Skip to content

Secrets

Slingshot reads secrets at startup, not at request time. Missing or misconfigured secrets fail loud and fast — before the server serves a single request.

Configure a provider in your app.config.ts:

app.config.ts
import { defineApp } from '@lastshotlabs/slingshot';
export default defineApp({
secrets: {
provider: 'env',
prefix: 'APP_',
},
// ...
});

Reads from process.env. The prefix option filters to matching variables only:

{ provider: 'env', prefix: 'APP_' }

APP_SECRET becomes SECRET, APP_DB_URL becomes DB_URL, and so on.

Reads a .env file and populates process.env before the app boots:

{ provider: 'file', path: import.meta.dir + '/.env' }

Fetches from SSM at startup:

{
provider: 'ssm',
path: '/my-app/prod/',
region: 'us-east-1',
}

Parameters under /my-app/prod/ are available by their trailing key name. /my-app/prod/SECRET becomes SECRET.

The most common usage is signing.secret for JWT signing — the resolved secret bundle is exposed to the framework, and signing pulls from it automatically when secrets resolves a JWT_SECRET value:

app.config.ts
export default defineApp({
secrets: { provider: 'env' },
// signing.secret defaults to the JWT_SECRET resolved by the provider
});

Missing secrets throw at startup:

Error: Required secret JWT_SECRET not found in environment.
Make sure APP_JWT_SECRET is set (using prefix "APP_").

A server that boots has all its secrets. Nothing resolves lazily at request time.

Pass any object that implements the SecretRepository interface directly:

app.config.ts
// @skip-typecheck
import { defineApp } from '@lastshotlabs/slingshot';
import type { SecretRepository } from '@lastshotlabs/slingshot';
declare const vaultClient: { read(path: string): Promise<string | undefined> };
const vaultProvider: SecretRepository = {
async get(key: string) {
return vaultClient.read(`secret/data/my-app/${key}`);
},
// ...
};
export default defineApp({
secrets: vaultProvider,
// ...
});
  • Auth Setupsigning.secret is the most common secret