- Docs
- Bureau — Blue Team (defensive)
- Neuro-Consent
Bureau — Blue Team (defensive)
Neuro-Consent
Brain-computer interfaces can be susceptible to adversarial visual stimuli that drive their classifiers toward commands the user did not intend. Neuro-Consent signs every motor command emitted by a BCI together with the visual stimulus, the EEG digest, and the user's signed consent envelope, providing a verifiable record for neural-rights audits.
Posture: 🔵 Blue Team (defensive) · Status: alpha (moonshot)
What it does
A Brain-Computer Interface (BCI) reads electrical activity from the scalp (EEG = electroencephalography), classifies the signal, and emits motor commands – a cursor click, a text-spelling letter, a wheelchair direction. Two BCI paradigms dominate consumer and medical deployment. P300 spellers show a letter grid that flashes one row/column at a time at ~6 Hz; the brain emits a signature spike (the P300) when the row containing the user's intended letter flashes; the classifier reads which letter the user wants. SSVEP (Steady-State Visual Evoked Potential) shows the user several flickering targets at distinct frequencies; the brain entrains to the target the user is attending to.
Researchers have shown – with peer-reviewed adversarial-flicker demonstrations – that a carefully-chosen flickering visual stimulus can prompt-inject these classifiers. The result for a P300 speller is the wrong letter; for a wheelchair SSVEP, the wrong direction; for a financial-approval BCI, an approval the user did not consent to. Chile passed neural-rights legislation in 2021 making this an explicit area of law. Other jurisdictions are following.
Neuro-Consent is the first neural-rights-grade audit primitive. Every motor command emitted by a BCI is signed with a tuple of (rawEegDigest, stimulusFrameDigest, classifierVersion, commandKind, userIdHash, consentedCommandKinds). Raw EEG bytes never appear in any signed body – only the sha256 digest. Raw stimulus pixels never appear – only the digest. The user-id appears only as a sha256 hash.
Who would use it
- A medical-device company (Neuralink, Synchron, Blackrock Neurotech, BrainGate) shipping consumer or clinical BCIs who needs neural-rights compliance observations per Chile's law and forthcoming EU/US versions.
- A neural-rights regulator (Chilean Senate, EU Parliament committee, US FDA neural-rights working group) auditing whether vendors honor the user's consent envelope.
- A patient advocacy group (ALS Association, Christopher Reeve Foundation) representing paralyzed BCI users who need cryptographic observations of unauthorized commands.
- A BCI security researcher publishing an adversarial-flicker disclosure who needs reproducible signed reconstructions.
What you'll need
- The Pluck CLI installed (
npm i -g @sizls/pluck-cli). - For real deployment: an OpenBCI / g.tec / Blackrock EEG headset, a stimulus rendering pipeline, and a P300 / SSVEP classifier. The hardware bridge and the real adversarial-flicker classifier are deferred today.
- A user-defined consent envelope – the list of command kinds the user has authorized (e.g.,
["yes", "no", "select-letter"]but NOT["transfer-funds"]). - A citizen Ed25519 keypair, distinct from the operator's. The citizen signs a
CitizenConsentEnvelopebinding their consented command kinds plus a validity window (validFrom .. validUntil). The operator threads that envelope onto eachBciCommand, and the Bureau verifies the citizen's signature against the citizen's published SPKI fingerprint at attest time. This keeps a compromised operator from forging consent on the citizen's behalf – the consent attestation rides a key the operator does not hold.
Step-by-step
pluck bureau neuro-consent demo
The demo synthesizes four BCI commands: one legit "yes" inside the consent envelope (no proof), one "approve-transaction" with adversarial flicker (fires adversarial-flicker-detected AND consent-violation), one "transfer-funds" with no adversarial signal (fires consent-violation only), and one stale-classifier-version "yes" (fires classifier-version-mismatch).
neuro-consent/demo: ingesting 4 BciCommands -> 3 NeuroConsentProofs.
[Bureau/NEURO-CONSENT] proof=9212b0f3… kind=adversarial-flicker-detected
[Bureau/NEURO-CONSENT] proof=08a50173… kind=consent-violation
[Bureau/NEURO-CONSENT] proof=ffeb7587… kind=classifier-version-mismatch
Production CLI (capture-eeg from the headset, capture-stimulus from the rendering pipeline, command to emit a motor command, verify to audit a published command) lands in a follow-up.
Run it yourself
Drop this into a Node 18+ project (npm install @sizls/pluck-bureau-neuro-consent @sizls/pluck-bureau-core tsx). Real adversarial-flicker classifier integration is research-required; the example fires consent-violation deterministically with a single command outside the user's signed envelope.
// index.ts
import { createHash } from "node:crypto";
import {
createNeuroConsentSystem,
fingerprintPrivateKey,
signCanonicalBody,
} from "@sizls/pluck-bureau-neuro-consent";
import { generateOperatorKey } from "@sizls/pluck-bureau-core";
const sha256 = (s: string) => createHash("sha256").update(s).digest("hex");
const flush = (n = 80) => new Promise<void>((r) => { let i = 0; const tick = () => (++i >= n ? r() : setImmediate(tick)); setImmediate(tick); });
async function main() {
const op = generateOperatorKey();
const opFp = fingerprintPrivateKey(op.privateKeyPem);
const system = createNeuroConsentSystem({
signingKey: op.privateKeyPem,
expectedClassifierVersion: "p300-classifier-v3.2",
disablePausePoll: true,
disableLogging: true,
});
// The user consented to yes/no – `transfer-funds` is outside the envelope.
const cmdBody = {
schemaVersion: 1 as const,
commandKind: "transfer-funds",
rawEegDigest: sha256("raw-eeg:trial-1"),
stimulusFrameDigest: sha256("raw-frame:legit"),
classifierVersion: "p300-classifier-v3.2",
userIdHash: sha256("user-id:subject-1"),
consentedCommandKinds: ["yes", "no"] as const,
operatorFingerprint: opFp,
emittedAt: "2026-04-15T11:00:00.200Z",
};
const commandId = sha256(JSON.stringify(cmdBody));
const { signature } = signCanonicalBody({ ...cmdBody, commandId }, op.privateKeyPem);
try {
system.observeCommand({ ...cmdBody, commandId, signature });
await flush();
for (const p of system.facts.proofs()) {
console.log(`proof kind=${p.kind} id=${p.proofId.slice(0, 16)}…`);
}
} finally {
await system.shutdown();
}
}
main().catch((err) => { console.error(err); process.exit(1); });
Run with tsx index.ts. Expected output:
proof kind=consent-violation id=…
▶ Open in StackBlitz – runs in your browser, no install required.
What you get
A BciCommand envelope per motor command containing the EEG digest, stimulus-frame digest, classifier version, command kind, user-id-hash, and the consent envelope active at that moment – all Rekor-anchored.
Optionally, a citizen-side CitizenConsentEnvelope rides alongside the command. Where the operator-signed consentedCommandKinds field on the command body is the operator's claim about what the user agreed to, the envelope is the citizen's OWN signed attestation – a separate Ed25519 body keyed to the citizen, scoped to a validFrom .. validUntil window, and verified by the Bureau against the citizen's published SPKI fingerprint. Set requireCitizenConsent: true on createNeuroConsentSystem and any envelope-less command is dropped fail-closed.
Mint an envelope and ship it on a command:
import {
signConsentEnvelope,
createNeuroConsentSystem,
} from "@sizls/pluck-bureau-neuro-consent";
import {
generateOperatorKey,
derivePublicKeyPem,
} from "@sizls/pluck-bureau-core";
// Citizen mints the envelope with their OWN key.
const citizen = generateOperatorKey();
const envelope = signConsentEnvelope(
{
schemaVersion: 1,
citizenFingerprint: citizen.fingerprint,
consentedCommandKinds: ["yes", "no", "select-letter"],
validFrom: "2026-04-15T00:00:00.000Z",
validUntil: "2026-04-30T00:00:00.000Z",
signedAt: "2026-04-15T00:00:00.000Z",
},
citizen.privateKeyPem,
);
// Operator threads the envelope onto each BciCommand and forwards the
// citizen's public key alongside the dispatch – the Bureau verifies
// the envelope signature against the citizen's fingerprint before any
// command is appended.
const citizenPublicKeyPem = derivePublicKeyPem(citizen.privateKeyPem);
const system = createNeuroConsentSystem({
signingKey: operator.privateKeyPem,
expectedClassifierVersion: "p300-classifier-v3.2",
requireCitizenConsent: true,
});
system.observeCommand({ ...command, consentEnvelope: envelope }, citizenPublicKeyPem);
Three classes of proof:
adversarial-flicker-detected– a flicker classifier returnedisAdversarial: truewith confidence > 0.7 AND the issued command is outside the user's consent envelope. The injection got through.consent-violation– the BCI emitted a command outside the user's signed consent envelope (e.g., the user consented to "yes/no" but the BCI emitted "transfer-funds"). The vendor's classifier exceeded its license.classifier-version-mismatch– the BCI's classifier version doesn't match the latest signed neural-rights manifest, indicating drift after a compromise (attacker swaps in a malicious classifier).
What it can't do
- Real P300 / SSVEP adversarial-flicker classifier is deferred.
detectAdversarialStimulus()returns deterministic test data. Real classifier integration is research-required. - Real EEG hardware bridge is deferred (OpenBCI, g.tec, Blackrock).
- Per-jurisdiction consent vocabulary library deferred – alpha consent envelopes are operator-defined; production needs Chile's neural-rights vocabulary plus EU/US-state-by-state.
- The package signs commands, not intentions. If the BCI hardware mis-classifies what the user wills, Neuro-Consent faithfully signs the misclassification. The proof says "this command was emitted from this EEG given this stimulus" – which is enough to litigate a vendor breach but not enough to prove what the user meant.
- Real Sigstore Rekor
notarizeintegration is stubbed.
A real-world example
A late-stage ALS patient in Santiago, Chile uses a Synchron Switch BCI to spell on a tablet. Her signed consent envelope is ["yes", "no", "select-letter", "select-word"]. In June 2027 her bank deploys a BCI-compatible authorization flow with a flickering "approve" button. Researchers at the University of Chile demonstrate that the flicker pattern, at the chosen frequency, drives the SSVEP classifier toward approve-transaction independent of where the user is looking. Her BCI emits approve-transaction. Neuro-Consent fires both adversarial-flicker-detected (the stimulus matched the adversarial pattern) and consent-violation (the command is not in her envelope). The signed proof becomes the central exhibit in a neural-rights enforcement action under the 2021 Chilean law. The signed record establishes what the EEG, the stimulus, and the consent envelope contained at the moment the command was emitted.
For developers
Predicate URIs
| URI | What it attests |
|---|---|
https://pluck.run/NeuroConsent.EegFeatures/v1 | EEG band-power vector with raw-EEG-digest D at sample rate H, captured at time T. |
https://pluck.run/NeuroConsent.StimulusFrame/v1 | Visual stimulus with raw-frame-digest D at flicker frequency F, rendered at time T. |
https://pluck.run/NeuroConsent.BciCommand/v1 | BCI emitted commandKind K with EEG-digest E, stimulus-digest S, classifier-version V, user-id-hash U, consent envelope L. |
https://pluck.run/NeuroConsent.Proof/v1 | Class: adversarial-flicker-detected | consent-violation | classifier-version-mismatch. |
The signed body never carries raw EEG bytes, raw stimulus pixels, or raw user identity. Only digests, band-power magnitudes, confidence values, and consent enums appear.
Programs composed
- ROTATE – operator-key rotation on classifier-version transitions.
- Custody – cryptographic anchoring of neural-rights manifests.
- Oath – vendor neural-rights commitments.
- Pluck core's DSSE in-toto envelopes + Sigstore Rekor client.
Threat model + adversary
Adversaries include vendors deploying adversarial-flicker UI under regulatory radar, classifier-swap supply-chain attackers, and platforms that issue commands outside the user's stated envelope. Privacy is strong: signed bodies never carry raw EEG / raw stimulus / raw user identity, but they DO carry the digest of the raw EEG, which means a future adversary with the raw bytes can confirm a match (the standard digest-binding tradeoff).
What's stubbed (alpha – moonshot)
- Real P300 / SSVEP adversarial-flicker classifier deferred.
dsseSign/notarizeAttestationRekor integration stubbed.- Per-jurisdiction consent-vocabulary library deferred.
Verify a published cassette
pluck bureau verify <bundle-dir>
cosign verify-blob --key <pubkey.pem> --signature <sig> \
--type https://pluck.run/NeuroConsent.BciCommand/v1 <body.json>