NotariumDocumentation
Documentation version: latest
EN

Security and Visibility

Giving an agent direct access to the storage engine means assembling the "lethal trifecta": private data × untrusted note content × an outbound channel. Any one axis is harmless on its own, but together they let an injection inside a note walk your data out the door. The Notarium MCP gateway breaks every axis by construction, not by configuration. This isn't a convenience wrapper — it's a trust boundary.

The trifecta broken by construction

  • No outbound channel. Every tool ships with openWorldHint:false — no tool reaches the network. There's no moving or copying between spaces, so internal data leakage is closed off too. There's nowhere to walk data to.
  • Untrusted content defused. The server's instructions are static and never mixed with note content: nothing from a note is folded into tool descriptions or into the server instructions. That way an injection in a note's body never becomes a command to the agent.
  • Destructive actions are always reversible. delete_note sends a note to the trash; restoring it and purging it for good are done by a human, not the agent. That's the "agent does nothing irreversible" line.

Permission checks on every call

Permissions are checked twice. First, tools/list is filtered by the token's ceiling — a read token simply doesn't see the writing tools. Then every tools/call additionally checks access to the specific space (can(principal, action, {space})). The permission formula is effective = scopes(token) ∩ grants(principal): the token's scope (its ceiling of actions) intersected with live membership in spaces. Revoking a grant narrows the token instantly.

Management actions (issuing tokens, managing members) sit above write — a leaked write-level token can't issue a new token or grant access.

Denial = 404, not 403

An access denial is returned as a 404 ("no such thing"), not a 403 ("not allowed"). That way the response codes can't be used to enumerate which notes or spaces exist beyond the permissions you've been granted. Another user's space is simply unreachable and indistinguishable from one that doesn't exist.

flowchart TD
  call[tools/call] --> listed{tool within the<br/>token's ceiling?}
  listed -->|no| gone[tool absent from tools/list]
  listed -->|yes| acl{can principal,<br/>action, space?}
  acl -->|no| notfound[404 · anti-enumeration]
  acl -->|yes| exec[execute · provenance to the log]

Defusing untrusted content

Everything that goes to the agent — title, snippet, content, frontmatter — is sanitized before it's sent: the angle brackets of pseudo-control tags (<system>, <instructions>, and the like) are defused. A note where someone typed in a "system instruction" reaches the agent as ordinary text, not as a command.

Edit history is visible

Every edit records who made it — a specific person or agent — in the edit history. get_note and recall can return who edited a note: a human or an agent, and which one. An injection that passed through an agent stays visible and traceable.

What this means in practice

Even an agent fully compromised by a prompt is bounded by its token: it won't reach the network, won't reach another space, won't make an irreversible deletion, and won't grant itself permissions. The worst it can do is a reversible edit within its own permissions, with full provenance in the log.

The boundary: not E2EE

Notarium deliberately doesn't do end-to-end encryption. A smart server — search, semantics, history, agents — needs access to plaintext. Privacy here is built on self-hosting and owning your files, not on E2EE. The gateway's threat model protects against a compromised agent, not against a compromised host, which you already trust with your files anyway.

Next