Backup Bundle
Writes one restorable backup: every included file encrypted under a bundle key, the vault keypair sealed under the operator's passphrase, and a manifest recording what the bundle holds and the digest of each entry.
The passphrase protects the vault key rather than each file, and the bundle key encrypts the files, so a restore derives from the passphrase once and the file count does not multiply the derivations.
The output directory has to be a path that does not exist yet. Writing over an existing one could mix entries from two backups and produce a manifest describing neither, so the call refuses instead of merging.
b.backupBundle.create(opts) #
{
dataDir: string, // required; must exist
outDir: string, // required; must not exist
passphrase: string, // required; Buffer or string
vaultKeyJson: string, // required; the in-memory vault keypair JSON
files: array, // required; non-empty include entries
metadata: object, // carried into the manifest
sign: boolean, // false writes the manifest unsigned
signOptional: boolean, // true continues when signing is unavailable
progressCallback: object, // function (event) per phase
}
Write a bundle and resolve with { manifest, manifestPath, outDir, bundleSize, fileCount, durationMs }.
dataDir has to exist and outDir has to not: an existing outDir raises backup-bundle/outdir-exists rather than being written into. passphrase seals the vault keypair supplied as vaultKeyJson, which is the in-memory keypair from b.vault.getKeysJson(). files lists what to include and must not be empty.
Each missing requirement has its own code, so a failed call says which one: backup-bundle/no-datadir, backup-bundle/no-outdir, backup-bundle/no-passphrase, backup-bundle/no-vault-key-json and backup-bundle/no-files.
An include entry is refused with backup-bundle/bad-include when it carries no relativePath, backup-bundle/bad-kind for a kind outside the set the manifest accepts, backup-bundle/missing-required when an entry marked required is not on disk, backup-bundle/not-a-file when its path is a directory, backup-bundle/empty when the include list resolves to nothing to write, and backup-bundle/short-read when a file returns fewer bytes than its size said, which would otherwise put a truncated entry in the bundle under a correct digest. A signing failure the signOptional escape does not cover raises backup-bundle/sign-failed.
The manifest is signed unless sign is false. It is a toggle rather than a key: the signature comes from the deployment's audit-signing key, so b.auditSign.init has to have run for a bundle to be signed. When it has not, the bundle is written unsigned and the progress callback reports a manifest-unsigned phase with audit-sign-not-initialized, so an operator can see that the bundle cannot later be proven to be theirs. Any other signing failure raises backup-bundle/sign-failed unless signOptional is true, which records the reason and keeps the backup.
sign and signOptional must be booleans, raising backup-bundle/bad-opt otherwise. A "false" for sign read as "not false" and signed anyway, while one for signOptional read as "not true" and refused the bundle, so a typo in either moved the outcome without saying so.
progressCallback receives a phase per step and a done event carrying the file count, bundle size and duration.
var b = require("@blamejs/core");
var res = await b.backupBundle.create({
dataDir: "./data",
outDir: "./backups/2026-10-06",
passphrase: process.env.BACKUP_PASSPHRASE,
vaultKeyJson: b.vault.getKeysJson(),
files: [{ relativePath: "app.db" }],
});
res.fileCount; // → 1
res.manifestPath; // → the manifest a restore reads first