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
- CLI
- MCP and the Claude Code hook
- Admission hooks
- PR bot
- Hosted API
- Self-hosted
- Corpus opt-in
- Signed records
- Data licences
- Report a vulnerability
- What we do not have
By surface: what leaves your machine
| Surface | Talks to | Never sends |
|---|---|---|
neurarch CLI | huggingface.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 server | Nothing 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 hook | huggingface.co with --hf; nothing without it. | The command it reads. It decides on your machine. |
| SkyPilot and SLURM hooks | The 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 bot | The 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 API | You call it. | We keep no graph unless you ask (share: true, or a training run). |
| Self-hosted container | Nothing. 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.
- A Hub id is the only reason it goes to the network.
npx neurarch Qwen/Qwen3-8B,layout,serve-checkandrightsizeread that model's public metadata and config files from huggingface.co with GET requests. SetHF_TOKENfor a gated repo; it is sent to huggingface.co and nowhere else. - A local graph stays local.
neurarch layout ./graph.json ...made no network request at all when we logged every request on 2026-10-18. - One request to us, and it carries nothing about you. After the default model check, the CLI fetches the public file
https://neurarch.com/m/index.jsonto decide whether to print a link to that model's page. The model id is not in the request; the lookup happens on your machine. It times out after 3 seconds and prints nothing on failure. - The CLI does not call the Neurarch API. The
POST /api/v1/checkline it prints is a pointer, not a request.
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.
| Switch | What leaves your machine | When |
|---|---|---|
--hf | The 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 tool | The graph being planned (and a base graph if passed) to POST /api/v1/plan. | Only when the agent calls plan. |
history tool | An 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=1 | One 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.
- Sizing source.
auto(the default) runs the local CLI first; only if it cannot answer does it POST tohttps://www.neurarch.com/api/v1/plan, and the hosted plan only accepts a graph file (.neurarch.json), not a bare Hub id. SetNEURARCH_POLICY_SIZING=cli(SkyPilot) or--sizing cli(SLURM) and nothing goes to us. - No package fetch at submit. The default CLI command is
npx --no neurarch, which never downloads from the registry during admission. - Fail open. If sizing cannot answer, the job is admitted with a warning, unless you set
fail_closed. The SLURMcli_filterruns in the user's own sbatch process, so it informs; it is not an enforcement boundary. - The hooks record their verdicts nowhere but your logs.
The PR bot (GitHub App and Action)
- The Action traces the model inside your own runner and sends the traced graph to
POST /api/v1/planto build the comment. Withfix: trueand an API key, it can also send the named source files toPOST /api/v1/fix, which passes them to a model provider for one completion; they are not stored or logged, and the server never applies a patch. - The GitHub App stores one row per webhook delivery from an allowlist: installation id, repository name, event, delivery id, and per event a pull request number with two commit shas and two branch names, or a command word with up to five argument tokens. Never comment text, titles, descriptions, commit messages, diffs, user names or source. Rows are deleted after 90 days. The App builds its plan in process, so no corpus row is written. Uninstalling stops all of it.
The hosted API
- Keyless calls are accepted by
planonly, rate limited per hour by IP. For that we keep a hash of the IP address with a timestamp. Every other endpoint needs a key. - Keyed calls to
lint,check,rank,planandtrainrecord one anonymous structural row taggedapi: the same four fields as the opt-in corpus, with no key, account or IP on it. This is the one row that is not opt-in, because you sent the graph to be graded. To avoid it, run the same checks locally (CLI, MCP, the self-hosted container). - A graph is stored in two cases only.
planwithshare: truestores the graph under an unguessable public link (/p/<id>), with no account attached; email us the id to remove it.trainstores the graph privately on your account because the GPU worker runs code generated from it; datasets are deleted 7 days and weights 30 days after a run. - Use
https://www.neurarch.comfor API calls: the apex domain redirects and drops theAuthorizationheader.
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."
- What needs our database (shared links, history, the corpus) is absent, and every response lists it under
hosted_onlywith the reason. - Telemetry is off unless two environment variables are both set. Even then the payload is built from a whitelist of counters plus rule ids re-checked against the rule catalogue; a test pushes a graph full of distinctive strings through it and asserts none appear.
GET /metrics/previewshows the exact payload. - The image is not on a public registry yet. We send it, with the offline proof.
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 carries | The 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
| What | Licence |
|---|---|
| Model change feeds: 586 OSV advisories, the Renovate datasource, the badges | CC 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 traces | MIT |
| neurarch-skypilot, neurarch-slurm | MIT |
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
- No SOC 2 (Type I or II), no ISO 27001, no third-party penetration test report.
- No signed data processing agreement template. No SSO or SAML for the pre-check yet: the Enterprise plan includes it, and it is set up with the first customer who needs it.
- No bug bounty.
- The main repository, which holds the hosted API and the site, is private. The CLI, MCP server and hooks ship as readable packages.
- Not on a public registry yet: the self-hosted image.
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
| Provider | For |
|---|---|
| Vercel | The site and the API functions |
| Supabase (Postgres) | Accounts, keys, the tables named above, with row-level security on user-scoped tables |
| Modal | GPU runs you submit through /api/v1/train or the app |
| GitHub | The PR bot App |
| Stripe | Payments |
| PostHog | Product analytics on our web pages and the app |
| OpenRouter, Anthropic, Google, Groq, xAI | The 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.