- Docs
- Bureau — Red & Blue (dual-use)
- Ember
Bureau — Red & Blue (dual-use)
Ember
Ember combines four orthogonal physical side-channels (power, EM, acoustic, thermal) into a single per-(model, hardware) fingerprint. A single channel can be suppressed or spoofed; the cost of spoofing four simultaneously is substantially higher.
Posture: 🟣 Red & Blue (dual-use) · Status: alpha
What it does
Ember is the multi-modal side-channel attestor. Where Power-Ledger reads only the PSU's millivolt trace and Tempest-Witness reads only the GPU's electromagnetic emanation, Ember fuses four orthogonal physics channels into one per-(model, hardware) fingerprint:
- Power – PMBus rail-mV trace from the PSU.
- EM – RTL-SDR or HackRF IQ capture at DDR-refresh harmonics.
- Acoustic – USB-microphone spectrogram of the chassis fan; fan PWM (pulse-width modulation) tracks load with model-specific transfer curves.
- Thermal – FLIR Lepton frame deltas; different models pin attention heads to different streaming multiprocessors, producing model-specific die hotspot patterns.
"Orthogonal" here means no single countermeasure suppresses all four channels. A Faraday cage suppresses EM but not heat; a capacitor bank smooths the power rail but does not silence the fan. Spoofing all four channels simultaneously requires a substantially larger attacker budget than spoofing one. Ember is the highest-confidence model-identity attestation in Bureau and is the appropriate primitive for evidentiary use.
Who would use it
- An enterprise AI customer building a litigation-grade attestation package against a non-cooperative vendor.
- A national security auditor verifying foreign-vendor compute compliance.
- A regulator (FTC, EU AI Office) building a courtroom-ready dossier.
- A datacenter operator selling premium-tier model attestation to enterprise tenants.
- An AI safety researcher demonstrating that vendor self-reports are mathematically falsifiable.
What you'll need
- The Pluck CLI (
npm install -g @sizls/pluck-cli). - All four sensors: a PMBus-capable PSU, an RTL-SDR or HackRF, a USB lavalier microphone, and a FLIR Lepton breakout. Total cost about $400 for the casual config.
- A reader device per channel (or one reader with four sensors wired in). Each reader holds an Ed25519 signing key.
- A registered fingerprint per (model, hardware) tuple. You generate this once at commissioning by running known workloads under controlled conditions.
Step-by-step
The alpha runs the full constraint chain on synthetic four-channel samples – there is no live multi-sensor reader integration yet. Production capture ships in a follow-up. To exercise the system today:
pluck bureau ember demo
Expected output: the system registers a (GPT-4, hwA) and a (Llama-3-70B, hwA) fingerprint pair across all four channels, ingests four reader-signed multi-modal samples (one baseline plus three contradictions: model-swap, rack-mismatch, channel-spoof), and emits three signed contradiction proofs. Each proof carries the per-channel deviation breakdown and the cross-channel agreement score.
What to do with the output: in production the four channels stream simultaneously and the reconciliation engine fuses them in real time. Ember proofs are the strongest single artifact you can submit to a regulator or court for AI workload identity.
Run it yourself
Drop this into a Node 18+ project (npm install @sizls/pluck-bureau-ember @sizls/pluck-bureau-core tsx):
// index.ts
import { createHash } from "node:crypto";
import {
createEmberSystem,
fingerprintPrivateKey,
signCanonicalBody,
type ChannelObservation,
type EmberChannel,
type EmberFingerprint,
type MultiModalSample,
} from "@sizls/pluck-bureau-ember";
import { generateOperatorKey } from "@sizls/pluck-bureau-core";
async function main() {
const operator = generateOperatorKey();
const reader = generateOperatorKey();
const auditor = generateOperatorKey();
const sensors = {
power: fingerprintPrivateKey((generateOperatorKey()).privateKeyPem),
em: fingerprintPrivateKey((generateOperatorKey()).privateKeyPem),
acoustic: fingerprintPrivateKey((generateOperatorKey()).privateKeyPem),
thermal: fingerprintPrivateKey((generateOperatorKey()).privateKeyPem),
} satisfies Record<EmberChannel, string>;
const readerFp = fingerprintPrivateKey(reader.privateKeyPem);
const auditorFp = fingerprintPrivateKey(auditor.privateKeyPem);
const rackA = digest("rack:rack-a");
const hwA = digest("hardware:gpu-001");
const ember = createEmberSystem({
signingKey: operator.privateKeyPem,
disablePausePoll: true,
disableLogging: true,
});
try {
// Register the GPT-4 baseline on hwA across all 4 channels.
ember.registerFingerprint(buildFp("gpt-4-turbo", hwA, auditor.privateKeyPem, auditorFp, vec(0.7, 0.3, 0.5), vec(0.65, 0.35, 0.45), vec(0.55, 0.45, 0.5), vec(0.6, 0.4, 0.5)));
ember.registerFingerprint(buildFp("llama-3-70b", hwA, auditor.privateKeyPem, auditorFp, vec(0.2, 0.8, 0.4), vec(0.25, 0.75, 0.35), vec(0.3, 0.7, 0.4), vec(0.25, 0.7, 0.35)));
// Model-swap: vendor claims GPT-4 but every channel screams Llama.
const sample = buildSample("2026-04-26T00:00:01.000Z", reader.privateKeyPem, readerFp, sensors, rackA, hwA, vec(0.2, 0.8, 0.4), vec(0.25, 0.75, 0.35), vec(0.3, 0.7, 0.4), vec(0.25, 0.7, 0.35));
ember.observeSample(sample);
ember.claimVendor({ sampleId: sample.sampleId, claimedRackId: rackA, claimedModelFamilyId: "gpt-4-turbo" });
for (let i = 0; i < 60; i++) await new Promise((r) => setImmediate(r));
const proofs = ember.facts.proofs();
console.log(`ember proofs = ${proofs.length}`);
for (const p of proofs) console.log(`kind=${p.kind} model=${p.fingerprint.modelFamilyId}`);
} finally {
await ember.shutdown();
}
}
function digest(s: string): string { return createHash("sha256").update(s).digest("hex"); }
function vec(a: number, b: number, c: number): number[] {
const out = new Array<number>(64);
for (let i = 0; i < 64; i++) {
const phase = (i / 64) * Math.PI * 2;
out[i] = a * Math.sin(phase) + b * Math.cos(phase * 2) + c * Math.sin(phase * 3 + 0.3);
}
return out;
}
function obs(channel: EmberChannel, featureVector: number[], sensorFingerprint: string, seed: string): ChannelObservation {
return { channel, rawDigest: createHash("sha256").update(`${channel}:${seed}`).digest("hex"), featureVector, sensorFingerprint };
}
function buildSample(timestamp: string, readerKey: string, readerFingerprint: string, sensors: Record<EmberChannel, string>, rackId: string, hardwareId: string, p: number[], e: number[], a: number[], t: number[]): MultiModalSample {
const seed = timestamp + rackId + hardwareId;
const power = obs("power", p, sensors.power, seed);
const em = obs("em", e, sensors.em, seed);
const acoustic = obs("acoustic", a, sensors.acoustic, seed);
const thermal = obs("thermal", t, sensors.thermal, seed);
const skeleton = { schemaVersion: 1 as const, rackId, hardwareId, power, em, acoustic, thermal, timestamp, readerFingerprint };
const sampleId = createHash("sha256").update(JSON.stringify(skeleton)).digest("hex");
const signed = signCanonicalBody({ ...skeleton, sampleId }, readerKey);
return { ...skeleton, sampleId, signature: signed.signature };
}
function buildFp(modelFamilyId: string, hardwareId: string, auditorKey: string, auditorFingerprint: string, p: number[], e: number[], a: number[], t: number[]): EmberFingerprint {
const skeleton = { schemaVersion: 1 as const, modelFamilyId, hardwareId, powerCentroid: p, emCentroid: e, acousticCentroid: a, thermalCentroid: t, powerStddev: 0.05, emStddev: 0.05, acousticStddev: 0.05, thermalStddev: 0.05, sampleCount: 64, registeredAt: "2026-04-26T00:00:00.000Z", auditorFingerprint };
const fingerprintId = createHash("sha256").update(JSON.stringify(skeleton)).digest("hex");
const signed = signCanonicalBody({ ...skeleton, fingerprintId }, auditorKey);
return { ...skeleton, fingerprintId, signature: signed.signature };
}
main().catch((err) => { console.error(err); process.exit(1); });
Run with tsx index.ts. Expected output:
ember proofs = 1
kind=model-swap model=gpt-4-turbo
Open in StackBlitz – runs in your browser, no install required.
What you get
A signed Ember.Proof for every contradiction with one of three kind values:
model-swap– combined cross-channel deviation greater than 3 standard deviations from baseline; consistent with an undisclosed model substitution.rack-mismatch– vendor claim binds a model to "rack 42" but the rack's combined emanation profile is consistent with a different rack.channel-spoof– three channels agree while the fourth diverges sharply, consistent with single-channel suppression (RF jamming, capacitor-bank power filtering, or a single-channel decoy).
Each proof carries the per-channel feature vector digests, deviation magnitudes, the agreement score, and a detached Ed25519 signature.
What it can't do
- The reader devices are trust anchors. If all four readers are compromised by the same adversary, the fusion is compromised. In practice you place readers from different vendors with different supply chains, which raises the bar dramatically.
- A vendor with full physical control of the rack and unlimited budget could in principle build a four-channel decoy – a separate machine that emits the right power, EM, thermal, and acoustic profile while a different machine actually runs the workload. This is expensive and operationally hard to maintain.
- Ember does not identify what model ran in place of the claimed one – it just proves the claim is false. To name the imposter, register more centroids.
A real-world example
A pharmaceutical company contracts with an AI provider for protein-folding inference, expecting a specific frontier model. An internal report suggests the provider may be substituting a smaller open-source model during off-hours. The compliance team installs Ember on a representative rack – power reader, RTL-SDR, microphone, FLIR – and runs continuous capture for two weeks. During weekday business hours, all four channels classify as the contracted frontier model. From Friday evening through Monday morning, three of four channels classify as a smaller Llama variant while the EM channel remains consistent with the contracted model (consistent with an EM decoy). Ember emits 71 channel-spoof proofs across the two weekends. The Rekor entries are filed with a contract-dispute proceeding, and the provider settles.
For developers
Predicate URIs
| URI | What it attests |
|---|---|
https://pluck.run/Ember.Sample/v1 | Reader-signed multi-modal observation across all 4 channels. Each channel carries its own digest, feature vector, and sensor signing-key fingerprint. |
https://pluck.run/Ember.Fingerprint/v1 | Auditor-signed per-(model, hardware) cross-channel fingerprint with per-channel centroids and stddevs. |
https://pluck.run/Ember.Proof/v1 | Bureau-signed contradiction proof with kind (model-swap, rack-mismatch, channel-spoof) and per-channel deviation + agreement detail. |
Programs composed
- Power-Ledger – single-channel power side-channel attestor.
- Tempest-Witness – single-channel EM side-channel attestor.
- Oath / Dragnet – vendor identity binding upstream of the rack/model claims.
- Thermal-Afterglow – overlapping thermal-IR domain but different detection class.
Threat model + adversary
The adversary is the vendor with full physical control over the rack. Their cheapest move (single-channel fake) is caught by Ember's agreement score. Their next-cheapest move (multi-channel decoy or shielding) is expensive enough to make silent model swaps unprofitable at scale. See Threat Model.
Verify a published cassette
pluck bureau verify <bundle-dir>
cosign verify-blob --key <pubkey.pem> --signature <sig> --type https://pluck.run/Ember.Proof/v1 <body.json>
Every signed shape is a detached Ed25519 signature over canonical JSON, optionally notarized into Sigstore Rekor as a DSSE in-toto envelope.
See also
- Bureau Foundations
- Threat Model
- Verify a dossier
- Power-Ledger – single-channel power side-channel attestor
- Tempest-Witness – single-channel EM side-channel attestor
- Thermal-Afterglow – IR-camera observation chain (overlapping thermal physics, different detection class)