← All @molecule/* packages · App templates

@molecule/api-secrets

Core interface · secrets · API (Node) · v1.0.1 · Apache-2.0

Secrets management interface

npm install @molecule/api-secrets

npm · Source on GitHub

How 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

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.ts JSDoc, not this file.

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

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

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[]
}

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
}

HealthCheckResult

Health check result for a service connection.

interface HealthCheckResult {
  service: string
  healthy: boolean
  latencyMs?: number
  error?: string
  details?: Record<string, unknown>
}

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[]
}

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
}

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
}

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>
}

SecretValidation

Result of secret validation.

interface SecretValidation {
  key: string
  valid: boolean
  value?: string
  error?: string
}

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
}

Functions

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.

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'.

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.

getAllProvisioners()

Returns all registered service provisioners.

function getAllProvisioners(): ServiceProvisioner[]

Returns: An array of all registered provisioners.

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.

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).

getProvider()

Retrieves the bonded secrets provider, or null if none is bonded.

function getProvider(): SecretsProvider | null

Returns: The bonded secrets provider, or null.

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.

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.

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).

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).

hasProvider()

Checks whether a secrets provider is currently bonded.

function hasProvider(): boolean

Returns: true if a secrets provider is bonded.

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.

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 from {@link buildConfigReport}.

Returns: The same report, for chaining.

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 its service name.

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.

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.

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.

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 into process.env.

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.

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

ProviderPackage
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 {@link get}/{@link 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 {@link get}/{@link getRequired} (env/Doppler/ Vault) so they're never committed. {@link getRequired} throws at startup when unset (fail fast) — prefer it for anything the app can't run without.
  • Use {@link validate} at boot to surface every missing/invalid secret at once.

Translations

Translation strings are provided by @molecule/api-locales-secrets.