@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,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal SOCKS5 CONNECT forwarder: listens on a local TCP port and pipes
|
|
3
|
+
* each client connection through a SOCKS5 proxy (no-auth) to a fixed target.
|
|
4
|
+
*
|
|
5
|
+
* Presents the same plain `localhost:PORT` contract the SSM tunnels give today,
|
|
6
|
+
* so an app (e.g. a Temporal gRPC client) connects with no proxy awareness —
|
|
7
|
+
* the SOCKS5 proxy is the userspace-Tailscale daemon (MESH-2040 / MESH-2036).
|
|
8
|
+
*/
|
|
9
|
+
import * as net from "node:net";
|
|
10
|
+
/** `"10.0.137.203"` → `[10,0,137,203]`; throws on anything that isn't IPv4. */
|
|
11
|
+
export declare function ipv4ToBytes(ip: string): number[];
|
|
12
|
+
/** SOCKS5 CONNECT request for an IPv4 target (VER, CMD=CONNECT, RSV, ATYP=IPv4, addr, port). */
|
|
13
|
+
export declare function socks5ConnectRequest(ip: string, port: number): Buffer;
|
|
14
|
+
/** Interpret the SOCKS5 reply code (byte 1 of the CONNECT reply). */
|
|
15
|
+
export declare function interpretSocksReply(code: number): {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
message: string;
|
|
18
|
+
};
|
|
19
|
+
export interface ForwarderOptions {
|
|
20
|
+
/** Local TCP port to listen on (0 = ephemeral, useful in tests). */
|
|
21
|
+
listenPort: number;
|
|
22
|
+
socksHost?: string;
|
|
23
|
+
socksPort: number;
|
|
24
|
+
targetIp: string;
|
|
25
|
+
targetPort: number;
|
|
26
|
+
/**
|
|
27
|
+
* Observes server errors — above all a bind failure (`EADDRINUSE`). The
|
|
28
|
+
* forwarder still never crashes the process, but the error must not be
|
|
29
|
+
* INVISIBLE: an unbound forwarder whose port is held by a foreign process is
|
|
30
|
+
* the silent-dead-tunnel class (MESH-2407), so callers record it and the
|
|
31
|
+
* ownership handshake reports the port as not-listening.
|
|
32
|
+
*/
|
|
33
|
+
onError?: (err: NodeJS.ErrnoException) => void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Create (and start) a forwarder server. Each inbound client is spliced to
|
|
37
|
+
* `targetIp:targetPort` via a SOCKS5 CONNECT through `socksHost:socksPort`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createForwarder(opts: ForwarderOptions): net.Server;
|
|
40
|
+
//# sourceMappingURL=socks-forward.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socks-forward.d.ts","sourceRoot":"","sources":["../../../src/utils/socks-forward.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAUhD;AAED,gGAAgG;AAChG,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErE;AAcD,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAElF;AAED,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,KAAK,IAAI,CAAC;CAChD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,GAAG,CAAC,MAAM,CA8ClE"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal SOCKS5 CONNECT forwarder: listens on a local TCP port and pipes
|
|
3
|
+
* each client connection through a SOCKS5 proxy (no-auth) to a fixed target.
|
|
4
|
+
*
|
|
5
|
+
* Presents the same plain `localhost:PORT` contract the SSM tunnels give today,
|
|
6
|
+
* so an app (e.g. a Temporal gRPC client) connects with no proxy awareness —
|
|
7
|
+
* the SOCKS5 proxy is the userspace-Tailscale daemon (MESH-2040 / MESH-2036).
|
|
8
|
+
*/
|
|
9
|
+
import * as net from "node:net";
|
|
10
|
+
/** `"10.0.137.203"` → `[10,0,137,203]`; throws on anything that isn't IPv4. */
|
|
11
|
+
export function ipv4ToBytes(ip) {
|
|
12
|
+
const parts = ip.split(".");
|
|
13
|
+
if (parts.length !== 4)
|
|
14
|
+
throw new Error(`not an IPv4 address: ${ip}`);
|
|
15
|
+
return parts.map((p) => {
|
|
16
|
+
const n = Number(p);
|
|
17
|
+
if (!Number.isInteger(n) || n < 0 || n > 255 || !/^\d+$/.test(p)) {
|
|
18
|
+
throw new Error(`not an IPv4 address: ${ip}`);
|
|
19
|
+
}
|
|
20
|
+
return n;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** SOCKS5 CONNECT request for an IPv4 target (VER, CMD=CONNECT, RSV, ATYP=IPv4, addr, port). */
|
|
24
|
+
export function socks5ConnectRequest(ip, port) {
|
|
25
|
+
return Buffer.from([0x05, 0x01, 0x00, 0x01, ...ipv4ToBytes(ip), (port >> 8) & 0xff, port & 0xff]);
|
|
26
|
+
}
|
|
27
|
+
const SOCKS_REPLY_MESSAGES = {
|
|
28
|
+
0: "succeeded",
|
|
29
|
+
1: "general SOCKS server failure",
|
|
30
|
+
2: "connection not allowed by ruleset",
|
|
31
|
+
3: "network unreachable",
|
|
32
|
+
4: "host unreachable",
|
|
33
|
+
5: "connection refused",
|
|
34
|
+
6: "TTL expired",
|
|
35
|
+
7: "command not supported",
|
|
36
|
+
8: "address type not supported",
|
|
37
|
+
};
|
|
38
|
+
/** Interpret the SOCKS5 reply code (byte 1 of the CONNECT reply). */
|
|
39
|
+
export function interpretSocksReply(code) {
|
|
40
|
+
return { ok: code === 0, message: SOCKS_REPLY_MESSAGES[code] ?? `unknown SOCKS reply ${code}` };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create (and start) a forwarder server. Each inbound client is spliced to
|
|
44
|
+
* `targetIp:targetPort` via a SOCKS5 CONNECT through `socksHost:socksPort`.
|
|
45
|
+
*/
|
|
46
|
+
export function createForwarder(opts) {
|
|
47
|
+
const socksHost = opts.socksHost ?? "127.0.0.1";
|
|
48
|
+
const server = net.createServer((client) => {
|
|
49
|
+
const up = net.connect(opts.socksPort, socksHost);
|
|
50
|
+
let buf = Buffer.alloc(0);
|
|
51
|
+
let phase = 0; // 0=await method-select, 1=await connect reply, 2=streaming
|
|
52
|
+
up.on("connect", () => up.write(Buffer.from([0x05, 0x01, 0x00]))); // greet, no-auth
|
|
53
|
+
up.on("data", (d) => {
|
|
54
|
+
if (phase === 2)
|
|
55
|
+
return;
|
|
56
|
+
buf = Buffer.concat([buf, d]);
|
|
57
|
+
if (phase === 0) {
|
|
58
|
+
if (buf.length < 2)
|
|
59
|
+
return;
|
|
60
|
+
buf = buf.subarray(2);
|
|
61
|
+
phase = 1;
|
|
62
|
+
up.write(socks5ConnectRequest(opts.targetIp, opts.targetPort));
|
|
63
|
+
}
|
|
64
|
+
if (phase === 1) {
|
|
65
|
+
if (buf.length < 10)
|
|
66
|
+
return;
|
|
67
|
+
const reply = interpretSocksReply(buf[1]);
|
|
68
|
+
const leftover = buf.subarray(10);
|
|
69
|
+
phase = 2;
|
|
70
|
+
if (!reply.ok) {
|
|
71
|
+
up.destroy();
|
|
72
|
+
client.destroy();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (leftover.length)
|
|
76
|
+
client.write(leftover);
|
|
77
|
+
client.pipe(up);
|
|
78
|
+
up.pipe(client);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
client.on("error", () => up.destroy());
|
|
82
|
+
up.on("error", () => client.destroy());
|
|
83
|
+
// A cleanly-closed client (clean FIN, no "error") must still tear down the
|
|
84
|
+
// upstream SOCKS→target leg — otherwise a probe that connects then closes
|
|
85
|
+
// strands a real VPC-target connection until the target times out.
|
|
86
|
+
client.on("close", () => up.destroy());
|
|
87
|
+
up.on("close", () => client.destroy());
|
|
88
|
+
});
|
|
89
|
+
// A bind failure (e.g. the port is already held by an SSM tunnel) must not
|
|
90
|
+
// crash the process running this forwarder — but it must be OBSERVED, not
|
|
91
|
+
// swallowed: the runner records it and ownership checks fail the port.
|
|
92
|
+
// Attach before listen() so the error is caught.
|
|
93
|
+
server.on("error", (err) => opts.onError?.(err));
|
|
94
|
+
server.listen(opts.listenPort, "127.0.0.1");
|
|
95
|
+
return server;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=socks-forward.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socks-forward.js","sourceRoot":"","sources":["../../../src/utils/socks-forward.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface StackSelector {
|
|
2
|
+
/** Canonical Pulumi stack name. */
|
|
3
|
+
stack?: string;
|
|
4
|
+
/** @deprecated SST-era alias for {@link StackSelector.stack}; still accepted. */
|
|
5
|
+
stage?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the stack selector, preferring the canonical `--stack` over the
|
|
9
|
+
* deprecated `--stage` alias. Pure: reports whether the deprecated alias supplied
|
|
10
|
+
* the value so the caller can warn. `--stack` wins when both are present.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveStackSelector(opts: StackSelector): {
|
|
13
|
+
stack: string | undefined;
|
|
14
|
+
usedDeprecatedStage: boolean;
|
|
15
|
+
};
|
|
16
|
+
/** Test-only: reset the once-per-process deprecation-warning latch. */
|
|
17
|
+
export declare function resetStackFlagWarning(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve `--stack`/`--stage` to the effective stack for use at a consumption
|
|
20
|
+
* site, warning ONCE per process when the deprecated `--stage` alias supplied it.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveStackOption(opts: StackSelector): string | undefined;
|
|
23
|
+
//# sourceMappingURL=stack-flag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-flag.d.ts","sourceRoot":"","sources":["../../../src/utils/stack-flag.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG;IACzD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAIA;AAID,uEAAuE;AACvE,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAS1E"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack-selection flag resolution (MESH-2154).
|
|
3
|
+
*
|
|
4
|
+
* `mesh` subcommands historically disagreed on the stack-selection flag:
|
|
5
|
+
* `deploy`/`cluster` use `--stack` (Pulumi-native), while `dev`/`secrets` used
|
|
6
|
+
* `--stage` (the SST-era term the platform has moved off). So `mesh kubectl
|
|
7
|
+
* --stage dev` and `mesh dev --stack …` each errored on muscle memory. We
|
|
8
|
+
* consolidate on `--stack` everywhere and keep `--stage` as a HIDDEN, deprecated
|
|
9
|
+
* alias that still works but warns — removable after a transition window.
|
|
10
|
+
*/
|
|
11
|
+
import { logWarn } from './log.js';
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the stack selector, preferring the canonical `--stack` over the
|
|
14
|
+
* deprecated `--stage` alias. Pure: reports whether the deprecated alias supplied
|
|
15
|
+
* the value so the caller can warn. `--stack` wins when both are present.
|
|
16
|
+
*/
|
|
17
|
+
export function resolveStackSelector(opts) {
|
|
18
|
+
if (opts.stack != null)
|
|
19
|
+
return { stack: opts.stack, usedDeprecatedStage: false };
|
|
20
|
+
if (opts.stage != null)
|
|
21
|
+
return { stack: opts.stage, usedDeprecatedStage: true };
|
|
22
|
+
return { stack: undefined, usedDeprecatedStage: false };
|
|
23
|
+
}
|
|
24
|
+
let warnedOnce = false;
|
|
25
|
+
/** Test-only: reset the once-per-process deprecation-warning latch. */
|
|
26
|
+
export function resetStackFlagWarning() {
|
|
27
|
+
warnedOnce = false;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve `--stack`/`--stage` to the effective stack for use at a consumption
|
|
31
|
+
* site, warning ONCE per process when the deprecated `--stage` alias supplied it.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveStackOption(opts) {
|
|
34
|
+
const { stack, usedDeprecatedStage } = resolveStackSelector(opts);
|
|
35
|
+
if (usedDeprecatedStage && !warnedOnce) {
|
|
36
|
+
warnedOnce = true;
|
|
37
|
+
logWarn('--stage is deprecated; use --stack (the Pulumi-native name). --stage still works for now.');
|
|
38
|
+
}
|
|
39
|
+
return stack;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=stack-flag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-flag.js","sourceRoot":"","sources":["../../../src/utils/stack-flag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AASnC;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAmB;IAItD,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC;IACjF,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC;IAChF,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC;AAC1D,CAAC;AAED,IAAI,UAAU,GAAG,KAAK,CAAC;AAEvB,uEAAuE;AACvE,MAAM,UAAU,qBAAqB;IACnC,UAAU,GAAG,KAAK,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAmB;IACpD,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAClE,IAAI,mBAAmB,IAAI,CAAC,UAAU,EAAE,CAAC;QACvC,UAAU,GAAG,IAAI,CAAC;QAClB,OAAO,CACL,2FAA2F,CAC5F,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a tenant's VPC tunnel targets from the platform bastion's service
|
|
3
|
+
* map — the same source `startSsmTunnels` reads — mapping bastion service keys
|
|
4
|
+
* to the app's tunnel names, resolving each ELB/RDS hostname to its private IP,
|
|
5
|
+
* and assigning collision-free localhost ports via the SSM port convention.
|
|
6
|
+
* (MESH-2040 / Slice 1 of MESH-2014.)
|
|
7
|
+
*/
|
|
8
|
+
/** Local-port block width per tenant — wider than the canonical port span so
|
|
9
|
+
* two tenants' port blocks never overlap. */
|
|
10
|
+
export declare const PORT_BLOCK = 3000;
|
|
11
|
+
/**
|
|
12
|
+
* Deterministic per-tenant index for local-port offsetting. Reads a machine-global
|
|
13
|
+
* registry (`~/.config/mesh/tailscale/port-registry.json`), seeded `{ mesh: 0 }` so
|
|
14
|
+
* the hub's canonical ports are grandfathered regardless of registration order.
|
|
15
|
+
* Assigns the next index to an unseen tenant and persists it. `registryPath` is
|
|
16
|
+
* injectable for tests.
|
|
17
|
+
*/
|
|
18
|
+
export declare function tenantPortIndex(tenant: string, registryPath?: string): number;
|
|
19
|
+
export interface TunnelTarget {
|
|
20
|
+
/** App-facing tunnel name (e.g. "temporal"). */
|
|
21
|
+
name: string;
|
|
22
|
+
/** Local port the forwarder listens on (SSM convention: base + remotePort). */
|
|
23
|
+
localPort: number;
|
|
24
|
+
/** VPC hostname (internal ELB / RDS endpoint). */
|
|
25
|
+
targetHost: string;
|
|
26
|
+
/** Resolved private IP of `targetHost`. */
|
|
27
|
+
targetIp: string;
|
|
28
|
+
/** Port on the VPC service. */
|
|
29
|
+
remotePort: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Bastion service key → app tunnel name. Mirrors `tunnelToBastionKey` in dev.ts
|
|
33
|
+
* (inverted): the bastion exposes `temporal-frontend`; the app calls it `temporal`.
|
|
34
|
+
*/
|
|
35
|
+
export declare const TUNNEL_NAME_BY_BASTION_KEY: Record<string, string>;
|
|
36
|
+
/**
|
|
37
|
+
* Build the tunnel target set. `resolveIp` is injected for testability (the
|
|
38
|
+
* command passes `resolveElbIp`). Services not in the name map are skipped;
|
|
39
|
+
* services whose host can't be resolved are skipped (the forwarder needs an IP).
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveTunnelTargets(services: Record<string, {
|
|
42
|
+
host: string;
|
|
43
|
+
port: number;
|
|
44
|
+
}>, resolveIp: (host: string) => string | null, portOffset?: number): TunnelTarget[];
|
|
45
|
+
/**
|
|
46
|
+
* Resolve an AWS-internal ELB/RDS hostname to its private IP via a public
|
|
47
|
+
* resolver — these names publish their private (10.x) address to public DNS
|
|
48
|
+
* but the host's default resolver may not answer for them. Returns null on
|
|
49
|
+
* failure (caller skips that tunnel).
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveElbIp(host: string): string | null;
|
|
52
|
+
//# sourceMappingURL=tailscale-targets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tailscale-targets.d.ts","sourceRoot":"","sources":["../../../src/utils/tailscale-targets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH;6CAC6C;AAC7C,eAAO,MAAM,UAAU,OAAO,CAAC;AAE/B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAc7E;AAED,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAI7D,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACxD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,EAC1C,UAAU,SAAI,GACb,YAAY,EAAE,CAiBhB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAexD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a tenant's VPC tunnel targets from the platform bastion's service
|
|
3
|
+
* map — the same source `startSsmTunnels` reads — mapping bastion service keys
|
|
4
|
+
* to the app's tunnel names, resolving each ELB/RDS hostname to its private IP,
|
|
5
|
+
* and assigning collision-free localhost ports via the SSM port convention.
|
|
6
|
+
* (MESH-2040 / Slice 1 of MESH-2014.)
|
|
7
|
+
*/
|
|
8
|
+
import { execFileSync } from "node:child_process";
|
|
9
|
+
import * as fs from "node:fs";
|
|
10
|
+
import * as path from "node:path";
|
|
11
|
+
import { reserveSsmLocalPortCandidate, preferredSsmLocalPort } from "../commands/dev.js";
|
|
12
|
+
import { CONFIG_DIR, atomicWriteFileSync } from "../commands/login.js";
|
|
13
|
+
/** Local-port block width per tenant — wider than the canonical port span so
|
|
14
|
+
* two tenants' port blocks never overlap. */
|
|
15
|
+
export const PORT_BLOCK = 3000;
|
|
16
|
+
/**
|
|
17
|
+
* Deterministic per-tenant index for local-port offsetting. Reads a machine-global
|
|
18
|
+
* registry (`~/.config/mesh/tailscale/port-registry.json`), seeded `{ mesh: 0 }` so
|
|
19
|
+
* the hub's canonical ports are grandfathered regardless of registration order.
|
|
20
|
+
* Assigns the next index to an unseen tenant and persists it. `registryPath` is
|
|
21
|
+
* injectable for tests.
|
|
22
|
+
*/
|
|
23
|
+
export function tenantPortIndex(tenant, registryPath) {
|
|
24
|
+
const p = registryPath ?? path.join(CONFIG_DIR, "tailscale", "port-registry.json");
|
|
25
|
+
let reg;
|
|
26
|
+
try {
|
|
27
|
+
reg = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
reg = { mesh: 0 };
|
|
31
|
+
}
|
|
32
|
+
if (tenant in reg)
|
|
33
|
+
return reg[tenant];
|
|
34
|
+
const idx = Math.max(-1, ...Object.values(reg)) + 1;
|
|
35
|
+
reg[tenant] = idx;
|
|
36
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
37
|
+
atomicWriteFileSync(p, JSON.stringify(reg, null, 2), 0o600);
|
|
38
|
+
return idx;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Bastion service key → app tunnel name. Mirrors `tunnelToBastionKey` in dev.ts
|
|
42
|
+
* (inverted): the bastion exposes `temporal-frontend`; the app calls it `temporal`.
|
|
43
|
+
*/
|
|
44
|
+
export const TUNNEL_NAME_BY_BASTION_KEY = {
|
|
45
|
+
"temporal-frontend": "temporal",
|
|
46
|
+
"temporal-ui": "temporal-ui",
|
|
47
|
+
rds: "rds",
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Build the tunnel target set. `resolveIp` is injected for testability (the
|
|
51
|
+
* command passes `resolveElbIp`). Services not in the name map are skipped;
|
|
52
|
+
* services whose host can't be resolved are skipped (the forwarder needs an IP).
|
|
53
|
+
*/
|
|
54
|
+
export function resolveTunnelTargets(services, resolveIp, portOffset = 0) {
|
|
55
|
+
const reserved = new Set();
|
|
56
|
+
const targets = [];
|
|
57
|
+
for (const [key, svc] of Object.entries(services)) {
|
|
58
|
+
const name = TUNNEL_NAME_BY_BASTION_KEY[key];
|
|
59
|
+
if (!name)
|
|
60
|
+
continue;
|
|
61
|
+
const targetIp = resolveIp(svc.host);
|
|
62
|
+
if (!targetIp)
|
|
63
|
+
continue;
|
|
64
|
+
// Per-tenant offset keeps concurrent platform tenants off each other's ports.
|
|
65
|
+
const localPort = reserveSsmLocalPortCandidate(svc.port, reserved, preferredSsmLocalPort(svc.port) + portOffset);
|
|
66
|
+
targets.push({ name, localPort, targetHost: svc.host, targetIp, remotePort: svc.port });
|
|
67
|
+
}
|
|
68
|
+
return targets;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Resolve an AWS-internal ELB/RDS hostname to its private IP via a public
|
|
72
|
+
* resolver — these names publish their private (10.x) address to public DNS
|
|
73
|
+
* but the host's default resolver may not answer for them. Returns null on
|
|
74
|
+
* failure (caller skips that tunnel).
|
|
75
|
+
*/
|
|
76
|
+
export function resolveElbIp(host) {
|
|
77
|
+
try {
|
|
78
|
+
const out = execFileSync("dig", ["+short", host, "@1.1.1.1"], {
|
|
79
|
+
encoding: "utf8",
|
|
80
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
81
|
+
});
|
|
82
|
+
const ip = out
|
|
83
|
+
.trim()
|
|
84
|
+
.split("\n")
|
|
85
|
+
.map((l) => l.trim())
|
|
86
|
+
.find((l) => /^\d+\.\d+\.\d+\.\d+$/.test(l));
|
|
87
|
+
return ip ?? null;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=tailscale-targets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tailscale-targets.js","sourceRoot":"","sources":["../../../src/utils/tailscale-targets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Userspace-Tailscale daemon management + tunnel-session state for
|
|
3
|
+
* `mesh vpn tunnel` (MESH-2040 / Slice 1 of MESH-2014).
|
|
4
|
+
*
|
|
5
|
+
* A per-tenant `tailscaled` runs in userspace-networking mode (brew formula,
|
|
6
|
+
* NOT the GUI app) exposing a SOCKS5 proxy; forwarders bridge `localhost:PORT`
|
|
7
|
+
* to VPC services through it. State lives under `~/.config/mesh/tailscale/<tenant>/`
|
|
8
|
+
* (r+w-granted under safehouse — see the MESH-2036 spike).
|
|
9
|
+
*/
|
|
10
|
+
import type { PidSource } from "./pid.js";
|
|
11
|
+
import type { OwnershipCheck } from "./tunnel-ownership.js";
|
|
12
|
+
import type { TunnelTarget } from "./tailscale-targets.js";
|
|
13
|
+
import type { DevOutput } from "../commands/dev.js";
|
|
14
|
+
export declare function tenantStateDir(tenant: string): string;
|
|
15
|
+
export declare function socketPath(tenant: string): string;
|
|
16
|
+
export declare function logPath(tenant: string): string;
|
|
17
|
+
export declare function statePath(tenant: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Daemon-scoped metadata, written by `ensureDaemon` when it actually spawns the
|
|
20
|
+
* daemon. Unlike `tunnel-state.json` (which `down` clears), this survives `down`
|
|
21
|
+
* so a later `up` reuses the RUNNING daemon's SOCKS port instead of minting a
|
|
22
|
+
* fresh one the daemon isn't listening on (which would leave every forwarder
|
|
23
|
+
* dialing a dead port). Also records the daemon pid so `stopDaemon` can kill it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function daemonMetaPath(tenant: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Ownership manifest written by the RUNNER (the process that binds the
|
|
28
|
+
* forwarder ports) — pid, process-group id, per-run token, control port. The
|
|
29
|
+
* ownership handshake (MESH-2407) verifies against it; teardown signals the
|
|
30
|
+
* recorded process group.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runnerManifestPath(tenant: string): string;
|
|
33
|
+
export interface TunnelState {
|
|
34
|
+
tenant: string;
|
|
35
|
+
env: string;
|
|
36
|
+
socksPort: number;
|
|
37
|
+
loginServer: string;
|
|
38
|
+
/** PID of the detached forwarder supervisor (null until spawned). */
|
|
39
|
+
supervisorPid: number | null;
|
|
40
|
+
/** How the runner is supervised. Defaults to "detached" when absent. */
|
|
41
|
+
managed?: "launchd" | "detached";
|
|
42
|
+
startedAt: string;
|
|
43
|
+
tunnels: TunnelTarget[];
|
|
44
|
+
}
|
|
45
|
+
export declare function readTunnelState(tenant: string): TunnelState | null;
|
|
46
|
+
export declare function writeTunnelState(tenant: string, state: TunnelState): void;
|
|
47
|
+
export declare function clearTunnelState(tenant: string): void;
|
|
48
|
+
export interface DaemonMeta {
|
|
49
|
+
/** The `--socks5-server` port the running daemon actually listens on. */
|
|
50
|
+
socksPort: number;
|
|
51
|
+
/** PID of the detached `tailscaled` process (for `stopDaemon`). */
|
|
52
|
+
pid: number;
|
|
53
|
+
}
|
|
54
|
+
export declare function readDaemonMeta(tenant: string): DaemonMeta | null;
|
|
55
|
+
export declare function writeDaemonMeta(tenant: string, meta: DaemonMeta): void;
|
|
56
|
+
export declare function clearDaemonMeta(tenant: string): void;
|
|
57
|
+
/** Parse `tailscale status --json` → the fields we care about. */
|
|
58
|
+
export declare function parseDaemonState(statusJson: string): {
|
|
59
|
+
backendState: string;
|
|
60
|
+
selfName?: string;
|
|
61
|
+
};
|
|
62
|
+
/** The brew `tailscaled` (NOT the GUI app, which ships no standalone daemon). */
|
|
63
|
+
export declare function tailscaledBinPath(): string;
|
|
64
|
+
/** The brew `tailscale` CLI (prefer it over the GUI shim, which aborts under sandbox). */
|
|
65
|
+
export declare function tailscaleBinPath(): string;
|
|
66
|
+
/** Backend state via the tenant's control socket; "Down" when no daemon answers. */
|
|
67
|
+
export declare function daemonState(tenant: string): {
|
|
68
|
+
backendState: string;
|
|
69
|
+
selfName?: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Extract the `--socks5-server` port from a `tailscaled` command line. Pure so
|
|
73
|
+
* it's unit-testable. Accepts both `--socks5-server=127.0.0.1:PORT` and the
|
|
74
|
+
* space-separated form, and a `localhost` host literal. Returns null if absent
|
|
75
|
+
* or malformed.
|
|
76
|
+
*/
|
|
77
|
+
export declare function parseSocksPortFromArgv(argv: string): number | null;
|
|
78
|
+
/**
|
|
79
|
+
* Find the running userspace `tailscaled` for a tenant by its unique
|
|
80
|
+
* `--socket=<path>` argument, returning its pid and the SOCKS port it ACTUALLY
|
|
81
|
+
* bound (parsed from argv). Authoritative when `daemon.json` is missing or stale
|
|
82
|
+
* (e.g. a daemon left by an older build that predates the meta file). Returns
|
|
83
|
+
* null when no matching process is found or `ps` is unavailable.
|
|
84
|
+
*/
|
|
85
|
+
export declare function findRunningDaemon(tenant: string): {
|
|
86
|
+
pid: number;
|
|
87
|
+
socksPort: number | null;
|
|
88
|
+
} | null;
|
|
89
|
+
/** True if something accepts TCP on 127.0.0.1:port within `timeoutMs`. */
|
|
90
|
+
export declare function portAccepts(port: number, timeoutMs?: number): Promise<boolean>;
|
|
91
|
+
/**
|
|
92
|
+
* Ensure a userspace `tailscaled` is running for the tenant and return the SOCKS
|
|
93
|
+
* port the forwarders should dial. Idempotent — reuses a live daemon, but
|
|
94
|
+
* RECONCILES the port: a daemon that's up on a different port than requested
|
|
95
|
+
* (older build with no `daemon.json`, or stale meta) would otherwise leave every
|
|
96
|
+
* forwarder dialing a dead port (MESH-2169). Trust `opts.socksPort` only if it
|
|
97
|
+
* truly accepts; else adopt the running daemon's real port; else restart fresh.
|
|
98
|
+
*/
|
|
99
|
+
export declare function ensureDaemon(tenant: string, opts: {
|
|
100
|
+
region: string;
|
|
101
|
+
socksPort: number;
|
|
102
|
+
}): Promise<number>;
|
|
103
|
+
/**
|
|
104
|
+
* Stop the detached `tailscaled` for a tenant (SIGTERM its pid) and remove the
|
|
105
|
+
* socket + daemon metadata. Leaves the Headscale node identity in `tailscaled.state`
|
|
106
|
+
* so a later `up` re-spawns and rejoins without an interactive re-login — unless
|
|
107
|
+
* the caller logged out first.
|
|
108
|
+
*
|
|
109
|
+
* Best-effort, and that includes a corrupt `daemon.json`: an unsignalable
|
|
110
|
+
* recorded pid is REFUSED (never handed to `kill`) but only warns — the socket
|
|
111
|
+
* and meta are still cleared. `ensureDaemon` calls this on the UP path to
|
|
112
|
+
* recycle a daemon it can't verify, so throwing here would dead-end
|
|
113
|
+
* `mesh vpn tunnel up` / `mesh dev` on the very file this function deletes.
|
|
114
|
+
* Safe to call when nothing is running.
|
|
115
|
+
*/
|
|
116
|
+
export declare function stopDaemon(tenant: string): void;
|
|
117
|
+
/**
|
|
118
|
+
* Build the `tailscale up` argument vector. Pure so it can be unit-tested and so
|
|
119
|
+
* the interactive (browser-register) and zero-touch (pre-auth key) forms differ
|
|
120
|
+
* only by the trailing `--authkey`.
|
|
121
|
+
*/
|
|
122
|
+
export declare function buildTailscaleUpArgs(opts: {
|
|
123
|
+
socket: string;
|
|
124
|
+
loginServer: string;
|
|
125
|
+
hostname: string;
|
|
126
|
+
preAuthKey?: string;
|
|
127
|
+
}): string[];
|
|
128
|
+
/**
|
|
129
|
+
* Join the tenant's Headscale tailnet via Zitadel OIDC if not already Running.
|
|
130
|
+
* Prints the device-flow registration URL and polls until registered. When a
|
|
131
|
+
* pre-auth key is supplied the join is non-interactive: no `/register/` URL is
|
|
132
|
+
* emitted, so the scrape/relay is skipped and we just wait for Running.
|
|
133
|
+
*/
|
|
134
|
+
export declare function joinHeadscale(tenant: string, loginServer: string, opts?: {
|
|
135
|
+
preAuthKey?: string;
|
|
136
|
+
}): Promise<void>;
|
|
137
|
+
/** Log the tenant daemon out of Headscale (disconnect). Daemon process persists. */
|
|
138
|
+
export declare function logout(tenant: string): void;
|
|
139
|
+
/**
|
|
140
|
+
* True iff two target sets are identical down to targetIp + remotePort. A live
|
|
141
|
+
* runner pins each forwarder's target at startup, so if the ELB IP rotated (or a
|
|
142
|
+
* port changed) the running forwarders point at a dead address and must be
|
|
143
|
+
* respawned, not reused. Pid-agnostic (a launchd runner records no supervisor pid).
|
|
144
|
+
*/
|
|
145
|
+
export declare function tunnelTargetsEqual(a: TunnelTarget[], b: TunnelTarget[]): boolean;
|
|
146
|
+
/** True iff `state` has a supervisor pid and its target set equals `targets`. */
|
|
147
|
+
export declare function supervisorTargetsMatch(state: TunnelState | null, targets: TunnelTarget[]): boolean;
|
|
148
|
+
/**
|
|
149
|
+
* SIGTERM the supervisor's whole process GROUP, not the bare pid.
|
|
150
|
+
*
|
|
151
|
+
* `state.supervisorPid` is the pid of the detached spawn — which, under the
|
|
152
|
+
* canonical source launcher, is `bin/mesh.mjs`. That launcher blocks in
|
|
153
|
+
* `execFileSync` around the *real* runner (a `node --import tsx … mesh.ts`
|
|
154
|
+
* grandchild that actually binds the forwarder ports), and `execFileSync` does
|
|
155
|
+
* not forward signals. So signalling the bare pid kills only the launcher and
|
|
156
|
+
* ORPHANS the runner, which keeps its ports bound — the orphan then answers
|
|
157
|
+
* `allForwardersListening`'s ownership-less liveness dial and silently pins
|
|
158
|
+
* every tunnel to a stale target (the MESH-2169 / MESH-2014 failure class).
|
|
159
|
+
*
|
|
160
|
+
* The launcher is spawned `detached: true`, so it is a process-group leader
|
|
161
|
+
* (`pgid === pid`); `process.kill(-pid, …)` reaps the launcher and the runner
|
|
162
|
+
* together. Falls back to the bare pid for a legacy state file whose pid was
|
|
163
|
+
* not a group leader, and tolerates ESRCH (already gone).
|
|
164
|
+
*
|
|
165
|
+
* `pid` is always recovered — from `tunnel-state.json`, `runner.json`, or a
|
|
166
|
+
* `ps` scan — never constructed here, so it is guarded first. The guard rejects
|
|
167
|
+
* anything below 2, which is what makes the NEGATED form safe: `pid >= 2` ⇒
|
|
168
|
+
* `-pid <= -2`, a real process group, never `kill(0)` (this shell's own group)
|
|
169
|
+
* or `kill(-1)` (broadcast to everything the user can signal). See utils/pid.ts.
|
|
170
|
+
*
|
|
171
|
+
* @throws {MeshCliError} when `pid` is unsignalable. Callers reaping SEVERAL
|
|
172
|
+
* independently-recovered pids must catch per-pid (see `stopTunnelRunners`) —
|
|
173
|
+
* letting one refusal propagate would skip the other pids and leave a live
|
|
174
|
+
* runner holding ports.
|
|
175
|
+
*/
|
|
176
|
+
export declare function killSupervisor(pid: number, source?: PidSource): void;
|
|
177
|
+
/**
|
|
178
|
+
* The ownership handshake for a tenant's tunnel runner (MESH-2407): manifest →
|
|
179
|
+
* live pid → control endpoint → token + SOCKS port + port coverage. This is
|
|
180
|
+
* the ONLY readiness/reuse signal — a bare TCP dial proves a listener exists,
|
|
181
|
+
* not that it is ours, and adopting a foreign listener is exactly the
|
|
182
|
+
* silent-dead-tunnel class (MESH-2169 / MESH-2014 / #2991). As a bonus the
|
|
183
|
+
* handshake reads listening state from the runner's in-process servers, so it
|
|
184
|
+
* opens no SOCKS→VPC data connection the way port dials do.
|
|
185
|
+
*/
|
|
186
|
+
export declare function verifyTunnelOwnership(tenant: string, expected: {
|
|
187
|
+
socksPort: number;
|
|
188
|
+
ports: number[];
|
|
189
|
+
}): Promise<OwnershipCheck>;
|
|
190
|
+
/**
|
|
191
|
+
* Tear down EVERY runner we can attribute to the tenant: the recorded
|
|
192
|
+
* supervisor pid (as a process group — see `killSupervisor`), the launchd
|
|
193
|
+
* agent, the manifest's process group, and any `__run`/`__supervise` process
|
|
194
|
+
* discovered from argv (a runner from an older build, or one whose state file
|
|
195
|
+
* was lost). This is the single teardown path — the #2991 lesson generalized:
|
|
196
|
+
* no kill path may leave a grandchild with ports still bound.
|
|
197
|
+
*/
|
|
198
|
+
export declare function stopTunnelRunners(tenant: string, prior: TunnelState | null): void;
|
|
199
|
+
/**
|
|
200
|
+
* Ensure the per-tenant forwarder supervisor is running for `state.tunnels`.
|
|
201
|
+
* Idempotent: reuses a live runner ONLY when it passes the ownership handshake
|
|
202
|
+
* (our manifest token, our SOCKS port, every target port listening in-process);
|
|
203
|
+
* otherwise tears down every attributable runner, verifies the ports actually
|
|
204
|
+
* freed (a still-held port is a foreign squatter → loud failure, never spawn
|
|
205
|
+
* over it), and (re)spawns a fresh runner — whose readiness is again the
|
|
206
|
+
* handshake, not a bare port dial. Persists the state and returns the pid.
|
|
207
|
+
*/
|
|
208
|
+
export declare function ensureForwarders(state: TunnelState): Promise<number>;
|
|
209
|
+
/**
|
|
210
|
+
* Rewrite `devOutput.tunnels` so each resolved target points at its local
|
|
211
|
+
* forwarder (`localhost:localPort`) — the same shape `startSsmTunnels`
|
|
212
|
+
* produces. Unmatched tunnels are left untouched. Pure (no mutation of input).
|
|
213
|
+
*/
|
|
214
|
+
export declare function rewriteTunnelsForTargets(devOutput: DevOutput, targets: TunnelTarget[]): DevOutput;
|
|
215
|
+
/** True when the brew `tailscaled` binary is resolvable (Tailscale transport is usable). */
|
|
216
|
+
export declare function tailscaleAvailable(): boolean;
|
|
217
|
+
/**
|
|
218
|
+
* Ensure the tenant's Tailscale tunnels are fully up: the shared per-tenant
|
|
219
|
+
* daemon (started + OIDC-joined if needed), the resolved VPC targets, and the
|
|
220
|
+
* forwarder supervisor. Idempotent (shared across worktrees/invocations of the
|
|
221
|
+
* same tenant). Returns the resolved targets. Used by both `mesh vpn tunnel up`
|
|
222
|
+
* and `mesh dev --transport=tailscale`.
|
|
223
|
+
*/
|
|
224
|
+
export declare function ensureTailscaleTunnels(tenant: string, env: string, opts: {
|
|
225
|
+
region: string;
|
|
226
|
+
loginServer: string;
|
|
227
|
+
socksPort: number;
|
|
228
|
+
preAuthKey?: string;
|
|
229
|
+
}): Promise<TunnelTarget[]>;
|
|
230
|
+
/**
|
|
231
|
+
* `startSsmTunnels` drop-in for `mesh dev`: ensure the tenant's Tailscale
|
|
232
|
+
* tunnels, then rewrite `devOutput.tunnels` to the local forwarder ports.
|
|
233
|
+
*/
|
|
234
|
+
export declare function startTailscaleTunnels(devOutput: DevOutput, ctx: {
|
|
235
|
+
tenant: string;
|
|
236
|
+
env: string;
|
|
237
|
+
region: string;
|
|
238
|
+
loginServer: string;
|
|
239
|
+
socksPort: number;
|
|
240
|
+
preAuthKey?: string;
|
|
241
|
+
}): Promise<DevOutput>;
|
|
242
|
+
export declare function launchAgentLabel(tenant: string): string;
|
|
243
|
+
/** Render the per-tenant LaunchAgent plist (pure). */
|
|
244
|
+
export declare function renderLaunchAgentPlist(args: {
|
|
245
|
+
tenant: string;
|
|
246
|
+
meshBin: string;
|
|
247
|
+
nodeBin: string;
|
|
248
|
+
logPath: string;
|
|
249
|
+
/** PATH for the agent — must include the dir of `tailscaled` so daemon reheal
|
|
250
|
+
* works under launchd's minimal PATH (esp. Intel `/usr/local/bin`). */
|
|
251
|
+
pathEnv?: string;
|
|
252
|
+
}): string;
|
|
253
|
+
/** Targets whose local forwarder port isn't currently accepting connections. */
|
|
254
|
+
export declare function forwardersNeedingRebind(targets: TunnelTarget[], listening: Set<number>): TunnelTarget[];
|
|
255
|
+
export declare function launchAgentPath(tenant: string): string;
|
|
256
|
+
/** True when launchctl works for this user (blocked under the seatbelt sandbox → false). */
|
|
257
|
+
export declare function launchdAvailable(): boolean;
|
|
258
|
+
/**
|
|
259
|
+
* Write + (re)load the per-tenant LaunchAgent. Returns true iff it fully
|
|
260
|
+
* succeeded — any failure (plist write blocked by the sandbox, `launchctl`
|
|
261
|
+
* bootstrap denied, …) returns false so the caller falls back to a detached
|
|
262
|
+
* runner. Never throws.
|
|
263
|
+
*/
|
|
264
|
+
export declare function installLaunchAgent(tenant: string, meshBin: string): boolean;
|
|
265
|
+
/** Unload + remove the per-tenant LaunchAgent (best-effort). */
|
|
266
|
+
export declare function uninstallLaunchAgent(tenant: string): void;
|
|
267
|
+
/**
|
|
268
|
+
* Long-lived runner for a tenant's tunnels — used both under launchd and as the
|
|
269
|
+
* detached fallback. Runs a forwarder per target and, every ~5s, self-heals:
|
|
270
|
+
* respawns the daemon if its process died, and rebinds any forwarder whose port
|
|
271
|
+
* stopped listening. As the process that actually binds the ports, it is the
|
|
272
|
+
* sole author of the ownership manifest + control endpoint (MESH-2407) that
|
|
273
|
+
* callers verify against. Needs no AWS (targets come from tunnel-state). Never
|
|
274
|
+
* returns.
|
|
275
|
+
*/
|
|
276
|
+
export declare function runTunnels(tenant: string): Promise<never>;
|
|
277
|
+
//# sourceMappingURL=tailscale.d.ts.map
|