Security

Trust levels

Hosts carry a trust_level of none | software | edr | hardware. The array order in packages/shared/src/index.ts is the rank:

none < software < edr < hardware

trustMeets(level, min) is that rank comparison. Public routing default min_trust is software (DEFAULT_MIN_TRUST in workers/src/routing.ts). The hardware value is listed so a buyer can ask for it and get an honest 503; nothing in this repo grants hardware.

This page is the contract a buyer can rely on. It is not operator-blind marketing. Cross-links: overview, threat model, verify a response, verifiable inference, releases, EDR adapters.

At a glance

TierHow a host gets itWhat a buyer can rely onOperator-blind?
noneDefault. Dev builds (build=dev), unknown/revoked hash, missing keys, failed/stale challenge.Heartbeat liveness (15 s / 45 s offline). Pool/self only.No
softwareReports a blessed release sha256 + Ed25519 over nonce ‖ build_hash at register, then passing 5-min challenges (still-blessed hash, valid sig, posture policy).The host claims a publicly verifiable blessed build and keeps proving possession of its registered key. The coordinator cannot check which binary is actually running — see below. Public-eligible after probation.No — not on Linux/Windows; not on macOS until T28/T72
edrAlready software, plus the org's EDR adapter verifies the reported device id this challenge cycle (T94).Same as software, plus an org-controlled sensor says this device is in the fleet, online (< 10 min), facts match, score ≥ min_score.No. EDR is not a TEE. Root can still read memory.
hardwareReserved (T72).Nothing today. X-NeuronPool-Min-Trust: hardware → 503 No hardware-tier hosts online.n/a

none

Guarantee. The coordinator has a row, a host token, and a recent heartbeat if online. That is all.

How. Register without a blessed build_hash, with build=dev, with a revoked hash, without sign_pubkey, or with a bad build-attestation signature (evaluateTrust in workers/src/blessed.ts). Any failed or unanswered challenge demotes software back here (verifyChallengeAnswer, handleHeartbeatChallenge).

Buyer reliance. Do not send public paid traffic here. The router excludes trust_level === 'none' from public even if sell_idle=1. Pool and self still work — that is the social-pool wedge: friends already trust the machine.

Not proven. Identity beyond "this token registered"; binary integrity; confidentiality.

software

Guarantee. At the last successful challenge (≤ 5 min ago if the host is still online and answering):

  1. The reported build_hash is on blessed_builds and not revoked (T20). The hash is self-reported: the agent computes it and the coordinator has no way to measure the running process. A modified agent can report the blessed hash of an unmodified release. Binding the hash to the running code needs a hardware root (TPM quote / Secure Enclave), which is the reserved hardware tier.
  2. The host signed neuronpool-build-attestation\n{nonce}\n{build_hash} (register) and neuronpool-host-challenge\n{nonce}\n{build_hash}\n{posture} (challenge) with the registered Ed25519 sign_pubkey (T19, T21).
  3. Posture policy: secure_boot !== false. Unknown (null) is allowed. Explicit secure_boot: false demotes to none. SIP / lockdown / debugger_blocked are collected and signed but not gated (T21.4 postureMeetsTier).

Anyone can independently check the hash against Rekor via GET /verify or GET /v1/blessed-builds/:sha256 (T86). Auto-updating hosts re-check manifest signature + cosign identity + Rekor before swapping bits (T89).

How. Run a release binary from the GitHub Release (not tsx / dev). Register with pubkeys. Stay in the 5-min challenge loop. Pass T25 probation (20 canaries, age ≥ 24 h) before public leases. Return logprobs on complete or the host is marked unverifiable and dropped from public (T102).

Buyer reliance.

  • The host says it runs a blessed build of the open-source agent and still holds the key it registered, as of the last challenge. Treat this as an honest-host signal backed by reputation, canaries, and T102 sampling — not as proof of the running binary.
  • Completions that carry X-NeuronPool-Attestation were signed by that host's key (T23 / T103 — see Verifying a response).
  • Public jobs may be T102-sampled. A mismatch costs reputation; quarantine removes the host from public.

Explicitly not claimed.

  • The operator cannot read the prompt. They can. Sealing stops at the agent process (T22). This is the sentence T27 exists to keep in writing.
  • The listed weights are what ran. That is T102/T103, sampled, statistical.
  • Secure Boot / SIP / no-debugger in the strong sense. Only "did not report Secure Boot off" is enforced; null passes.
  • macOS Hardened Runtime, PT_DENY_ATTACH, notarization (T28 shim + posture are in tree; release.yml runs notarytool when Apple secrets exist).

edr

Guarantee. Everything software guarantees, plus: this challenge cycle, the org's configured EDR adapter returned verified for the device id the agent reported (packages/host-agent/src/edr.ts). Falcon (CrowdStrike) checks Hosts + Zero Trust Assessment: device exists, sensor last seen within 10 minutes, hostname/OS match, assessment.overall >= org.min_score (T94).

edr requires software first. An EDR sensor does not replace the blessed-build proof. Failure (offline sensor, unknown AID, low score, provider outage, decrypt failure, disabled config) leaves the host at software — it does not crash the challenge path.

How. Host is in an org; org writes org_edr (provider, sealed credentials, min_score, min_trust, enabled). Agent reports { provider, device_id } at register and every challenge. Coordinator calls resolveEdrTrust after the software challenge verifies.

Buyer reliance. For tenant-pool traffic, an org can set policy min_trust: "edr" (T96) or org_edr.min_trust. Public buyers can send X-NeuronPool-Min-Trust: edr and will 503 if no such public-eligible host is online (T24).

Not proven. Confidential computing. Falcon ZTA is a vendor score, not a memory-encryption proof. Defender for Endpoint and SentinelOne adapters are stubs (contract tests pass; production mapping is a hand-off — see edr-adapters.md).

hardware

Guarantee. None today. TRUST_LEVELS includes the rank so min-trust filters, headers, and the attestation endpoint sort it above edr. evaluateTrust and verifyChallengeAnswer never return it. resolveEdrTrust never promotes to it.

Roadmap (T72 software scaffold; rank reserved). TPM 2.0 quotes over PCR 0–7 and NVIDIA CC via NRAS exist as in-tree fixtures (hardware-tier-gpu.md). Verification does not persist or grant hardware. T28 (PT_DENY_ATTACH shim + posture) is in tree; notarization CI is gated on Apple secrets (DAN-144). T71 is the same class of macOS Secure Enclave scaffold (hardware-tier-macos.md).

Buyer reliance. If you send X-NeuronPool-Min-Trust: hardware you get 503 with message No hardware-tier hosts online. That is the honest response, not a silent downgrade.

How a host moves

register ──evaluateTrust──► none | software
                │
heartbeat every 15 s
                │
         challenge due? (5 min)
                │
         answer signed nonce‖build_hash‖posture
                │
         verifyChallengeAnswer ──fail──► none
                │
              pass ── software
                │
         resolveEdrTrust (if org + sensor)
                │
         verified ──► edr
         else    ──► software (base)

Revoke (POST /v1/hosts/:id/revoke, T26) stamps revoked_at and refuses heartbeat/lease/re-register. It also nulls T19.4 prev_sign_pubkey so a leaked previous key cannot keep answering challenges. Rotate identity keys with neuronpool keys rotate / POST /v1/host/keys/rotate (old-key-signed handover; previous sign key valid for challenges for 24 h). Reputation quarantine (reputation < 40) and unverifiable=1 remove public eligibility without necessarily changing the tier string.

What the buyer sends and sees

InputEffect
(omit)min_trust = api_keys.min_trust or software
X-NeuronPool-Min-Trust: softwarePublic hosts at software or above (incl. edr)
X-NeuronPool-Min-Trust: edrOnly edr/hardware. 503 if none online (and lower-tier hosts existed, or always for hardware)
X-NeuronPool-Min-Trust: hardwareAlways 503 until T72 grants the tier
X-NeuronPool-Min-Trust: noneValid header. Public still excludes none hosts via the public-eligibility filter
Response headerMeaning
X-NeuronPool-TrustServing host's tier (none/software/edr/hardware)
X-NeuronPool-HostFirst 12 hex chars of sha256(host id) — not the raw id
X-NeuronPool-PoolPool id when the job was pool-scoped
X-NeuronPool-Coordinatorcoordinator_id (federation-ready)
X-NeuronPool-AttestationHost signature; see below
Inference-IdJob id (also the attestation message prefix)

GET /v1/providers/attestation (public, Cache-Control: max-age=60) returns online, non-revoked hosts as { host, os, trust_level, build_hash, version, sign_pubkey, last_challenge_at, reputation_band } with no account ids (T24). build_hash / version are omitted for none hosts.

Verifying a response

Two signatures exist. The coordinator puts one of them on X-NeuronPool-Attestation and strips both from the buyer JSON (stripAttestation):

  1. T23.2 attestationjob_id ‖ sha256(content). Use verify-response.md when the host did not send a T103 commitment (legacy complete).
  2. T103 commitmentjob_id ‖ sha256(content) ‖ sha256(canonical logprobs JSON). Preferred when present. This is what current agents send.

T103 verifier (same key as T23; extra 32 bytes):

import { ed25519 } from "@noble/curves/ed25519.js";
import { sha256 } from "@noble/hashes/sha2.js";

function canonicalLogprobsJson(logprobs) {
  const rows = Array.isArray(logprobs) ? logprobs : [];
  return JSON.stringify(
    rows.map((t) => [
      typeof t.token_id === "number" ? t.token_id : null,
      t.token,
      t.logprob,
      (t.top ?? []).map((x) => [typeof x.token_id === "number" ? x.token_id : null, x.token, x.logprob]),
    ]),
  );
}

const jobId = new TextEncoder().encode(inferenceId);
const contentHash = sha256(new TextEncoder().encode(content));
const logprobsHash = sha256(new TextEncoder().encode(canonicalLogprobsJson(logprobs)));
const msg = new Uint8Array(jobId.length + contentHash.length + logprobsHash.length);
msg.set(jobId, 0);
msg.set(contentHash, jobId.length);
msg.set(logprobsHash, jobId.length + contentHash.length);
const sig = Uint8Array.from(atob(header), (c) => c.charCodeAt(0));
const pub = Uint8Array.from(atob(signPubkey), (c) => c.charCodeAt(0));
ed25519.verify(sig, msg, pub);

sign_pubkey comes from GET /v1/providers/attestation (match X-NeuronPool-Host) or from GET /v1/hosts if you own the host. Do not log prompt or response content. A pass means that key signed that job's claimed content (and logprobs). It is not a TEE quote and not a T102 pass.

Posture bits (T21.1 policy constants)

Collected by packages/host-agent/src/posture.ts (best-effort; missing sensor → null, never throws):

BitOSGated for software?
sipmacOS (csrutil status)No
secure_bootLinux (mokutil / lockdown sysfs), Windows (Confirm-SecureBootUEFI)Yes: false rejects; null allowed
lockdownLinux kernel lockdown LSMNo
debugger_blockedBest-effort ptrace / kernel debugNo (T28 reports true only when the shim armed PT_DENY_ATTACH)

none has no posture bar. edr / hardware skip postureMeetsTier's software check (if (tier !== "software") return true) because those tiers are decided after the software answer already passed.

Comparison with Darkbloom (Eigen Labs)

T27 asks for an honest comparison. The Darkbloom column is as publicly described (Apple-Silicon-only hosts, hardware attestation + MDM, proprietary agent). It is not a reverse-engineering of their coordinator. NeuronPool column is this repository.

Darkbloom (public description)NeuronPool (this repo)
Host OSApple SiliconLinux, Windows, macOS (llama.cpp; MLX on Mac)
Default public trustHardware attestation + MDMsoftware (blessed binary + challenge). hardware not granted
Operator-blind promptsClaimed via hardware isolation on enrolled MacsNot at software or edr. Worker edge also sees plaintext (T22)
Build blessingProprietary blessed-hash checkOffline release key + cosign keyless + public Rekor (T20/T86/T89). Anyone can re-check
Agent sourceProprietaryApache-2.0 agent + published protocol v1; coordinator BSL 1.1
Confidentiality on the control planeE2E sealed (their docs)Same family (X25519 + XChaCha20-Poly1305). D1/DO ciphertext; Worker isolate plaintext
Inference verificationNot in our treeT102 spot-checks + T103 commit-reveal, public jobs only, statistical
Enterprise postureMDMOptional EDR tier (Falcon implemented) (T94)
Free / social pathSelf-route to own MacsPools: any OS, never billed, never scored
Fee0 % alpha (public)PLATFORM_FEE_BPS default 0

NeuronPool does not claim feature-parity with Darkbloom's hardware attestation. The software tier is a different product: a verifiable open-source binary on commodity PCs, with sampled logprob checks, not a Secure Enclave. Where Darkbloom is narrower (Mac, MDM) and stronger on operator-blindness if their hardware story holds, NeuronPool is broader (Linux/Windows, pools, public Rekor) and weaker on host-side confidentiality until T72.

Buyer checklist

  1. Set X-NeuronPool-Min-Trust (or api_keys.min_trust) to the floor you mean. Default is software, not edr.
  2. Read X-NeuronPool-Trust on the response — the coordinator does not silently upgrade the header.
  3. Verify X-NeuronPool-Attestation against the host sign_pubkey (T23 or T103 above).
  4. Treat software as "blessed agent, hostile operator." Treat edr as "blessed agent, org EDR agrees the device is theirs." Do not treat either as a confidential VM.
  5. If you need operator-blind inference, wait for hardware or run the model on machines you already trust (self / tenant pool) and accept that the hosted Worker edge still decrypts.