For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /docs/releases/v0.11.0.md.

v0.11.0

Released: October 28, 2026

This release is about secrets. Each service reads the shared secrets and its own, on every provider, and the cloud permissions follow the same rule. Azure gets a Key Vault per service, and the gateway reads its secrets when it starts. Existing environments upgrade with two new commands.


Secrets per service

  • Each service reads two scopes: shared and its own.
  • When a key is in both, the service's own value wins. This works the same locally and on every provider.
  • Both scopes are read in parallel.
  • A secret that doesn't exist is "not found". Access and network problems are reported as errors.
  • One cache for every provider: 5 minutes in the cloud, 1 minute locally. URLs are never cached.

Auth secrets

  • The JWT signing keys, the refresh token secret, BCRYPT_ROUNDS and ADMIN_EMAILS live in the auth service's scope. Only the auth service reads them.
  • cloud-secrets:push keeps an environment's existing keys, so your users stay logged in.
  • cloud-secrets:set, get and remove find these keys in the auth service's scope.
  • The gateway trust token and the service API keys are shared. Every service checks them.

Cloud permissions

  • GCP and AWS: each service's account reads the shared secrets and its own. Names are matched exactly, so auth and auth-service stay apart.
  • Azure: each backend service gets its own Key Vault next to the shared one. Its identity reads the shared vault and its own.
  • AWS: the role that starts containers reads the shared secrets and each service's database URL. The database setup tasks have a role of their own.
  • Reserved names: shared, secrets and kv can't be service names, and neither can names starting with shared-.

Gateway secrets at startup

The gateway image holds no secrets. Its config references them ({vault://env/redis-password}), and the gateway reads them from its environment when it starts.

  • Locally: docker-compose passes them from the root .env.
  • GCP: Cloud Run sets them from Secret Manager.
  • AWS: the task definition injects them.
  • Azure: App Service reads them from Key Vault. infra:deploy-kong waits until all three are resolved.

The gateway's identity reads exactly these three secrets. A new framework plugin, tsdevstack-trust, sets the trust header.

New commands

  • cloud-secrets:migrate copies secrets from where earlier versions kept them to where services read them now. It never deletes or overwrites.
  • cloud-secrets:cleanup deletes the old copies after the deploy. It asks first. A copy whose value differs from the new one gets its own question, and --force never deletes it. On Azure, it runs once every service is on the new deploy.
  • cloud-secrets:set --stdin reads the value from standard input. It stays out of your shell history and the process list.

The MCP server (cli-mcp 0.9.0) has two new tools, cloud_secrets_migrate and cloud_secrets_cleanup, and an upgrade workflow in its guide.

Pushing your secrets

  • cloud-secrets:push pushes the values in a service's section of .secrets.user.json to that service's scope.
  • Values in a frontend's or a worker's section are listed, not pushed.
  • Values only local development needs stay local.

Improvements

  • Login takes the same time whether or not the email has an account. Projects created before this version apply the change themselves: see the upgrade steps.
  • nest-common declares class-transformer and class-validator, so every NestJS service image has them.
  • cloud:init on Azure checks that it can read the Key Vault's secrets, and names the missing role when it can't.
  • cloud-secrets:push lists each secret that failed, with its error, and continues with the others.
  • Deploys tag images with the last commit. Without --tag, they warn about uncommitted changes.
  • Azure: Key Vault names are the same in every command, for any project name length.
  • Azure: the deploy stops with an error when it can't read the managed identities.
  • GCP: the deploy lists only the DNS records that are missing, with what each one is for.
  • GCP: when Google is still releasing the network, destroy says so and tells you to run it again later.

Breaking changes

Pre-1.0, so they ship in a minor version. The upgrade steps below cover each.

  • nest-common: SecretsService.set() and delete() are removed. Custom SecretsProvider implementations implement read(key, scope).
  • Lookup order: a service's own value wins over a shared one with the same key.
  • kong.user.yml: the Kong commands stop while a request-transformer adds X-Kong-Trust:${KONG_TRUST_TOKEN}.
  • Existing cloud environments run cloud-secrets:migrate before their first deploy with this version.
  • Reserved names: a service named shared, secrets or kv, or starting with shared-, needs a new name.
  • AWS with the scoped IAM statements: add arn:aws:iam::*:role/PROJECT_NAME-db-tasks-execution to ManageFrameworkRoles.

Upgrading an existing project

1. Packages.

npm install -D @tsdevstack/cli@^0.11.0
npm install @tsdevstack/nest-common@^0.11.0 -w <service>

Run the second command for each NestJS service. Remove any calls to SecretsService.set() or delete().

2. kong.user.yml. In the request-transformer plugin, delete X-Kong-Trust:${KONG_TRUST_TOKEN} from add.headers and X-Kong-Trust from remove.headers. If add is left empty, delete it too.

3. Auth service. If your auth service came from the template, add this to src/auth/auth.service.ts:

private dummyPasswordHash!: string;

// In onModuleInit, after bcryptRounds is set:
this.dummyPasswordHash = await bcrypt.hash(
  randomBytes(16).toString('hex'),
  this.bcryptRounds,
);

// In login, before throwing for an unknown user:
await bcrypt.compare(password, this.dummyPasswordHash);

4. Local stack.

npx tsdevstack sync

This moves the auth secrets into the auth service's section of .secrets.local.json. It also gives the gateway its three secrets from the root .env.

5. Each cloud environment. In this order:

npx tsdevstack cloud-secrets:migrate --env <env>
npx tsdevstack infra:deploy --env <env>
npx tsdevstack cloud-secrets:cleanup --env <env>

migrate only copies, and cleanup only deletes the old copies. If your environments deploy from CI only, run these once from a machine with the environment's credentials.

New projects get all of this from the start.