Secrets
Lucent Secrets stores JSON secrets encrypted in the database. It is designed for server-side credentials such as service account private keys, API keys, and integration tokens.
Secrets are encrypted with AES-256-GCM. The encrypted record is stored in
lucent_secrets; the master key must come from outside the database, usually an
environment variable.
Configuration
export default defineLucentConfig({
secrets: {
enabled: true,
masterKey: Bun.env.LUCENT_SECRETS_KEY,
keyVersion: "v1",
},
});
Generate a master key:
import { LucentSecrets } from "@codesordinatestudio/lucent";
console.log(LucentSecrets.generateMasterKey());
Store the generated value in LUCENT_SECRETS_KEY. Keep a backup outside the app
database. If the master key is lost, existing encrypted secrets cannot be
recovered.
Standalone Usage
import { LucentSecrets } from "@codesordinatestudio/lucent";
const secrets = LucentSecrets.create({
adapter,
masterKey: Bun.env.LUCENT_SECRETS_KEY!,
});
const key = LucentSecrets.key("tenant", tenantId, "googleDrive", "serviceAccount");
await secrets.set(key, {
clientEmail,
privateKey,
});
const record = await secrets.require<{ clientEmail: string; privateKey: string }>(key);
Key Convention
Use scoped keys:
scope:ownerId:provider:name
Examples:
tenant:tenant_123:googleDrive:serviceAccount
user:user_456:stripe:apiKey
app:default:resend:apiKey
LucentSecrets.key(scope, ownerId, provider, name) builds this format and
rejects empty parts.
Local API Usage
When secrets.enabled and secrets.masterKey are configured, the Local API
includes lucent.secrets:
const lucent = await getLucent(config);
await lucent.secrets?.set("app:default:resend:apiKey", {
apiKey: "re_...",
});
Rotation
Secrets store a keyVersion beside the encrypted payload. To rotate keys, decrypt
with the old key, re-encrypt with the new key, then retire the old key:
const oldSecrets = LucentSecrets.create({ adapter, masterKey: oldKey, keyVersion: "v1" });
await oldSecrets.rotate("app:default:resend:apiKey", {
adapter,
masterKey: newKey,
keyVersion: "v2",
});
Do not change LUCENT_SECRETS_KEY without rotating existing records first.