Certificates
Turnkey TLS-certificate manager. Wraps b.acme.create (RFC 8555 client + RFC 9773 ARI renewal-window respect), sealed persistence via b.vault.seal, the renewal scheduler from b.safeAsync.repeating, OCSP-stapling via b.network.tls.ocsp, and the operator's choice of ACME challenge solver (HTTP-01 / DNS-01 / TLS-ALPN-01).
The operator passes a declarative manifest of certificates + storage + an ACME directory URL + per-challenge solver callbacks; the manager handles ordering, finalization, retrieval, periodic renewal, key rotation on renew, OCSP refresh, and sealed-disk persistence of every artifact.
Composes: - b.acme.create → ACME orders, JWS, ARI fetch - b.vault.seal → sealed-disk persistence of certs + keys + account material - b.safeAsync.repeating → renewal scheduler with drop-silent error path - b.network.tls.ocsp → fetches + caches a validated OCSP response per cert for server-side stapling - b.audit → cert.* lifecycle audit chain - b.compliance → validates the declared posture names; storage-confidentiality postures hold because keys/certs are always sealed at rest
Does NOT ship the challenge-solver implementations (HTTP-01 server, DNS provider integrations, TLS-ALPN-01 socket). Those are operator- side adapters — the manager calls operator-provided provision(challengeParams) / cleanup(challengeParams) callbacks for whatever solver the operator wires.
Key escrow: when keyEscrow: { recipient } is set, the renewed private key is also encrypted to the recipient's public key via b.crypto.encryptEnvelope and persisted alongside the sealed key. The recipient is operator-controlled (typically an offline break-glass key); the escrow copy is for legitimate key-recovery under break-glass policy, NOT for routine access.
b.cert.create(opts) #
{
storage: {
type: "sealed-disk", // only backend in v1 — operator-supplied storage extensible via the same shape
rootDir: string, // required — directory under which sealed artifacts land
vault: b.vault.Store, // optional — defaults to b.vault.getDefaultStore()
},
acme: {
directory: string, // required — RFC 8555 directory URL (https://)
contactEmail: string, // optional — mailto: contact registered on account
accountKey: { privatePem, publicPem } | "auto", // "auto" → generate + persist on first start; sealed via storage.vault
timeoutMs: number, // optional — per-HTTP-call timeout; defaults from b.acme.create
ariCompliant: boolean, // optional, default true — RFC 9773 ARI renewalInfo respect
},
certs: Array<{
name: string, // required — unique manifest identifier; used as subdirectory + lookup key
domains: Array, // required — first entry is the CN subject; rest are SANs
keyAlg: "ecdsa-p256" | "ecdsa-p384" | "rsa-2048" | "rsa-3072" | "rsa-4096", // default "ecdsa-p256"
challenge: {
type: "http-01" | "dns-01" | "tls-alpn-01",
provision: async function (params) { ... }, // required — operator wires the solver
cleanup: async function (params) { ... }, // required — runs after authorization completes
},
keyEscrow: { // optional — break-glass-only key recovery
recipient: string | { publicKey, ecPublicKey }, // ML-KEM-1024 pubkey PEM, or a
// b.crypto.generateEncryptionKeyPair() hybrid pair; the
// renewed key is sealed to it via b.crypto.encrypt and
// recovered offline with b.crypto.decrypt
},
}>,
renew: {
intervalMs: number, // default 6h — poll cadence
minDaysBeforeExpiry: number, // default 14 — renew if , // optional — posture names (e.g. ["hipaa"]); validated against b.compliance.KNOWN_POSTURES (throws on an unknown name) + surfaced on getContext().compliance. Cert keys/certs are always sealed at rest, so storage-confidentiality postures hold by construction.
}
Build a turnkey cert-management handle. Composes b.acme.create for the ACME protocol layer, b.vault.seal for sealed-disk persistence, b.safeAsync.repeating for the renewal scheduler, and b.network.tls.ocsp for stapling.
The handle exposes: - start() — ensures every manifest cert exists (issues if absent); starts the renewal scheduler. - stop() — halts the renewal scheduler; releases sealed handles. - getContext(name) — returns { cert, key, ca, expiresAt, fingerprintSha256 } (PEM strings + meta) for the named cert. - sniCallback — function (servername, cb) suitable for https.createServer({ SNICallback }) — looks up by SNI hostname, falls back to the first registered cert. - refresh(name) — force-renew the named cert NOW (operator override). - on(event, fn) — cert.issued / cert.renewed / cert.renew-failed / cert.ocsp-refreshed.
var mgr = b.cert.create({
storage: { type: "sealed-disk", rootDir: "/var/lib/blamejs/certs" },
acme: {
directory: "https://acme-v02.api.letsencrypt.org/directory",
contactEmail: "ops@example.com",
accountKey: "auto",
},
certs: [
{
name: "main",
domains: ["example.com", "www.example.com"],
keyAlg: "ecdsa-p256",
challenge: {
type: "http-01",
provision: async function (p) { await myHttp01Server.add(p.token, p.keyAuthorization); },
cleanup: async function (p) { await myHttp01Server.remove(p.token); },
},
},
],
});
await mgr.start();
var ctx = await mgr.getContext("main");
typeof ctx.cert; // → "string" (PEM chain)
typeof ctx.key; // → "string" (PEM)
typeof ctx.expiresAt; // → "number" (epoch ms)
Last updated 2026-08-08T16:39:49.652Z by seeder.