Security

Can we read
your memories?
Yes, technically.

A brain holds the reasoning behind your decisions, distilled. That makes it a denser target than the transcripts it came from and it deserves a straighter answer than most security pages give. On the hosted edition we hold the keys that protect your data, so an engineer with production access and a reason could decrypt what you store. We would rather say that plainly than hide it behind a sentence that sounds like cryptography.

worst case · attacker takes the database hosted edition
# everything on disk
memories.body   → ciphertext, per-org key
memories.title  → ciphertext
events          → ciphertext
data_keys       → wrapped, useless alone
master key      → not here. Vault holds it.

# what is NOT encrypted, stated plainly
search index    → your words, in the clear
                an index over ciphertext matches nothing
a stolen backup is two useless halves except the index

Why not zero-knowledge #

An earlier version of this site said the hosted brain was shaped so the server could not read what it stored. That was the intention when it was written and it does not survive contact with what the hosted product has to do.

Search is the obvious one. Retrieval runs full-text matching and then a ranking pass over the results and neither works on ciphertext. Nor does a web UI that shows you a memory, the conflict queue when two people correct the same fact, or a support engineer looking at why your recall returned nothing. Encrypting so we cannot read it means giving up most of what you are paying for.

So we made the other choice and we are telling you which one it was. What stops an engineer reading your memories is key custody, no standing production access and a break-glass path that is logged, reviewed and rare. That is access control, not mathematics.

If you want an arrangement where we genuinely cannot read your data, there are two and both are real. Mind is free, self-hosted and involves no server of ours at any point. The appliance runs the same team edition inside your perimeter, where the master key is generated on your machine and we never hold it.

How the encryption actually works #

Two limits, stated rather than discovered. The search index holds your words in the clear. And the encrypted values carry no additional authenticated data yet, so ciphertext could be moved between rows by somebody who already has write access to the database. Retrofitting that binds every existing row and needs a re-encryption pass; it is on the list and it is not done.

Your agent, your model, your credentials #

ns-brain does not call a language model. Your coding agent does that with your own account and the brain never sees the key, the prompt or the completion. It stores text and gives it back, ranked.

The one exception is search quality. At company scale, matching on words alone starts missing what somebody meant, so the hosted brain also builds vector embeddings of what you store. Those run on an open model on our own hardware, paid for by us. Your memories are not sent to OpenAI, Anthropic or anyone else to be embedded and there is no third-party model provider anywhere in the path.

Who can reach what #

Permissions live on the tree you define: organisation, department, team, project. A grant is inherited downward and can be revoked at any level. There are no per-memory sharing rules, deliberately, because a permission model you cannot hold in your head is one nobody can audit. If a memory needs different visibility, it belongs at a different level.

Agents and CI get their own tokens, scoped to a node rather than to a person and capped below the level that can retract a guardrail. A compromised token in a build pipeline is not a route to everything your company knows. Revoking one takes effect on the next request and there is no local replica to chase.

Tokens are 32 random bytes, stored as a SHA-256 hash, compared in constant time, with revocation and expiry. Reads are logged as well as writes, so when a security review asks which agent read what and when, that is a query rather than an apology.

What the last audit found #

The first code-level audit of the server, the MCP transports, the web UI and the client ran on 2026-08-12. An earlier pass had reviewed the specification and found nothing, because none of this is visible in a specification.

The tenant boundary was the whole story. Four issues, all cross-organisation, all in the layer whose comments asserted the opposite:

Since 2026-09-18 the boundary is also driven from outside, as a company would hit it: tools/hive_company_test.py puts two organisations on one server and, from a credential in one, tries the other's memories by search and by id, its history and restore, notes and broadcasts to its projects, its index, axioms and lessons, a hold on its node, an erasure of its person, its settings, an approval into its root and a revocation of its credential from the dashboard. Every one refuses and the refusals for ids do not confirm the id exists. One person belonging to both organisations from one machine keeps them apart by naming the organisation in each project.

Both cross-tenant failures were reproduced with tests before being fixed and those tests are in the suite. The list of what was not fixed and why each is a decision rather than an oversight, is kept with the audit: no AAD on the encrypted values, the device token sitting in cleartext between approval and first poll, no rate limiting, raw error text to authenticated callers and missing read and write timeouts on the HTTP servers.

We publish this because a security page that only lists what went right is a marketing page.

Backups and getting your data out #

Backups are continuous, encrypted with the same key hierarchy and kept on a rolling 30-day window. Restores are tested rather than assumed and point-in-time restore is self-serve.

Export is complete, free and always available. One JSON file with every memory, every event, the supersession links and the provenance. ns-brain import reads it back into a free local brain that behaves identically, because it is the same binary. Nothing about paying makes your data harder to take somewhere else and nothing about leaving triggers a negotiation.

If an account lapses and stays lapsed, we switch the brain off and hand over the extract. We will not hold a company's institutional memory hostage over a failed card.

Deleting things, properly #

This system is built not to forget. Retractions outrank facts, corrections stay linked to what they corrected and a deliberate deletion leaves a tombstone so the same wrong answer is not learned twice. All of that works against erasure, which is why erasure is built in rather than bolted on.

What is captured about the person

The session hook stores every user message verbatim before the turn is answered, clipped at 8000 characters and classified. There is no per-message opt-out: the only way to turn it off is not to wire that hook, with ns-brain init --no-auto-recall, which also turns off automatic retrieval. Credential-shaped text is refused outright with no override, because no human is on the other end of a hook to ask.

That text is in the store like anything else, so it comes out in export, backup and snapshot, in cleartext and it travels with the brain when the brain moves. On a shared brain, tell the people whose messages it is.

When a person asks to be forgotten, we remove what they wrote and their attribution across memories, tombstones, events and the search index, then let it age out of backups inside the 30-day window. We do not claim to scrub every mention of somebody from text other people wrote about an incident. That promise is unbounded and a promise nobody can keep is worse than a limit written down.

Per-node retention is yours to set. Finance can keep things for years while another team deletes on a timer and a parent can lock a setting so a team below cannot loosen it.

Where it runs #

EU by default, on servers in Germany and Finland. That is where the company is and where most of the first customers are, so residency is the starting position rather than an upgrade you buy.

A standard DPA is included on every paid account, from the cheapest tier upward. Under GDPR that is table stakes for anyone with European customers and holding it back for an enterprise tier would just mean nobody in Europe can legally buy the cheap one. The subprocessor list is short, published and changes with notice.

What the free edition does and does not #

Mind writes a SQLite file in your project at mode 600, adds it to .gitignore and refuses to store text that looks like a credential unless you override it. The one network call it makes on its own is a daily GET of brain.fightclub.pro/latest-version.txt at session start, to say when an upgrade is out. It sends nothing but the request, a failure is silent and NS_BRAIN_NO_UPDATE_CHECK=1 turns it off. No memory ever leaves the machine.

There is no encryption at rest and that is deliberate. A lone developer has no second party to be protected from and an unnecessary key hierarchy is an excellent way to lose a brain permanently. Full-disk encryption on your laptop is the right layer for that job.

Two more things worth knowing if you run it: several projects can share one database file, in which case the project filter is a filter and not a boundary and --all-projects widens on purpose. A project can opt out of being read that way with ns-brain private. Anything that needs a real boundary gets its own file, which is still the default. The details are here.

The moment a colleague's reasoning is in the store, the argument changes and that is where the hosted key hierarchy starts.

Reporting something #

Mail security@brain.fightclub.pro. We answer within one working day, we will not threaten you and we will credit you unless you would rather we did not.