Keyring
ReferenceControl-plane API

Control-plane configuration

Every KEYRING_* variable the control plane reads, with the validation it applies.

Generated from the schema in packages/api/src/config.ts by packages/docs/tools/generate-reference.mjs. deploy/api/.env.example names the same set, and a CI spec fails when the two drift.

A value that fails its rule refuses to start the process, naming the variable. KEYRING_PEPPER_V1 (and further _V<n>) and KEYRING_EMBED_SIGNING_KEY_V1/_V2 are read outside this schema: each must be 32 bytes of hex, at least one pepper is required, and at most two embed signing keys are accepted.

VariableRule
KEYRING_APP_DATABASE_URLz.string().min(1)
KEYRING_API_HOSTz.string().default('0.0.0.0')
KEYRING_API_PORTz.coerce.number().int().positive().default(3000)
KEYRING_API_POOL_SIZEz.coerce.number().int().positive().default(10)
KEYRING_API_CONNECTION_TIMEOUT_MSz.coerce .number() .int() .positive() .default(3_000)
KEYRING_API_STATEMENT_TIMEOUT_MSz.coerce .number() .int() .positive() .default(5_000)
KEYRING_API_LOCK_TIMEOUT_MSz.coerce .number() .int() .positive() .default(2_000)
KEYRING_API_IDLE_IN_TRANSACTION_TIMEOUT_MSz.coerce .number() .int() .positive() .default(10_000)
KEYRING_API_LOG_LEVELz.string().default('info')
KEYRING_BOOTSTRAP_TOKENz.string().min(16).optional()
KEYRING_POLICY_NODE_LIVENESS_MSz.coerce .number() .int() .positive() .default(60_000)
KEYRING_POLICY_NODE_RETENTION_MSz.coerce .number() .int() .positive() .default(1_800_000)
KEYRING_POLICY_NODE_REFRESH_MSz.coerce .number() .int() .positive() .default(30_000)
KEYRING_REVOKE_WAIT_TIMEOUT_MSz.coerce .number() .int() .positive() .default(10_000)
KEYRING_REVOKE_WAIT_POLL_MSz.coerce.number().int().positive().default(250)
KEYRING_POLICY_DELTA_MAX_CHANGESz.coerce .number() .int() .positive() .default(2_000)
KEYRING_POLICY_SNAPSHOT_MAX_KEYSz.coerce .number() .int() .positive() .default(10_000)
KEYRING_INGEST_MAX_EVENTS_PER_MINUTEz.coerce .number() .int() .positive() .default(120_000)
KEYRING_INGEST_MAX_BODY_BYTESz.coerce .number() .int() .positive() .default(4 * 1024 * 1024)
KEYRING_REDIS_URLz.string().min(1).optional()
KEYRING_REDIS_COMMAND_TIMEOUT_MSz.coerce .number() .int() .positive() .default(250)
KEYRING_HOT_AUTH_CACHE_MSz.coerce .number() .int() .min(0) .max(60_000) .default(5_000)
KEYRING_HOT_AUTH_CACHE_MAXz.coerce .number() .int() .positive() .default(10_000)
KEYRING_IDEMPOTENCY_TTL_MSz.coerce .number() .int() .min(60_000) .max(604_800_000) .default(86_400_000)
KEYRING_IDEMPOTENCY_MAX_TTL_MSz.coerce .number() .int() .min(60_000) .max(604_800_000) .default(604_800_000)
KEYRING_IDEMPOTENCY_LOCK_MSz.coerce .number() .int() .min(1_000) .max(600_000) .default(30_000)
KEYRING_IDEMPOTENCY_MAX_BODY_BYTESz.coerce .number() .int() .positive() .max(4 * 1024 * 1024) .default(256 * 1024)
KEYRING_EMBED_TOKEN_TTL_MSz.coerce .number() .int() .min(1_000) .max(900_000) .default(300_000)
KEYRING_EMBED_ISSUERz.string().min(1).max(255).default('keyring')
KEYRING_EMBED_EPOCH_CACHE_MSz.coerce .number() .int() .min(1_000) .max(60_000) .default(5_000)
KEYRING_EMBED_CLOCK_SKEW_MSz.coerce .number() .int() .min(0) .max(60_000) .default(5_000)
KEYRING_SESSION_IDLE_MSz.coerce .number() .int() .min(60_000) .max(2_592_000_000) .default(43_200_000)
KEYRING_SESSION_ABSOLUTE_MSz.coerce .number() .int() .min(60_000) .max(7_776_000_000) .default(2_592_000_000)
KEYRING_SESSION_TOUCH_MSz.coerce .number() .int() .min(0) .max(3_600_000) .default(60_000)
KEYRING_PASSWORD_RESET_TTL_MSz.coerce .number() .int() .min(60_000) .max(86_400_000) .default(1_800_000)
KEYRING_INVITE_TTL_MSz.coerce .number() .int() .min(3_600_000) .max(2_592_000_000) .default(604_800_000)
KEYRING_EMAIL_VERIFICATION_TTL_MSz.coerce .number() .int() .min(3_600_000) .max(2_592_000_000) .default(604_800_000)
KEYRING_LOGIN_MAX_FAILURESz.coerce .number() .int() .min(1) .max(1_000) .default(10)
KEYRING_LOGIN_LOCK_MSz.coerce .number() .int() .min(1_000) .max(86_400_000) .default(900_000)
KEYRING_QUARANTINE_MSz.coerce .number() .int() .min(1_000) .max(86_400_000) .default(3_600_000)
KEYRING_SECRET_SCANNING_KEYS_URLz .url() .default('https://api.github.com/meta/public_keys/secret_scanning')
KEYRING_SECRET_SCANNING_KEYSz.string().min(1).optional()
KEYRING_SECRET_SCANNING_KEYS_REFRESH_MSz.coerce .number() .int() .min(1_000) .max(86_400_000) .default(300_000)