Overview
@saflib/secret-store defines a shared secret lookup interface for runtime configuration. Fetch secrets after checking they are declared in the calling package's secrets.json. Validation is package-local at the call site — there is no process-wide secret registry or boot-time monorepo graph walk.
This package provides the abstract SecretStore, an env-backed implementation, and a process-level singleton (setSecretStore / getSecretStore). Vendor backends (e.g. Infisical) live in @saflib/vendors-* packages.
What this package provides
SecretStore—getSecretByName(name, packageSecrets)after manifest validationEnvSecretStore— reads fromprocess.envcreateSecretStore— factory for env-backed stores in tests and local devsecrets-manifest—isSecretDeclared,SecretManifesttypes- Errors —
SecretNotDeclaredError,EnvSecretNotFoundError(ReturnsError)
Code reference: docs/ref/.
Declare secrets
Add secrets.json next to the package's package.json:
[
{
"name": "STRIPE_SECRET_API_KEY",
"description": "Stripe secret API key. Sentinel \"mock\" selects the in-memory mock client."
}
]Required fields: name, description. Metadata only — never put values here.
Fetch with the package manifest
import type { SecretStore } from "@saflib/secret-store";
import packageSecrets from "./secrets.json" with { type: "json" };
const out = await store.getSecretByName(
"STRIPE_SECRET_API_KEY",
packageSecrets,
);
if (out.error) {
// includes SecretNotDeclaredError when the name is missing from packageSecrets
}getSecretByName(name, packageSecrets):
- Returns
SecretNotDeclaredErrorifnameis not inpackageSecrets. - Otherwise fetches from the configured backend.
Prefer importing ./secrets.json next to the configure* function that owns the secret.
Creating a store
import {
createSecretStore,
setSecretStore,
getSecretStore,
} from "@saflib/secret-store";
// Env-backed (typical for CLIs and base template):
const store = createSecretStore({ type: "env" });
setSecretStore(store);
// Infisical (product opt-in via @saflib/vendors-infisical):
import {
configureSecretStore,
getSecretStore,
} from "@saflib/vendors-infisical";
configureSecretStore();
const store = getSecretStore();Mock behavior
As a convention throughout SAF, if a key or client id of an integration is set to "mock", then the integration is mocked. This goes with the secret store as well; if the value does not exist then the secret store should return "mock" so that in tests and development, the mock is used.
Vendor implementations
Production backends implement SecretStore in vendor packages:
@saflib/vendors-infisical— Infisical vault
Infisical connection env (INFISICAL_TOKEN, INFISICAL_PROJECT_ID, INFISICAL_ENVIRONMENT) is declared on @saflib/vendors-infisical. Sentinel "mock" for INFISICAL_TOKEN selects the mock Infisical client.
Use createSecretStore({ type: "env" }) or INFISICAL_TOKEN=mock locally; call configureSecretStore() at startup in production. Other vendors (e.g. @saflib/vendors-brevo) fetch API keys through the configured store.
Integration
Service bootstrap calls setSecretStore (via a vendor configure* helper) before wiring email, object storage, or other integrations that need secrets at runtime.