feat: add verified NeuroSleep qEEG research ingestion (ADR-051) - #7
Merged
Conversation
Completes the H2 and H3 stages of ADR-051 on top of the H1 verified ingestion commit: a physically separate research artifact and a deterministic research panel, both disabled by default. The research build is separated by Cargo feature rather than by convention. `helix-neurosleep` now gates all bundle verification, signer trust, consent, replay protection, and sealed storage behind a default `native-ingest` feature. The `view`, `config`, and `longitudinal` modules compile without it. The separation is machine-checkable rather than asserted: with `--no-default-features` the crate's entire dependency tree is `serde` and `serde_json`, so the research artifact links no attestation, HMAC, or vault key-custody code at all. `helix-neurosleep-wasm` is a new crate whose only entry point accepts an identity-free `VerifiedNeuroSleepNight` list plus the four research flags. It has no API to enroll a signer, set admission policy, or submit a signed bundle, and every user-visible string it emits is a `&'static str` constant rather than anything interpolated from imported data. The derived view type uses `deny_unknown_fields`, so a payload carrying a study id, subject pseudonym, recording id, or nonce is rejected rather than silently ignored. The UI module renders through `textContent` and `createElement` only, requires the dedicated research WASM artifact rather than falling back, reconstructs all copy client-side from constants, and keeps its own prohibited-claim list. Also in this commit: - Both static safety scripts now fail closed. They previously invoked `rg` inside an `if` condition, so on a host without ripgrep every check exited 127, every condition evaluated false, and each script printed "clean" while testing nothing — silently voiding the AT-10 prohibited-claim evidence. They now use grep, treat a tool error as a failure, refuse to pass when an expected path is missing, and cover `helix-neurosleep-wasm`, which holds the user-facing measurement label and caveat copy. A negative control confirms an injected forbidden claim now produces exit 1. - `deny.toml` pins a permissive-only, crates.io-only dependency graph. The graph is free of copyleft licences. - CI gains a `cargo deny` job and a job running both NeuroSleep safety gates, so neither can rot unnoticed again. - The requirement-evidence trace records the withdrawn safety-script result explicitly instead of quietly amending the affected AT-10 and AT-12 rows. The absolute band-power unit is corrected from `uV2_per_hz` to `uV2` to match the upstream integrated-power contract; PSD-domain quantities such as the theta peak power and aperiodic offset correctly remain `log10_uV2_per_hz`. The upstream contract dependency is still a sibling path pin and is repointed at the published alpha in a follow-up commit.
Replaces the `../../../ruv-neural/ruv-neural-core` path dependency with an exact pin on the released `=0.2.0-alpha.1`. The path dependency could not work outside this developer's machine. CI has no sibling checkout, so the workspace did not build there at all; and because the manifest also carried `version = "=0.1.0"`, any build without the path override resolved to the *published* 0.1.0 crate, which predates the NeuroSleep contract entirely. A release cut from that state would have linked a contract with no NeuroSleep types rather than failing loudly. The pin is exact rather than a range on purpose. Helix verifies bundles the upstream signer produced; if a schema, extractor, or feature definition changed under a compatible-looking version, already-stored records would be reinterpreted by different rules without a new fingerprint. Removing the path dependency also fixes `cargo fmt --all -- --check`, which previously walked into the upstream checkout and reported that repository's unrelated formatting debt as a Helix failure. Verified against the published crate: 232 workspace tests, strict clippy, both wasm32 release builds, 8 UI tests, cargo-audit over 234 dependencies, cargo-deny, and both fail-closed safety gates all pass. The research build's dependency tree resolves to serde and serde_json only.
…heckout
The NeuroSleep tests reached the golden bundle and trust profile through
`include_bytes!("../../../../ruv-neural/ruv-neural-core/tests/fixtures/...")`.
That path only resolves on a machine with the upstream repository checked out
next to this one, so the crate did not compile in CI at all. Pinning the
published upstream crate does not fix it either: `include_bytes!` cannot reach
into a registry dependency's sources.
Both fixtures are now vendored under
`crates/helix-neurosleep/tests/fixtures/upstream-neurosleep-v1/`, copied
verbatim from the exact pinned version with their SHA-256 digests and upstream
paths recorded alongside. Only the Ed25519 verifying key is stored; no private
key material enters this repository.
A vendored copy would normally risk drifting from its source. It cannot drift
silently here, because these fixtures are cryptographically verified by the
same pinned contract code rather than merely parsed: the signature covers every
analytic and method field under RFC 8785 canonicalization. Any upstream change
to a field name, unit, canonicalization, required key, or compatibility
fingerprint makes the fixture stop verifying and fails the suite, which is
precisely when a human should be refreshing it.
The safety boundary script gains a matching structural guard: no source file
may `include_bytes!`/`include_str!` a path that escapes the repository. Local
green was not evidence for this class of bug — the sibling checkout existed on
the development machine — so it needs to be enforced statically. Verified by
negative control: reintroducing such an include produces exit 1.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the Helix side of ADR-051: verified ingestion of signed derived NeuroSleep bundles (H1), a physically separate research WASM artifact (H2), and a deterministic research panel (H3). Every capability is off by default.
Pairs with the upstream contract released as
ruv-neural-core 0.2.0-alpha.1(ruvnet/ruv-neural#5, #6, #7).What this is — and is not
This ingests a sleep and qEEG phenotype. It does not produce an Alzheimer's estimate, a microglial claim, a health score, a treatment recommendation, or a participant alert, and there is no code path by which it could: the output model has no such field, and a static gate fails the build if one appears.
The underlying finding is a preclinical APP/PS1 mouse study. The UI says "change from personal baseline associated with emerging research" and carries an explicit preclinical caveat; it never implies a human clinical marker.
Trust boundary
Helix verifies signatures itself rather than delegating across the repository boundary, against a separately enrolled trust key — a self-supplied trust root is rejected. Ingestion binds signer, study, subject, and consent scope; rejects replay; and seals derived records atomically under participant-opaque identifiers. Raw EEG never crosses into this repository — only versioned, signed, derived bundles.
The dependency is pinned exactly (
=0.2.0-alpha.1), not by range. Helix verifies what the upstream signer produced; a compatible-looking version carrying a changed schema or extractor would silently reinterpret already-stored records without a new fingerprint.The research build is separated by construction
helix-neurosleepgates all verification, trust, and storage behind a defaultnative-ingestfeature. The separation is machine-checkable, not asserted:No
ruv-neural-core, nohelix-vault, nosha2/hmac. The research artifact links no attestation or key-custody code at all.helix-neurosleep-wasmaccepts only identity-free verified nights plus the four flags. It has no API to enroll a signer, set policy, or submit a bundle. Its view type usesdeny_unknown_fields, so a payload carrying a study id, subject pseudonym, recording id, or nonce is rejected, not ignored. Every user-visible string is a&'static strconstant. The UI renders viatextContent/createElementonly — noinnerHTMLanywhere.A safety gate that was silently passing
Both static safety scripts were failing open. They invoked
rginside anifcondition;rgwas not installed, so every check exited 127, every condition evaluated false, and each script printedcleanhaving tested nothing. This voided the AT-10 prohibited-claim evidence recorded earlier in the requirement trace.They now use
grep, treat a tool error as a failure, refuse to pass vacuously when an expected path is missing, and coverhelix-neurosleep-wasm(which holds the user-facing copy). Both were re-verified by negative control — an injectedmicroglial activation detectedstring produces exit 1. The requirement trace records the withdrawal explicitly rather than quietly amending the affected rows.New CI jobs run both gates and
cargo denyon every change so this cannot rot unnoticed again.Verification
Not claimed
ADR-051 and AT-01 through AT-12 are not complete. Numeric parity against the frozen reference (AT-02/AT-03) is unproven — no pinned SciPy/FOOOF fixtures exist. Sealed storage is in-memory, so withdrawal, deletion, export ledger, and post-ingest revocation quarantine are absent. The WASM view lacks authenticated native provenance, so it is a trusted-host visualization adapter rather than independent verified ingestion. Sleep-EDF evidence, executed fuzz reports, and browser execution tests remain outstanding.
docs/validation/ADR-051-requirement-evidence.mdtracks all of this per requirement and per acceptance test.