Trust and data handling

What each part sends, and what it does not

Written for the engineer doing the review. Every row below is a property of code you can run, and most of it is code you can read: the CLI, the MCP server and the admission hooks ship as packages on npm and PyPI.

Last reviewed 2026-10-18. This page replaces the older security page, which covered only the design app. Questions: neurarch.ai@gmail.com.

By surface: what leaves your machine

SurfaceTalks toNever sends
neurarch CLIhuggingface.co, only for a model named by its Hub id (GET). One GET of a public file on neurarch.com after a model check.Your files, configs, job CSVs, graphs or tokens to Neurarch. HF_TOKEN goes to huggingface.co only.
MCP serverNothing by default. huggingface.co with --hf; neurarch.com only when the agent calls plan or history, or with NEURARCH_REPORT=1.The graph, except to plan when that tool is called.
Claude Code hookhuggingface.co with --hf; nothing without it.The command it reads. It decides on your machine.
SkyPilot and SLURM hooksThe local CLI, which reads huggingface.co. The hosted plan only as a fallback, for a graph file, and never with sizing=cli.Your task file, script, data or credentials.
PR botThe traced graph to POST /api/v1/plan. Source files to /api/v1/fix only with fix: true and a key.Diffs, comments, titles or user names into storage.
Hosted APIYou call it.We keep no graph unless you ask (share: true, or a training run).
Self-hosted containerNothing. It runs with the network removed.Anything, unless you set two telemetry variables, and even then no graph.

The CLI (npx neurarch)

On npm as neurarch 0.3.0. It is arithmetic over a model's config: nothing is trained, downloaded as weights, or run on a GPU.

Also in 0.3.0: pin-check reads files on disk and goes to the network only with --resolve (huggingface.co); .neurarch.yml presets that extend a GitHub file fetch it from raw.githubusercontent.com; --attest without --model-dir reads the model's file hashes from huggingface.co.

The MCP server and the Claude Code hook

On npm as neurarch-mcp 0.19.0, and listed in the official MCP Registry as io.github.neurarch-ai/neurarch-mcp. The parser, rule engine, verifier and sizing are vendored into the package, so the server answers with no network, no key and no account.

SwitchWhat leaves your machineWhen
--hfThe repo id you asked for, to huggingface.co, plus HF_TOKEN if set. Cached for a day under ~/.cache/neurarch-mcp.Only for a model named by Hub id.
plan toolThe graph being planned (and a base graph if passed) to POST /api/v1/plan.Only when the agent calls plan.
history toolAn 8-character structural fingerprint and your NEURARCH_API_KEY. Never the graph.Only when called and a key is set. With no key it makes no request.
NEURARCH_REPORT=1One anonymous row per graded graph (see corpus opt-in).Off by default.

The Claude Code hook (neurarch-mcp hook) reads the pending Bash command on stdin and decides on your machine. It contacts huggingface.co only with --hf. Run through npx -y, npm itself fetches the package from the registry; npm i -g neurarch-mcp and "command": "neurarch-mcp hook --hf" avoid that.

The admission hooks (SkyPilot, SLURM)

Both are on PyPI: neurarch-skypilot 0.1.1 and neurarch-slurm 0.1.0. Both are standard library Python and size the job with the CLI installed on the same host.

The PR bot (GitHub App and Action)

The hosted API

The self-hosted container

One container answers plan, check, lint and rank with the same code as the hosted API, inside your network. It makes no outbound connection, so the documented way to run it is with the network removed:

$ docker run --rm --network none -p 8080:8080 neurarch/verifier:local

It ships with a script that proves it: npm run selfhost:offline-proof replaces fetch, http.request, https.request, tls.connect, DNS and every non-loopback socket with stubs that throw, then starts the server, makes a real request over a real socket and prints the answer. On 2026-10-18 it printed a full plan for the GPT-2 template and ended: "No outbound call was attempted."

Corpus opt-in: what a row can and cannot carry

The design app, the lint Action, the MCP server and the agent guard can each share one anonymous row per check. All four are off by default: a Settings toggle in the app, report-corpus: true on the Action, NEURARCH_REPORT=1 for the MCP server and the guard. NEURARCH_REPORT=0 overrides an inherited workflow.

The row carriesThe row cannot carry
An 8-hex-character structural fingerprint; the layer-type histogram, layer count and edge count it is computed from; {ruleId, severity} pairs; a channel tag (app, ci, mcp, agent, api).The graph, parameter values, layer names, code, file paths, repository or commit, hostname, user name, account id. No field exists for any of them.

The server recomputes the fingerprint from the histogram and edge count and rejects a row that does not match, and rejects a histogram that does not add up to the layer count. Nothing is sent from a local dev server or a preview deployment. Reporting has a 5-second timeout and swallows every error, so it cannot fail a build or a tool call. The aggregates (never rows) are public at GET https://www.neurarch.com/api/v1/report.

Signed pre-check records (--attest)

In CLI 0.3.0, on npm. The neurarch CycloneDX property names are listed at /docs/cyclonedx.

--attest <file> on the model check, layout, serve-check and policy apply writes an in-toto Statement v1 with in-toto's own test-result predicate: PASSED, WARNED or FAILED, the rule ids under each, and the CLI version plus the sha256 of every file that decided the verdict. The subjects are the model's files, hashed the way OpenSSF model_signing does it; the root digest matched model_signing 1.1.1 byte for byte in our test. --cyclonedx <file> writes a CycloneDX 1.6 BOM fragment that validates against the official 1.6.1 schema.

The output is deterministic (sorted keys, no clock unless you pass --attest-time), so two runs over the same inputs write the same bytes. Sign it in CI with actions/attest and anyone can check it with gh attestation verify.

Licences of what we publish

WhatLicence
Model change feeds: 586 OSV advisories, the Renovate datasource, the badgesCC BY 4.0, attribution "Neurarch model change record"
Measured datasets at /d/ (check catalogue, arena results, selection replay, who wrote the design)CC BY 4.0
The architecture corpus (the templates)CC0 1.0
Data that ships inside the benchmark package, and the reasoning tracesMIT
neurarch-skypilot, neurarch-slurmMIT

Each dataset page at /d/ states its own licence and what the dataset is not.

Report a vulnerability

Email neurarch.ai@gmail.com with "Security" in the subject: what you found, where, and how to reproduce it. Please give us a chance to fix it before you publish. We will acknowledge within five business days and tell you what we changed. We have no bug bounty. The machine-readable contact is at /.well-known/security.txt.

What we do not have

If a review needs one of these on a timeline, email us and we will say where it actually stands.

Where the hosted parts run

ProviderFor
VercelThe site and the API functions
Supabase (Postgres)Accounts, keys, the tables named above, with row-level security on user-scoped tables
ModalGPU runs you submit through /api/v1/train or the app
GitHubThe PR bot App
StripePayments
PostHogProduct analytics on our web pages and the app
OpenRouter, Anthropic, Google, Groq, xAIThe design app's agent, and /api/v1/fix. With your own key in the app, calls go from your browser to the provider and never through us.

Training data and retention for the design app are covered in the privacy policy. This page describes the product as built on the date above; it is not a contract or a warranty.