@mesh-tech/mesh-cli 0.1.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +20826 -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 +21 -0
- package/dist/src/commands/install-shim.d.ts.map +1 -0
- package/dist/src/commands/install-shim.js +132 -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 +4 -0
- package/dist/src/commands/secrets/set.d.ts.map +1 -1
- package/dist/src/commands/secrets/set.js +243 -64
- 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 +35 -21
- 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,73 @@
|
|
|
1
|
+
# Local OTel Collector — the SAME ingestion topology the hosted platform runs
|
|
2
|
+
# (OpenTelemetryStack: collector → Loki via OTLP, → Tempo via OTLP gRPC,
|
|
3
|
+
# metrics scraped by Prometheus). Locally the k8sattributes processor's job —
|
|
4
|
+
# stamping k8s.namespace.name / k8s.deployment.name / k8s.container.name on
|
|
5
|
+
# every record — is done at the edges instead:
|
|
6
|
+
# - filelog: derives them from the log path
|
|
7
|
+
# /var/log/mesh-apps/{namespace}/{service}.log (written by
|
|
8
|
+
# `mesh dev --local`, namespace = {tenant}-{env}-{app})
|
|
9
|
+
# - otlp: apps send OTEL_RESOURCE_ATTRIBUTES injected by `mesh dev --local`
|
|
10
|
+
# so hub-api's LogQL/TraceQL queries run UNCHANGED against local data.
|
|
11
|
+
receivers:
|
|
12
|
+
otlp:
|
|
13
|
+
protocols:
|
|
14
|
+
grpc:
|
|
15
|
+
endpoint: 0.0.0.0:4317
|
|
16
|
+
http:
|
|
17
|
+
endpoint: 0.0.0.0:4318
|
|
18
|
+
filelog:
|
|
19
|
+
include:
|
|
20
|
+
- /var/log/mesh-apps/*/*.log
|
|
21
|
+
start_at: beginning
|
|
22
|
+
include_file_path: true
|
|
23
|
+
operators:
|
|
24
|
+
- type: regex_parser
|
|
25
|
+
parse_from: attributes["log.file.path"]
|
|
26
|
+
regex: '^/var/log/mesh-apps/(?P<mesh_namespace>[^/]+)/(?P<mesh_service>[^/]+)\.log$'
|
|
27
|
+
- type: move
|
|
28
|
+
from: attributes.mesh_namespace
|
|
29
|
+
to: resource["k8s.namespace.name"]
|
|
30
|
+
- type: move
|
|
31
|
+
from: attributes.mesh_service
|
|
32
|
+
to: resource["k8s.deployment.name"]
|
|
33
|
+
- type: copy
|
|
34
|
+
from: resource["k8s.deployment.name"]
|
|
35
|
+
to: resource["k8s.container.name"]
|
|
36
|
+
|
|
37
|
+
processors:
|
|
38
|
+
batch: {}
|
|
39
|
+
|
|
40
|
+
exporters:
|
|
41
|
+
# Same exporter shape as the hosted collector: Loki's native OTLP endpoint.
|
|
42
|
+
# Loki promotes k8s.namespace.name / k8s.deployment.name /
|
|
43
|
+
# k8s.container.name to index labels (k8s_namespace_name, …) by default.
|
|
44
|
+
otlphttp/loki:
|
|
45
|
+
endpoint: http://loki:3100/otlp
|
|
46
|
+
otlp/tempo:
|
|
47
|
+
endpoint: tempo:4317
|
|
48
|
+
tls:
|
|
49
|
+
insecure: true
|
|
50
|
+
prometheus:
|
|
51
|
+
endpoint: 0.0.0.0:8889
|
|
52
|
+
resource_to_telemetry_conversion:
|
|
53
|
+
enabled: true
|
|
54
|
+
|
|
55
|
+
extensions:
|
|
56
|
+
health_check:
|
|
57
|
+
endpoint: 0.0.0.0:13133
|
|
58
|
+
|
|
59
|
+
service:
|
|
60
|
+
extensions: [health_check]
|
|
61
|
+
pipelines:
|
|
62
|
+
logs:
|
|
63
|
+
receivers: [otlp, filelog]
|
|
64
|
+
processors: [batch]
|
|
65
|
+
exporters: [otlphttp/loki]
|
|
66
|
+
traces:
|
|
67
|
+
receivers: [otlp]
|
|
68
|
+
processors: [batch]
|
|
69
|
+
exporters: [otlp/tempo]
|
|
70
|
+
metrics:
|
|
71
|
+
receivers: [otlp]
|
|
72
|
+
processors: [batch]
|
|
73
|
+
exporters: [prometheus]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Local Prometheus — scrapes the OTel collector's exporter so app metrics
|
|
2
|
+
# sent via OTLP land where hub-api's PROMETHEUS_URL queries expect them.
|
|
3
|
+
global:
|
|
4
|
+
scrape_interval: 15s
|
|
5
|
+
|
|
6
|
+
scrape_configs:
|
|
7
|
+
- job_name: otel-collector
|
|
8
|
+
static_configs:
|
|
9
|
+
- targets: ['otel-collector:8889']
|
|
10
|
+
|
|
11
|
+
# External-service health probes (blackbox exporter) — the hosted Probe-CR
|
|
12
|
+
# topology: targets + labels come from file_sd JSON written by the CLI
|
|
13
|
+
# (mesh dev --externals / ExternalService wiring); probe_success/probe_duration
|
|
14
|
+
# land with type/tenant/env/app/external_service labels, exactly what
|
|
15
|
+
# hub-api's health enrichment and uptime views query.
|
|
16
|
+
- job_name: external-services
|
|
17
|
+
metrics_path: /probe
|
|
18
|
+
params:
|
|
19
|
+
module: [http_2xx]
|
|
20
|
+
scrape_interval: 30s
|
|
21
|
+
file_sd_configs:
|
|
22
|
+
- files: ['/etc/prometheus/probes/*.json']
|
|
23
|
+
refresh_interval: 15s
|
|
24
|
+
relabel_configs:
|
|
25
|
+
- source_labels: [__address__]
|
|
26
|
+
target_label: __param_target
|
|
27
|
+
- source_labels: [__param_target]
|
|
28
|
+
target_label: instance
|
|
29
|
+
# Per-target module override: file_sd entries may carry a
|
|
30
|
+
# __probe_module label (e.g. tcp_connect for databases/SFTP, where an
|
|
31
|
+
# HTTP GET can never succeed); default stays http_2xx from params.
|
|
32
|
+
- source_labels: [__probe_module]
|
|
33
|
+
regex: (.+)
|
|
34
|
+
target_label: __param_module
|
|
35
|
+
- target_label: __address__
|
|
36
|
+
replacement: blackbox-exporter:9115
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Local Tempo — trace store behind the OTel collector, same backend the
|
|
2
|
+
# hosted platform runs. hub-api queries it via TEMPO_URL (http://tempo:3200).
|
|
3
|
+
server:
|
|
4
|
+
http_listen_port: 3200
|
|
5
|
+
|
|
6
|
+
distributor:
|
|
7
|
+
receivers:
|
|
8
|
+
otlp:
|
|
9
|
+
protocols:
|
|
10
|
+
grpc:
|
|
11
|
+
endpoint: 0.0.0.0:4317
|
|
12
|
+
http:
|
|
13
|
+
endpoint: 0.0.0.0:4318
|
|
14
|
+
|
|
15
|
+
storage:
|
|
16
|
+
trace:
|
|
17
|
+
backend: local
|
|
18
|
+
local:
|
|
19
|
+
path: /var/tempo/blocks
|
|
20
|
+
wal:
|
|
21
|
+
path: /var/tempo/wal
|
|
22
|
+
|
|
23
|
+
compactor:
|
|
24
|
+
compaction:
|
|
25
|
+
block_retention: 48h
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Local Development Temporal Dynamic Configuration
|
|
2
|
+
# Environment-specific settings for local development.
|
|
3
|
+
# NO authorization block here: the local stack runs Temporal open
|
|
4
|
+
# (TEMPORAL_AUTH_ENABLED=false in compose) and the seeder connects
|
|
5
|
+
# without a token — auth is exercised on deployed platforms only.
|
|
6
|
+
system.forceSearchAttributesCacheRefreshOnRead:
|
|
7
|
+
- value: true
|
|
8
|
+
constraints: {}
|
|
9
|
+
|
|
10
|
+
frontend.enableUpdateWorkflowExecution:
|
|
11
|
+
- value: true
|
|
12
|
+
constraints: {}
|
|
13
|
+
|
|
14
|
+
frontend.enableUpdateWorkflowExecutionAsyncAccepted:
|
|
15
|
+
- value: true
|
|
16
|
+
constraints: {}
|
|
17
|
+
|
|
18
|
+
system.enableEagerWorkflowStart:
|
|
19
|
+
- value: true
|
|
20
|
+
constraints: {}
|
|
21
|
+
|
|
22
|
+
system.enableActivityEagerExecution:
|
|
23
|
+
- value: true
|
|
24
|
+
constraints: {}
|
|
25
|
+
|
|
26
|
+
frontend.enableWorkerVersioningDataAPIs:
|
|
27
|
+
- value: true
|
|
28
|
+
constraints: {}
|
|
29
|
+
|
|
30
|
+
frontend.enableWorkerVersioningWorkflowAPIs:
|
|
31
|
+
- value: true
|
|
32
|
+
constraints: {}
|
|
33
|
+
|
|
34
|
+
frontend.enableWorkerVersioningRuleAPIs:
|
|
35
|
+
- value: true
|
|
36
|
+
constraints: {}
|
|
37
|
+
|
|
38
|
+
worker.buildIdScavengerEnabled:
|
|
39
|
+
- value: true
|
|
40
|
+
constraints: {}
|
|
41
|
+
|
|
42
|
+
frontend.enableExecuteMultiOperation:
|
|
43
|
+
- value: true
|
|
44
|
+
constraints: {}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Agent guidance — {{name}}
|
|
2
|
+
|
|
3
|
+
- Invoke the CLI as `pnpm mesh <cmd>` or (cwd-independent) `pnpm exec mesh <cmd>` —
|
|
4
|
+
a `"mesh"` script + the bundled `@mesh-tech/*` dep make both work after
|
|
5
|
+
`pnpm install`. For a bare `mesh` on PATH, run once: `pnpm exec mesh install-shim`.
|
|
6
|
+
- Operations are `mesh` commands, never raw `aws`/`pulumi`/`kubectl`:
|
|
7
|
+
`mesh start`, `mesh login local`, `mesh dev`, `mesh deploy`.
|
|
8
|
+
- The full local proof is in the README: 401 (no token) → 200 (`mesh login
|
|
9
|
+
local` token) → 403 (no grant) → `pnpm seed:authz` → 200.
|
|
10
|
+
- Authorization rules live ONLY in `api/src/schema.ts` (`defineSchema`);
|
|
11
|
+
routes enforce them with `m.require(resource, action)`. Never hand-roll
|
|
12
|
+
permission checks in route handlers.
|
|
13
|
+
- `spicedb-http-provider.ts` is a starter — swap for the first-party
|
|
14
|
+
provider when @mesh-tech/authz ships it.
|
|
15
|
+
- Pattern skills for authn/authz ship inside those packages (TanStack
|
|
16
|
+
Intent discovers them after `pnpm install`).
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# {{titleCase name}}
|
|
2
|
+
|
|
3
|
+
Platform-authenticated API: `@mesh-tech/authn` (Zitadel JWT) + `@mesh-tech/authz`
|
|
4
|
+
(schema-driven SpiceDB permissions). Three routes: open, authenticated,
|
|
5
|
+
permission-gated.
|
|
6
|
+
|
|
7
|
+
## Run it locally (no AWS, no VPN)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
mesh start # local platform (seeded Zitadel + SpiceDB)
|
|
11
|
+
mesh login local # sign in as dev@local.mesh / LocalDev1!
|
|
12
|
+
pnpm install
|
|
13
|
+
mesh dev # wires the api to the local platform
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Prove the auth planes (401 → 200 → 403 → 200)
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# open route — no token
|
|
20
|
+
curl -s http://localhost:3000/health
|
|
21
|
+
# → {"status":"ok"}
|
|
22
|
+
|
|
23
|
+
# authenticated route without a token → 401
|
|
24
|
+
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/me
|
|
25
|
+
# → 401
|
|
26
|
+
|
|
27
|
+
# with your mesh login token → 200
|
|
28
|
+
TOKEN=$(jq -r '.local.accessToken' ~/.config/mesh/credentials.json)
|
|
29
|
+
curl -s http://localhost:3000/api/me -H "Authorization: Bearer $TOKEN"
|
|
30
|
+
# → {"sub":"…","email":"dev@local.mesh"}
|
|
31
|
+
|
|
32
|
+
# permission-gated route before any grant → 403
|
|
33
|
+
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/report -H "Authorization: Bearer $TOKEN"
|
|
34
|
+
# → 403
|
|
35
|
+
|
|
36
|
+
# grant yourself report:view (writes the SpiceDB schema + relation) …
|
|
37
|
+
SUB=$(jq -r '.local.sub' ~/.config/mesh/credentials.json)
|
|
38
|
+
cd api && pnpm seed:authz -- "$SUB" && cd ..
|
|
39
|
+
|
|
40
|
+
# … now 200
|
|
41
|
+
curl -s http://localhost:3000/api/report -H "Authorization: Bearer $TOKEN"
|
|
42
|
+
# → {"id":"quarterly","title":"Quarterly Report",…}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Log in as `ops@local.mesh` instead and `/api/report` stays 403 — the grant
|
|
46
|
+
is per-subject, in SpiceDB, exactly like the deployed platform.
|
|
47
|
+
|
|
48
|
+
## Deploy to a tenant environment
|
|
49
|
+
|
|
50
|
+
The deployed Service runs behind the platform's oauth2-proxy sidecar
|
|
51
|
+
(`auth: { provider: "mesh", … }` in `index.ts`), which needs its own OIDC
|
|
52
|
+
client in the platform Zitadel:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
mesh login {{tenant}}.dev
|
|
56
|
+
pulumi config set {{name}}:authClientId <clientId>
|
|
57
|
+
pulumi config set --secret {{name}}:authClientSecret <clientSecret>
|
|
58
|
+
mesh deploy up --yes
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Layout
|
|
62
|
+
|
|
63
|
+
- `index.ts` — Pulumi program (`Service` with platform auth + `/health` open)
|
|
64
|
+
- `api/src/index.ts` — Hono app: authn middleware + authz `require()`
|
|
65
|
+
- `api/src/schema.ts` — the authorization schema (single source of truth)
|
|
66
|
+
- `api/src/spicedb-http-provider.ts` — starter `AuthzProvider` (HTTP API)
|
|
67
|
+
- `api/src/seed-authz.ts` — local schema write + grant
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}-api",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "tsx watch src/index.ts",
|
|
8
|
+
"start": "node dist/index.js",
|
|
9
|
+
"build": "esm-bundle src/index.ts --outfile dist/index.js",
|
|
10
|
+
"check-types": "tsc --noEmit",
|
|
11
|
+
"seed:authz": "tsx src/seed-authz.ts"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@mesh-tech/authn": "latest",
|
|
15
|
+
"@mesh-tech/authz": "latest",
|
|
16
|
+
"@opentelemetry/auto-instrumentations-node": "^0.78.0",
|
|
17
|
+
"@mesh-tech/sinks": "latest",
|
|
18
|
+
"hono": "^4.0.0",
|
|
19
|
+
"@hono/node-server": "^1.0.0",
|
|
20
|
+
"zod": "^4.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@mesh-tech/esm-bundle": "latest",
|
|
24
|
+
"@types/node": "^20.0.0",
|
|
25
|
+
"tsx": "^4.0.0",
|
|
26
|
+
"typescript": "^5.0.0"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{titleCase name}} API — platform auth on both planes.
|
|
3
|
+
*
|
|
4
|
+
* authn (@mesh-tech/authn): verifies Zitadel JWTs (zitadel-jwt scheme).
|
|
5
|
+
* authz (@mesh-tech/authz): schema-driven permission checks via SpiceDB.
|
|
6
|
+
*
|
|
7
|
+
* Routes:
|
|
8
|
+
* GET /health public (no token)
|
|
9
|
+
* GET /api/me authenticated (valid JWT → 200, none → 401)
|
|
10
|
+
* GET /api/report permission-gated (needs report:view via SpiceDB → else 403)
|
|
11
|
+
*
|
|
12
|
+
* Environment (mesh dev injects all of these — local or tethered):
|
|
13
|
+
* PORT, ZITADEL_ISSUER, SPICEDB_ENDPOINT, SPICEDB_PRESHARED_KEY
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { Hono } from "hono";
|
|
17
|
+
import { serve } from "@hono/node-server";
|
|
18
|
+
import { createAuthn } from "@mesh-tech/authn";
|
|
19
|
+
import { zitadelJwtScheme } from "@mesh-tech/authn/schemes/zitadel-jwt";
|
|
20
|
+
import { createAuthnMiddleware, type AuthnVariables } from "@mesh-tech/authn/hono";
|
|
21
|
+
import { createAuthz } from "@mesh-tech/authz/runtime";
|
|
22
|
+
import { createAuthzMiddleware, type AuthzVariables } from "@mesh-tech/authz/hono";
|
|
23
|
+
import { schema } from "./schema.js";
|
|
24
|
+
import { spiceDbHttpProvider } from "./spicedb-http-provider.js";
|
|
25
|
+
|
|
26
|
+
const PORT = parseInt(process.env.PORT ?? "3000", 10);
|
|
27
|
+
const ZITADEL_ISSUER = process.env.ZITADEL_ISSUER ?? "http://localhost:8080";
|
|
28
|
+
|
|
29
|
+
// --- authn: who is calling ---
|
|
30
|
+
|
|
31
|
+
// Audience: locally, mesh dev injects the seeded CLI app's clientId
|
|
32
|
+
// (tokens come from `mesh login local`); in the cloud this is the app's own
|
|
33
|
+
// audience and consumers request its project-audience scope.
|
|
34
|
+
const AUTH_AUDIENCE = process.env.AUTH_AUDIENCE ?? "{{name}}";
|
|
35
|
+
|
|
36
|
+
const authn = createAuthn({
|
|
37
|
+
schemes: {
|
|
38
|
+
"zitadel-jwt": zitadelJwtScheme({ issuer: ZITADEL_ISSUER, audience: AUTH_AUDIENCE }),
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
const { middleware: requireAuth, public: publicRoute } = createAuthnMiddleware(authn);
|
|
42
|
+
|
|
43
|
+
// --- authz: what they may do ---
|
|
44
|
+
|
|
45
|
+
const authz = createAuthz({
|
|
46
|
+
schemas: {
|
|
47
|
+
"{{name}}": {
|
|
48
|
+
schema,
|
|
49
|
+
provider: spiceDbHttpProvider({
|
|
50
|
+
endpoint: process.env.SPICEDB_HTTP_ENDPOINT ?? "http://localhost:8443",
|
|
51
|
+
// "local-dev-key" is the `mesh start` stack's key — local ONLY. In
|
|
52
|
+
// any deployed env the platform injects SPICEDB_PRESHARED_KEY; fail
|
|
53
|
+
// loudly rather than silently authing with the public default.
|
|
54
|
+
presharedKey:
|
|
55
|
+
process.env.SPICEDB_PRESHARED_KEY ??
|
|
56
|
+
(process.env.NODE_ENV === "production"
|
|
57
|
+
? (() => {
|
|
58
|
+
throw new Error("SPICEDB_PRESHARED_KEY is required in production");
|
|
59
|
+
})()
|
|
60
|
+
: "local-dev-key"),
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
// Explicit subject mapping: authenticated humans are the schema's `user`
|
|
66
|
+
// subject. Required, not optional — the default resolver types EVERY caller as
|
|
67
|
+
// `api_key` (MESH-2472), and a relation cannot target `api_key`, so this app's
|
|
68
|
+
// `viewer: { subject: "user" }` relation would never match without this.
|
|
69
|
+
const m = createAuthzMiddleware(authz, {
|
|
70
|
+
resolveSubject: (c) => ({ type: "user", id: (c as { get(key: "auth"): { subjectSub: string } }).get("auth").subjectSub }),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// --- routes ---
|
|
74
|
+
|
|
75
|
+
const app = new Hono<{ Variables: AuthnVariables & AuthzVariables }>();
|
|
76
|
+
|
|
77
|
+
// Open: no token needed (also excluded from the oauth2-proxy in the cloud)
|
|
78
|
+
app.get("/health", publicRoute(), (c) => c.json({ status: "ok" }));
|
|
79
|
+
|
|
80
|
+
// Everything under /api requires a valid Zitadel JWT…
|
|
81
|
+
app.use("/api/*", requireAuth());
|
|
82
|
+
app.use("/api/*", m.authContextMiddleware());
|
|
83
|
+
|
|
84
|
+
// …authenticated is enough here:
|
|
85
|
+
app.get("/api/me", (c) =>
|
|
86
|
+
c.json({ sub: c.var.auth.subjectSub, email: c.var.auth.claims?.email }),
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// …and this one additionally needs the report:view permission (SpiceDB):
|
|
90
|
+
app.get("/api/report", m.require("report", "view", { id: () => "quarterly" }), (c) =>
|
|
91
|
+
c.json({ id: "quarterly", title: "Quarterly Report", classification: "internal" }),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
serve({ fetch: app.fetch, port: PORT }, () => {
|
|
95
|
+
console.log(`{{name}} api listening on :${PORT} (issuer: ${ZITADEL_ISSUER})`);
|
|
96
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authorization schema — the single source of truth (@mesh-tech/authz).
|
|
3
|
+
*
|
|
4
|
+
* One resource (`report`) with one gated action (`view`), grantable via the
|
|
5
|
+
* `viewer` relation. `pnpm seed:authz` compiles this to SpiceDB and grants
|
|
6
|
+
* the local dev test user; in the cloud the compiled schema ships through
|
|
7
|
+
* the platform's authz pipeline.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { defineSchema } from "@mesh-tech/authz/schema";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
|
|
13
|
+
const Report = z.object({
|
|
14
|
+
id: z.string(),
|
|
15
|
+
title: z.string(),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const schema = defineSchema({
|
|
19
|
+
namespace: "{{name}}",
|
|
20
|
+
version: "1.0.0",
|
|
21
|
+
subjects: {
|
|
22
|
+
user: { coarseRoles: ["user"], identity: { claim: "sub" } },
|
|
23
|
+
},
|
|
24
|
+
resources: {
|
|
25
|
+
report: {
|
|
26
|
+
schema: Report,
|
|
27
|
+
actions: ["view"] as const,
|
|
28
|
+
relations: {
|
|
29
|
+
viewer: { subject: "user", grants: ["view"], writeAuthority: "app" },
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
coarseRoles: ["user"] as const,
|
|
34
|
+
zitadelSync: "coarse",
|
|
35
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local authz seed: compile the schema to SpiceDB and grant the dev test
|
|
3
|
+
* user the report `viewer` relation — the 403→200 half of the README proof.
|
|
4
|
+
*
|
|
5
|
+
* pnpm seed:authz # after `mesh start`
|
|
6
|
+
*
|
|
7
|
+
* dev@local.mesh gets report:view; ops@local.mesh does not (stays 403).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { compileSpiceDBSchema } from "@mesh-tech/authz/compilers";
|
|
11
|
+
import { schema } from "./schema.js";
|
|
12
|
+
import { spiceDbHttpProvider } from "./spicedb-http-provider.js";
|
|
13
|
+
|
|
14
|
+
const ENDPOINT = process.env.SPICEDB_HTTP_ENDPOINT ?? "http://localhost:8443";
|
|
15
|
+
const KEY = process.env.SPICEDB_PRESHARED_KEY ?? "local-dev-key";
|
|
16
|
+
|
|
17
|
+
// The Zitadel subject (`sub` claim) of the user to grant. Find it after
|
|
18
|
+
// `mesh login local`: the CLI caches it in ~/.config/mesh/credentials.json,
|
|
19
|
+
// or pass it explicitly: pnpm seed:authz -- <sub>
|
|
20
|
+
// pnpm may forward a literal "--" — ignore it
|
|
21
|
+
const sub = process.argv.slice(2).filter((a) => a !== "--")[0] ?? process.env.SEED_USER_SUB;
|
|
22
|
+
if (!sub) {
|
|
23
|
+
console.error("Usage: pnpm seed:authz <zitadel-user-sub>");
|
|
24
|
+
console.error("(the `sub` from your mesh login local session — see README)");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { zed } = compileSpiceDBSchema(schema);
|
|
29
|
+
|
|
30
|
+
const res = await fetch(`${ENDPOINT}/v1/schema/write`, {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
|
|
33
|
+
body: JSON.stringify({ schema: zed }),
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
console.error(`schema write failed: ${res.status} ${await res.text()}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
console.log("✓ SpiceDB schema written");
|
|
40
|
+
|
|
41
|
+
const provider = spiceDbHttpProvider({ endpoint: ENDPOINT, presharedKey: KEY });
|
|
42
|
+
await provider.writeRelationship({
|
|
43
|
+
subject: { type: "user", id: sub },
|
|
44
|
+
relation: "viewer",
|
|
45
|
+
resource: { type: "report", id: "quarterly" },
|
|
46
|
+
op: "touch",
|
|
47
|
+
});
|
|
48
|
+
console.log(`✓ Granted report:view on 'quarterly' to user ${sub}`);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal AuthzProvider over SpiceDB's HTTP API.
|
|
3
|
+
*
|
|
4
|
+
* The `mesh start` local platform exposes SpiceDB HTTP on :8443 (preshared
|
|
5
|
+
* key `local-dev-key`); deployed SpiceDB exposes the same API. When the
|
|
6
|
+
* platform ships a first-party gRPC provider in @mesh-tech/authz (tracked
|
|
7
|
+
* under MESH-1823-adjacent runtime work), swap this file for it — the
|
|
8
|
+
* AuthzProvider seam is the whole point.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { AuthzProvider } from "@mesh-tech/authz/runtime";
|
|
12
|
+
|
|
13
|
+
export interface SpiceDbHttpConfig {
|
|
14
|
+
/** e.g. http://localhost:8443 */
|
|
15
|
+
endpoint: string;
|
|
16
|
+
presharedKey: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function call(cfg: SpiceDbHttpConfig, path: string, body: unknown): Promise<any> {
|
|
20
|
+
const res = await fetch(`${cfg.endpoint}${path}`, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: {
|
|
23
|
+
Authorization: `Bearer ${cfg.presharedKey}`,
|
|
24
|
+
"Content-Type": "application/json",
|
|
25
|
+
},
|
|
26
|
+
body: JSON.stringify(body),
|
|
27
|
+
});
|
|
28
|
+
const data: any = await res.json().catch(() => ({}));
|
|
29
|
+
if (!res.ok) {
|
|
30
|
+
throw new Error(`SpiceDB ${path} → ${res.status}: ${data?.message ?? "error"}`);
|
|
31
|
+
}
|
|
32
|
+
return data;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function spiceDbHttpProvider(cfg: SpiceDbHttpConfig): AuthzProvider {
|
|
36
|
+
// compileSpiceDBSchema emits unprefixed definitions (`definition report`),
|
|
37
|
+
// so object types pass through as-is.
|
|
38
|
+
const objectType = (type: string) => type;
|
|
39
|
+
return {
|
|
40
|
+
name: "spicedb-http",
|
|
41
|
+
|
|
42
|
+
async checkPermission({ subject, action, resource, consistency }) {
|
|
43
|
+
// An id-less m.require() would silently check the wildcard resource —
|
|
44
|
+
// fail-closed in practice, but it hides the caller's bug. Fail loud.
|
|
45
|
+
if (!resource.id) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`checkPermission: resource.id is required (got type '${resource.type}' with no id) — pass the object id being authorized.`,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
// Default to fully-consistent: the hello-world flow grants then checks
|
|
51
|
+
// immediately, and SpiceDB's minimize-latency default can serve a stale
|
|
52
|
+
// denial. Tune per-call via the runtime's consistency hint in real apps.
|
|
53
|
+
const data = await call(cfg, "/v1/permissions/check", {
|
|
54
|
+
consistency:
|
|
55
|
+
consistency === "minimize-latency" ? { minimizeLatency: true } : { fullyConsistent: true },
|
|
56
|
+
resource: { objectType: objectType(resource.type), objectId: resource.id },
|
|
57
|
+
permission: action,
|
|
58
|
+
subject: { object: { objectType: objectType(subject.type), objectId: subject.id } },
|
|
59
|
+
});
|
|
60
|
+
return { allowed: data.permissionship === "PERMISSIONSHIP_HAS_PERMISSION" };
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
async writeRelationship({ subject, relation, resource, op }) {
|
|
64
|
+
const operation =
|
|
65
|
+
op === "delete" ? "OPERATION_DELETE" : op === "create" ? "OPERATION_CREATE" : "OPERATION_TOUCH";
|
|
66
|
+
await call(cfg, "/v1/relationships/write", {
|
|
67
|
+
updates: [
|
|
68
|
+
{
|
|
69
|
+
operation,
|
|
70
|
+
relationship: {
|
|
71
|
+
resource: { objectType: objectType(resource.type), objectId: resource.id },
|
|
72
|
+
relation,
|
|
73
|
+
subject: { object: { objectType: objectType(subject.type), objectId: subject.id } },
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
});
|
|
78
|
+
return {};
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
async lookupResources() {
|
|
82
|
+
throw new Error("lookupResources not implemented by the HTTP starter provider");
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
async lookupSubjects() {
|
|
86
|
+
throw new Error("lookupSubjects not implemented by the HTTP starter provider");
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{titleCase name}} — Platform-authenticated API
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure: AppEnvironment + API Service behind platform auth
|
|
5
|
+
* (oauth2-proxy sidecar against the platform Zitadel).
|
|
6
|
+
*
|
|
7
|
+
* Local: mesh start && mesh dev (runtime auth only — no proxy sidecar)
|
|
8
|
+
* Deploy: mesh deploy up
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
import { mesh } from "@mesh-tech/app-kit";
|
|
15
|
+
|
|
16
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const { tenant, platform, stack, deploy } = mesh.apps.getConfig(pulumi);
|
|
18
|
+
|
|
19
|
+
// --- Environment ---
|
|
20
|
+
|
|
21
|
+
const env = new mesh.apps.AppEnvironment("env", {
|
|
22
|
+
tenant,
|
|
23
|
+
platform,
|
|
24
|
+
stack,
|
|
25
|
+
deploy,
|
|
26
|
+
appName: "{{name}}",
|
|
27
|
+
namespace: true,
|
|
28
|
+
rootDir: __dirname,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// --- Services ---
|
|
32
|
+
|
|
33
|
+
// The oauth2-proxy sidecar needs its own OIDC client in the platform
|
|
34
|
+
// Zitadel. Approved tenant-auth pattern: one Zitadel PROJECT per app (in
|
|
35
|
+
// your app tenant's org), one APPLICATION per service — create the app's
|
|
36
|
+
// project if it doesn't exist, add a web application for this service, and
|
|
37
|
+
// set both values on the stack:
|
|
38
|
+
// pulumi config set {{name}}:authClientId <clientId>
|
|
39
|
+
// pulumi config set --secret {{name}}:authClientSecret <clientSecret>
|
|
40
|
+
const appConfig = new pulumi.Config("{{name}}");
|
|
41
|
+
|
|
42
|
+
const api = new mesh.apps.Service("api", {
|
|
43
|
+
env,
|
|
44
|
+
runtime: "node",
|
|
45
|
+
src: "./api",
|
|
46
|
+
port: 3000,
|
|
47
|
+
auth: {
|
|
48
|
+
provider: "mesh", // issuer auto-derived from the platform Zitadel
|
|
49
|
+
clientId: appConfig.require("authClientId"),
|
|
50
|
+
clientSecret: appConfig.requireSecret("authClientSecret"),
|
|
51
|
+
allowUnauthenticated: ["/health"],
|
|
52
|
+
},
|
|
53
|
+
ingress: env.buildIngress({
|
|
54
|
+
subdomain: "{{name}}-api",
|
|
55
|
+
healthCheckPath: "/health",
|
|
56
|
+
}),
|
|
57
|
+
replicas: 1,
|
|
58
|
+
resources: { cpu: "100m", memory: "128Mi" },
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// --- Outputs ---
|
|
62
|
+
|
|
63
|
+
export const app = env.register({
|
|
64
|
+
description: "{{titleCase name}} — platform-authenticated API (authn + authz)",
|
|
65
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"packageManager": "pnpm@10.29.2",
|
|
7
|
+
"keywords": ["tanstack-intent"],
|
|
8
|
+
"scripts": {
|
|
9
|
+
"mesh": "mesh",
|
|
10
|
+
"typecheck": "tsc --noEmit"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@mesh-tech/app-kit": "latest",
|
|
14
|
+
"@pulumi/pulumi": "^3.214.1"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"tsx": "^4.20.4",
|
|
18
|
+
"typescript": "^5.7.2"
|
|
19
|
+
}
|
|
20
|
+
}
|