Secret Manager
Secret Manager provides secure storage for sensitive values like API keys, tokens, and credentials that your application needs at runtime.
Overview
Secret Manager provides:
- Secure storage for sensitive configuration values
- Organized secrets within named vaults
- Runtime access from executors and workflows
- CLI management for secrets lifecycle
Concepts
Vaults
Vaults are containers that group related secrets together. Each workspace can have multiple vaults, typically organized by purpose or environment.
workspace/
├── vault: api-keys
│ ├── stripe-secret-key
│ ├── sendgrid-api-key
│ └── external-service-token
└── vault: database
├── read-replica-password
└── analytics-connection-stringSecrets
Secrets are key-value pairs stored within a vault. Secret values are encrypted at rest and only accessible at runtime by authorized services.
Managing Secrets
There are two ways to manage secrets: declaratively via defineSecretManager() in tailor.config.ts, or imperatively via the CLI. Management is scoped per vault — do not mix both approaches for the same vault. When a vault is defined in config, the config becomes the source of truth: any secrets in that vault not present in the config will be deleted on tailor-sdk apply.
Declarative Configuration
Define your secrets in tailor.config.ts using defineSecretManager(). Each key is a vault name, and its value is a record of secret names to their values. These values are deployed to each vault on tailor-sdk apply.
Since secret values should not be committed to source control, use environment variables:
import { defineConfig, defineSecretManager } from "@tailor-platform/sdk";
export const secrets = defineSecretManager({
"api-keys": {
"stripe-secret-key": process.env.STRIPE_SECRET_KEY!,
"sendgrid-api-key": process.env.SENDGRID_API_KEY!,
},
database: {
"analytics-connection-string": process.env.ANALYTICS_DB_URL!,
},
});
export default defineConfig({
name: "my-app",
secrets,
// ...other config
});The exported secrets object provides type-safe get() and getAll() methods for runtime access from resolvers, executors, and workflows.
Using Secrets
Runtime Access with get() / getAll()
Use the secrets object exported from tailor.config.ts to retrieve secret values at runtime. The vault and secret names are fully type-checked based on the defineSecretManager() configuration.
get(vault, secret)
Retrieves a single secret value.
import { createResolver } from "@tailor-platform/sdk";
import { secrets } from "../tailor.config";
export default createResolver({
name: "call-stripe",
// ...
operation: async ({ input }) => {
const apiKey = await secrets.get("api-keys", "stripe-secret-key");
// Use apiKey to call the Stripe API
},
});getAll(vault, secrets)
Retrieves multiple secret values at once from the same vault.
import { createResolver } from "@tailor-platform/sdk";
import { secrets } from "../tailor.config";
export default createResolver({
name: "send-notification",
// ...
operation: async ({ input }) => {
const [apiKey, webhookSecret] = await secrets.getAll("api-keys", [
"sendgrid-api-key",
"stripe-secret-key",
]);
// Use the retrieved secrets
},
});Both methods return Promise<string | undefined> (or an array of them for getAll).
In Webhook Operations
Reference secrets in webhook headers using the vault/key syntax:
import { createExecutor, recordCreatedTrigger } from "@tailor-platform/sdk";
import { order } from "../tailordb/order";
export default createExecutor({
name: "notify-external-service",
trigger: recordCreatedTrigger({ type: order }),
operation: {
kind: "webhook",
url: "https://api.example.com/orders",
headers: {
"Content-Type": "application/json",
Authorization: { vault: "api-keys", key: "external-api-token" },
"X-API-Key": { vault: "api-keys", key: "api-secret" },
},
requestBody: ({ newRecord }) => ({
orderId: newRecord.id,
amount: newRecord.total,
}),
},
});The secret reference format:
{ vault: "vault-name", key: "secret-name" }At runtime, these references are replaced with the actual secret values.
CLI Management
Use the CLI to manage vaults that are not defined in defineSecretManager(). If you attempt to modify a vault that is managed by the config, the CLI will show a warning and ask for confirmation. Once confirmed, the CLI releases the vault's ownership label so it is no longer managed by config.
After ownership is released, the next tailor-sdk apply will treat the vault as an unmanaged resource and prompt for confirmation before taking any action on it.
Create a Vault
tailor-sdk secret vault create --name api-keysAdd Secrets
# Create a secret
tailor-sdk secret create \
--vault-name api-keys \
--name stripe-secret-key \
--value sk_live_xxxxx
# Update a secret
tailor-sdk secret update \
--vault-name api-keys \
--name stripe-secret-key \
--value sk_live_yyyyyList Secrets
# List vaults
tailor-sdk secret vault list
# List secrets in a vault (values are hidden)
tailor-sdk secret list --vault-name api-keysDelete Secrets
# Delete a secret
tailor-sdk secret delete --vault-name api-keys --name old-key --yes
# Delete a vault (must be empty)
tailor-sdk secret vault delete --name old-vault --yesSee Secret CLI Commands for full documentation.