Config Drift

Monitor + alert when runtime config diverges from a declared baseline.

The framework's audit chain captures DATA writes (every row, every key change). It does NOT capture RUNTIME CONFIG — an operator who silently changes allowedOrigins three weeks ago leaves no signal. b.configDrift fills that gap: at every boot the operator passes the baseline snapshot they want tracked. The primitive hashes it with SHA3-512, signs the digest with the audit-signing key, and writes the result to a sidecar at /config-baseline.sig. On the next boot the sidecar is loaded, verified, and diffed against the new snapshot. Drift surfaces as an audit event (config.drift.detected); no boot block — the operator may have a legitimate reason to change config, and the framework's job is to make the change auditable, not to refuse to start.

The signed sidecar uses b.auditSign — same SLH-DSA-SHAKE-256f keypair the audit chain anchors on. An attacker who flips a config value would also need to forge the signing key to update the sidecar cleanly; otherwise next-boot verify catches the tamper.

b.configDrift.verifyVendorIntegrity is a sibling primitive that re-hashes every file under lib/vendor/ against the manifest's sha256 digests at boot — catches a half-applied vendor refresh, a corrupted install, or a vendored cjs modified without a manifest update.

b.configDrift.create(opts) #

stable0.6.0
{
  dataDir:      string,    // directory holding the baseline sidecar (required)
  audit:        object,    // b.audit instance; pass false to disable
  baseline:     string,    // baseline name — sidecar is `config-baseline-.sig`
  criticalKeys: string[],  // keys whose drift raises severity to "high"
  ignoreKeys:   string[],  // keys excluded from drift detection
}

Build a per-baseline drift detector bound to a dataDir. Returns a handle exposing .checkpoint(snapshot) (write or compare against the signed sidecar), .read() (load + verify the sidecar without mutating it), and .sidecarPath (absolute path of the sidecar file).

Drift on a key listed in opts.criticalKeys surfaces as config.drift.detected with severity: "high" and outcome failure; drift in any other key surfaces as severity: "low" and outcome success. When criticalKeys is omitted every key is treated as high severity. Keys listed in opts.ignoreKeys are captured in the snapshot but never raise a drift event.

// requires: write access to the dataDir below
var fakeAudit = { safeEmit: function () {} };
var detector = b.configDrift.create({
  dataDir:      "/tmp/blamejs-drift-demo",
  audit:        fakeAudit,
  criticalKeys: ["allowedOrigins", "csp"],
  ignoreKeys:   ["bootCount"],
});
detector.sidecarPath;
// → "/tmp/blamejs-drift-demo/config-baseline.sig"

var first = await detector.checkpoint({
  allowedOrigins: ["https://app.example.com"],
  csp:            "default-src 'self'",
  bootCount:      1,
});
first.signed;     // → true
first.drifted;    // → false
first.previousAt; // → null

b.configDrift.verifyVendorIntegrity(opts) #

stable0.7.39
{
  libVendorDir: string,  // absolute path to the lib/vendor tree to verify; default: the framework's own (cwd-independent). Per-file manifest paths resolve under this directory.
  manifestPath: string,  // absolute path to MANIFEST.json (defaults under libVendorDir)
}

At-boot integrity check over lib/vendor/*. MANIFEST.json carries a sha256 digest per bundled file; the call re-hashes each one and surfaces mismatches without throwing. Returns { ok, checkedCount, mismatches } and emits vendor.integrity.verified (success) or vendor.integrity.tampered (failure) on every invocation so a corrupted install lands in the audit chain at boot, not later.

Throws config-drift/vendor-manifest-missing when MANIFEST.json is absent and config-drift/vendor-manifest-shape when its top-level packages is missing, null, an array, or an object with no packages in it, so an operator sees a hard fail instead of a silent zero-files-checked pass. An entry that cannot be verified, because it names no path or carries no hash, and a package that declares no files at all, are reported as a mismatch with actual: "" for the same reason. A run that verified nothing therefore never returns ok: true.

It does not abort the process on a mismatch. Read ok and stop the boot yourself; SECURITY.md's operator checklist carries the shape.

var result = b.configDrift.verifyVendorIntegrity();
result.ok;                       // → true
typeof result.checkedCount;      // → "number"
result.mismatches;               // → []

// At boot, before any listener opens. The call reports; stopping is yours.
var integrity = b.configDrift.verifyVendorIntegrity();
if (!integrity.ok) {
  console.error("vendored artifact mismatch", integrity.mismatches);
  process.exitCode = 1;
}
integrity.ok;                    // → true

Last updated 2026-10-12T14:21:56.879Z by seeder.