Skip to main content

Secrets-Backed Config

Resolve an application config from a shared base object, the selected RANK_ENV, and a JSON secret fetched from AWS Secrets Manager.

This example is backed by LocalStack so the provider call is runnable in the repository without a real AWS account.

Source

examples/secrets-backed-config/types.rank
pub Environment = `dev` | `staging` | `prod`

pub LogLevel = `debug` | `info` | `warn`

pub BaseConfig = Object {
service: Object {
name: string,
baseUrl: string,
logLevel: LogLevel,
},
database: Object {
host: string,
port: number,
name: string,
user: string,
},
auth: Object {
issuer: string,
},
integrations: Object {
billingApiBaseUrl: string,
},
}

pub RuntimeSecrets = Object {
dbPassword: string,
jwtSigningSecret: string,
stripeApiKey: string,
}

pub ResolvedConfig = Object {
service: Object {
name: string,
env: Environment,
baseUrl: string,
logLevel: LogLevel,
},
database: Object {
host: string,
port: number,
name: string,
user: string,
password: string,
},
auth: Object {
issuer: string,
jwtSigningSecret: string,
},
integrations: Object {
billingApiBaseUrl: string,
stripeApiKey: string,
},
source: Object {
secretId: string,
},
}
examples/secrets-backed-config/main.rank
/// Resolves a deployable app config from a shared base, the selected
/// environment, and a JSON secret fetched from AWS Secrets Manager.

use aws::{ SecretsManager }
use std::Env
use root::types::{ BaseConfig, Environment, LogLevel, ResolvedConfig, RuntimeSecrets }

SysEnv = Object {
RANK_ENV?: Environment,
SECRETS_ENDPOINT?: string,
...: string,
}

{ RANK_ENV, SECRETS_ENDPOINT } = Env<SysEnv> {}

selected_env: Environment = RANK_ENV ?? `staging`
secrets_endpoint = SECRETS_ENDPOINT ?? `http://127.0.0.1:4566`

base: BaseConfig = {
service: {
name: `payments-api`,
baseUrl: `https://payments.internal`,
logLevel: `info`,
},
database: {
host: `db.internal`,
port: 5432,
name: `payments`,
user: `payments_app`,
},
auth: {
issuer: `https://auth.internal/issuer`,
},
integrations: {
billingApiBaseUrl: `https://billing.internal/api`,
},
}

log_level_for = |env: Environment| -> LogLevel {
return match env {
`dev` => `debug`,
`staging` => `info`,
`prod` => `warn`,
}
}

secret_id_for = |env: Environment| -> string {
return match env {
`dev` => `rank/examples/payments-api/dev`,
`staging` => `rank/examples/payments-api/staging`,
`prod` => `rank/examples/payments-api/prod`,
}
}

env_config: BaseConfig = match selected_env {
`dev` => base with {
service: base.service with {
baseUrl: `https://payments.dev.internal`,
logLevel: log_level_for(selected_env),
},
database: base.database with {
host: `dev-db.internal`,
},
integrations: base.integrations with {
billingApiBaseUrl: `https://billing.dev.internal/api`,
},
},
`staging` => base with {
service: base.service with {
baseUrl: `https://payments.staging.internal`,
logLevel: log_level_for(selected_env),
},
database: base.database with {
host: `staging-db.internal`,
},
integrations: base.integrations with {
billingApiBaseUrl: `https://billing.staging.internal/api`,
},
},
`prod` => base with {
service: base.service with {
baseUrl: `https://payments.example.com`,
logLevel: log_level_for(selected_env),
},
database: base.database with {
host: `payments-db.internal`,
},
integrations: base.integrations with {
billingApiBaseUrl: `https://billing.example.com/api`,
},
},
}

secrets_client: aws::SecretsManager::ClientConfig = SecretsManager::createClient({
region: `us-east-1`,
endpoint: secrets_endpoint,
credentials: {
accessKeyId: `test`,
secretAccessKey: `test`,
},
})

secret_id = secret_id_for(selected_env)

secret_result: aws::SecretsManager::SecretResult<RuntimeSecrets> = aws::SecretsManager::Secret<RuntimeSecrets> {
client: secrets_client,
secretId: secret_id,
format: `json`,
}

pub main = || -> ResolvedConfig {
return {
service: env_config.service with {
env: selected_env,
},
database: env_config.database with {
password: secret_result.secret.dbPassword,
},
auth: env_config.auth with {
jwtSigningSecret: secret_result.secret.jwtSigningSecret,
},
integrations: env_config.integrations with {
stripeApiKey: secret_result.secret.stripeApiKey,
},
source: {
secretId: secret_id,
},
}
}
examples/secrets-backed-config/rank.toml
manifestVersion = 1

[package]
name = "secrets-backed-config-example"
version = "0.1.0"
source = "."

[providers]
aws = { path = "../../packages/plugins/aws" }

[security]
allow-provider-capabilities = ["network"]
allow-env = ["RANK_ENV", "SECRETS_ENDPOINT"]

Output

Default output with RANK_ENV unset:

service:
name: payments-api
baseUrl: https://payments.staging.internal
logLevel: info
env: staging
database:
host: staging-db.internal
port: 5432
name: payments
user: payments_app
password: staging-db-password
auth:
issuer: https://auth.internal/issuer
jwtSigningSecret: staging-jwt-signing-secret
integrations:
billingApiBaseUrl: https://billing.staging.internal/api
stripeApiKey: sk_test_staging_456
source:
secretId: rank/examples/payments-api/staging

Run it

Start LocalStack from the example directory:

cd examples/secrets-backed-config
docker compose up

Then run the Rank program from the workspace root:

npm run rank -- examples/secrets-backed-config

Switch environments with RANK_ENV:

RANK_ENV=prod npm run rank -- examples/secrets-backed-config

If you changed the LocalStack host port, pass the matching endpoint:

RANK_ENV=prod SECRETS_ENDPOINT=http://127.0.0.1:4567 npm run rank -- examples/secrets-backed-config

Key concepts

  • aws::SecretsManager::Secret<T> fetches a typed secret payload and decodes JSON directly into a checked Rank object.
  • Base + environment patching uses with to keep the stable config shape separate from environment-specific overrides.
  • std::Env selection turns RANK_ENV into typed branching instead of ad hoc string checks.
  • LocalStack-backed provider example keeps the example runnable in-repo while still exercising the real provider surface.