@molecule/api-secrets
Core interface · secrets · API (Node) · v1.0.2 · Apache-2.0
Secrets management interface
npm install @molecule/api-secretsHow it works
@molecule/api-secrets is the secrets core interface on the API (Node) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 3 providers: @molecule/api-secrets-doppler, @molecule/api-secrets-env, @molecule/api-secrets-molecule.
import { get, getRequired, validate, COMMON_SECRETS } from '@molecule/api-secrets'
// Get a secret (returns undefined if not set)
const apiKey = await get('STRIPE_SECRET_KEY')
// Get a required secret (throws if not set)
const dbUrl = await getRequired('DATABASE_URL')
// Validate multiple secrets
const results = await validate([COMMON_SECRETS.DATABASE_URL, COMMON_SECRETS.STRIPE_SECRET_KEY])Providers (3): @molecule/api-secrets-doppler, @molecule/api-secrets-env, @molecule/api-secrets-molecule
Works with: @molecule/api-bond
Reference
Secrets management core interface.
Provides a standardized way to:
- Define required secrets for packages
- Retrieve secrets from various providers (env, Doppler, Vault, etc.)
- Validate secrets at startup
- Auto-provision services
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import { get, getRequired, validate, COMMON_SECRETS } from '@molecule/api-secrets'
// Get a secret (returns undefined if not set)
const apiKey = await get('STRIPE_SECRET_KEY')
// Get a required secret (throws if not set)
const dbUrl = await getRequired('DATABASE_URL')
// Validate multiple secrets
const results = await validate([COMMON_SECRETS.DATABASE_URL, COMMON_SECRETS.STRIPE_SECRET_KEY])
Type
core
Installation
npm install @molecule/api-secrets @molecule/api-bond
API
Interfaces
Secret
A secret value with metadata.
interface Secret {
/** The secret key/name */
key: string
/** The secret value (undefined if not set) */
value: string | undefined
/** Whether the secret is required */
required: boolean
/** Human-readable description */
description?: string
/** URL with instructions on how to obtain this secret */
helpUrl?: string
/** Validation pattern (regex) */
pattern?: string
/** Example value (for documentation) */
example?: string
}
SecretDefinition
Secret definition used by packages to declare their requirements.
interface SecretDefinition {
/** Environment variable name */
key: string
/** Human-readable description */
description: string
/** Whether this secret is required (default: true) */
required?: boolean
/** URL with instructions on how to obtain this secret */
helpUrl?: string
/** Validation regex pattern */
pattern?: string
/** Example value */
example?: string
/** Default value (for optional secrets) */
default?: string
}
SecretValidation
Result of secret validation.
interface SecretValidation {
key: string
valid: boolean
value?: string
error?: string
}
ConfigReportEntry
One secret's line in a boot-time configuration report.
interface ConfigReportEntry {
/** The secret key. */
key: string
/** `set` (value present), `default` (unset but a default applies), or `missing`. */
status: 'set' | 'default' | 'missing'
/** Whether the secret is required (SecretDefinition.required, default true). */
required: boolean
/** Human-readable description from the registered definition. */
description?: string
/** Setup URL from the registered definition — where to obtain the value. */
helpUrl?: string
}
ConfigReport
Structured boot-time configuration report (see buildConfigReport).
interface ConfigReport {
/** `true` when no REQUIRED secret is missing. */
ok: boolean
/** Every reported secret. */
entries: ConfigReportEntry[]
/** Missing secrets that are required — the app is degraded until set. */
missingRequired: ConfigReportEntry[]
/** Missing secrets that are optional. */
missingOptional: ConfigReportEntry[]
}
HealthCheckResult
Health check result for a service connection.
interface HealthCheckResult {
service: string
healthy: boolean
latencyMs?: number
error?: string
details?: Record<string, unknown>
}
SecretsProvider
Secrets provider interface.
Providers implement this interface to retrieve secrets from different sources (env files, Doppler, Vault, etc.)
interface SecretsProvider {
/** Provider name (for logging) */
readonly name: string
/**
* Get a single secret value.
*/
get(key: string): Promise<string | undefined>
/**
* Get multiple secret values.
*/
getMany(keys: string[]): Promise<Record<string, string | undefined>>
/**
* Set a secret value (if supported by the provider).
*/
set?(key: string, value: string): Promise<void>
/**
* Delete a secret (if supported by the provider).
*/
delete?(key: string): Promise<void>
/**
* Check if the provider is available and configured.
*/
isAvailable(): Promise<boolean>
/**
* Sync secrets from this provider to environment variables.
* Call this at app startup to populate process.env.
*/
syncToEnv?(keys: string[]): Promise<void>
}
ServiceProvisioner
Service provisioner interface.
Provisioners can automatically create accounts, API keys, or resources for specific services.
interface ServiceProvisioner {
/** Service name */
readonly service: string
/** Human-readable display name */
readonly displayName: string
/** Secrets this service provides */
readonly secrets: SecretDefinition[]
/**
* Checks if the service is already configured with valid credentials.
*/
isConfigured(): Promise<boolean>
/**
* Interactively provisions the service (may open a browser or prompt for input).
*/
setup(options?: ProvisionerOptions): Promise<ProvisionerResult>
/**
* Validates that the current configuration works by connecting to the service.
*/
validate(): Promise<HealthCheckResult>
/**
* Returns human-readable instructions for manual setup of this service.
*/
getSetupInstructions(): string
}
ProvisionerOptions
Options passed to a service provisioner's setup() method.
interface ProvisionerOptions {
/** Run in non-interactive mode */
nonInteractive?: boolean
/** Secrets provider to store credentials */
secretsProvider?: SecretsProvider
/** Use test/sandbox mode if available */
sandbox?: boolean
}
ProvisionerResult
Result returned by a service provisioner's setup() method.
interface ProvisionerResult {
success: boolean
secrets?: Record<string, string>
error?: string
message?: string
}
PackageSecrets
Package-level secret manifest, mapping a package name to the secrets it requires. Read from package metadata during CLI operations.
interface PackageSecrets {
/** Package name */
package: string
/** Required secrets */
secrets: SecretDefinition[]
}
Functions
setProvider(provider)
Registers a secrets provider as the active singleton. Called by bond packages during application startup.
function setProvider(provider: SecretsProvider): void
provider— The secrets provider implementation to bond.
getProvider()
Retrieves the bonded secrets provider, or null if none is bonded.
function getProvider(): SecretsProvider | null
Returns: The bonded secrets provider, or null.
hasProvider()
Checks whether a secrets provider is currently bonded.
function hasProvider(): boolean
Returns: true if a secrets provider is bonded.
get(key)
Retrieves a single secret value. Delegates to the bonded provider if
available, otherwise reads from process.env.
function get(key: string): Promise<string | undefined>
key— The environment variable / secret key name.
Returns: The secret value, or undefined if not set.
getMany(keys)
Retrieves multiple secret values at once. Delegates to the bonded
provider if available, otherwise reads from process.env.
function getMany(keys: string[]): Promise<Record<string, string | undefined>>
keys— The secret key names to retrieve.
Returns: A record mapping each key to its value (or undefined).
getRequired(key)
Retrieves a secret value, throwing if it is not set.
function getRequired(key: string): Promise<string>
key— The environment variable / secret key name.
Returns: The secret value (guaranteed non-empty).
validate(definitions)
Validates a list of secret definitions against the current environment, checking presence and optional pattern matching. Values are masked in the returned results.
function validate(definitions: SecretDefinition[]): Promise<SecretValidation[]>
definitions— The secret definitions to validate.
Returns: One validation result per definition, each with valid and optional error.
isConfigured(definitions)
Checks whether all required secrets in the given definitions are set and valid.
function isConfigured(definitions: SecretDefinition[]): Promise<boolean>
definitions— The secret definitions to check.
Returns: true if every definition passes validation.
syncToEnv(keys)
Fetches secrets from the bonded provider and writes them into process.env.
Call this at application startup before other modules access secrets.
function syncToEnv(keys: string[]): Promise<void>
keys— The secret key names to sync intoprocess.env.
resolveAll(keys)
Resolves all registered secret definitions and syncs them into process.env.
Call this at application startup after bonding a secrets provider and before
initializing other bonds. Bond packages register their required secrets
via registerSecrets(), and this function fetches them all at once.
function resolveAll(keys?: string[]): Promise<void>
keys— Optional explicit list of keys to resolve; if omitted, resolves all registered definitions.
registerProvisioner(provisioner)
Registers a service provisioner so the CLI can discover and auto-provision the service.
function registerProvisioner(provisioner: ServiceProvisioner): void
provisioner— The provisioner to register, keyed by itsservicename.
getProvisioner(service)
Retrieves a registered service provisioner by service name.
function getProvisioner(service: string): ServiceProvisioner | undefined
service— The service name (e.g.'stripe','sendgrid').
Returns: The provisioner, or undefined if not registered.
getAllProvisioners()
Returns all registered service provisioners.
function getAllProvisioners(): ServiceProvisioner[]
Returns: An array of all registered provisioners.
getProvisionerForSecret(key)
Finds the provisioner whose secrets array includes the given key.
function getProvisionerForSecret(key: string): ServiceProvisioner | undefined
key— The secret key to search for.
Returns: The provisioner that owns the secret, or undefined.
registerSecret(definition)
Registers a single secret definition. Provider bonds call this to declare their required secrets at import time.
function registerSecret(definition: SecretDefinition): void
definition— The secret definition to register.
registerSecrets(definitions)
Registers multiple secret definitions at once.
function registerSecrets(definitions: SecretDefinition[]): void
definitions— The secret definitions to register.
getAllSecretDefinitions()
Returns all registered secret definitions from both dynamic registration and pre-registered common secrets.
function getAllSecretDefinitions(): SecretDefinition[]
Returns: An array of all registered secret definitions.
getSecretDefinition(key)
Looks up a secret definition by key. Checks the dynamic registry first
(populated by provider bonds), then falls back to COMMON_SECRETS.
function getSecretDefinition(key: string): SecretDefinition | undefined
key— The secret key to look up.
Returns: The secret definition, or undefined if not registered.
getSecretDefinitions(keys)
Looks up secret definitions for a list of keys, filtering out any keys that have no registered definition.
function getSecretDefinitions(keys: string[]): SecretDefinition[]
keys— The secret keys to look up.
Returns: The matching secret definitions (keys without definitions are omitted).
buildConfigReport(keys)
Builds a structured configuration report for the given secret keys
(default: every registered definition). Each entry reports whether the
secret is set, satisfied by a default, or missing — with the
definition's description and setup URL attached so a missing entry is
directly actionable.
function buildConfigReport(keys?: string[]): Promise<ConfigReport>
keys— Secret keys to report on. Defaults to all registered definitions.
Returns: The report; ok is false when any REQUIRED secret is missing.
logConfigReport(report)
Logs a configuration report: one warning per missing REQUIRED secret (with its description + setup URL — the integration is degraded until it is set), a compact info line for missing optional secrets, and a summary. Never throws — booting with missing credentials is allowed; the point is that the gap is loud and actionable instead of surfacing later as an opaque 503.
function logConfigReport(report: ConfigReport): ConfigReport
report— A report frombuildConfigReport.
Returns: The same report, for chaining.
configNotConfiguredError(key, capability)
Builds the tagged error a bond should throw when a request needs a
secret that is not configured. The API error middleware maps
statusCode + errorKey to a clean 503, and the message carries the
secret's description and setup URL from the registry — so the user sees
exactly which key to set and where to get it, not an opaque failure.
function configNotConfiguredError(
key: string,
capability?: string,
): Error & { statusCode: number; errorKey: string }
key— The missing secret's key (e.g.'STRIPE_SECRET_KEY').capability— Optional human label for what is disabled (e.g.'payments').
Returns: An Error tagged with statusCode: 503 and errorKey: 'config.notConfigured'.
Constants
COMMON_SECRETS (deprecated)
Common secret definitions — only generic application-level secrets.
Vendor-specific secrets (SendGrid, Stripe, AWS, etc.) are registered
by their respective provider bonds. Use registerSecret() to add
new definitions at runtime.
const COMMON_SECRETS: Record<string, SecretDefinition>
Available Providers
| Provider | Package |
|---|---|
| Doppler | @molecule/api-secrets-doppler |
| Environment Variables | @molecule/api-secrets-env |
| Molecule Vault | @molecule/api-secrets-molecule |
Injection Notes
Requirements
Peer dependencies:
@molecule/api-bond^1.0.1
Runtime Dependencies
@molecule/api-bond
Secrets are SERVER-SIDE only. NEVER send a secret value to the browser, embed it in
client code, or expose it through a VITE_/NEXT_PUBLIC_ build var — those ship to
every user. Only a PUBLISHABLE/public key (Stripe pk_…, a VAPID public key, an OAuth
client id) may be client-side; everything from get/getRequired stays in
the API.
- Never log a secret VALUE or return it in an API response / error message.
- Don't hardcode secrets — read them via
get/getRequired(env/Doppler/ Vault) so they're never committed.getRequiredthrows at startup when unset (fail fast) — prefer it for anything the app can't run without. - Use
validateat boot to surface every missing/invalid secret at once.
Translations
Translation strings are provided by @molecule/api-locales-secrets.