Architecture¶
How Nanorix produces AuditProofs for regulated data workloads.
Core concept¶
A capsule is a sealed ephemeral workspace — an isolated Linux-namespace environment where regulated data lives, works, and dies. Customers route sensitive data (PHI, PII, financial, credentials) through capsules: upload data, run computation with their own code, get results out, then destroy. Every capsule produces an AuditProof: cryptographic evidence the destruction happened.
The capsule is the product. The AuditProof is the evidence.
Capsule lifecycle¶
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐
│ create │ → │ execute │ → │ destroy │ → │ AuditProof │
└─────────────┘ └──────────────┘ └─────────────┘ └──────────────┘
POST POST DELETE GET
/v1/capsules /v1/capsules/ /v1/capsules/ /v1/proofs/
:id/exec :id :id
- Create. Customer declares
data_classification("PHI"/"PII"/"financial"/"credentials"/"general") +jurisdiction("US"/"EU"/"UK"/"CA"/"AU"/"IN"/"OTHER"). Optional: reference a Capsulefile (frozen environment definition) bycapsulefile_id. - Execute. Customer uploads input files, runs commands inside the capsule, downloads output files. Every outbound HTTPS call goes through the sealed daemon — a per-capsule sidecar that records every request as a
SealedHttpRequestactivity event in the AuditProof. - Destroy. Customer issues
DELETE /v1/capsules/:id. The capsule executes the 8-step destruction chain — namespace teardown, tmpfs unmount, multi-pass DoD-5220 memory wipe, key incineration, forensic verification — and emits the AuditProof. - AuditProof. Customer retrieves the signed proof via
GET /v1/proofs/:id(full proof, requires auth) orGET /v1/capsules/:id/cdp/verify(verification proof — public, rate-limited). Anyone with the proof can verify it offline using thenanorix verifyCLI or the offline verifier modules in the Python + TypeScript SDKs.
Defense-in-depth (Linux isolation)¶
Each capsule runs inside a stack of Linux kernel isolation primitives:
| Layer | Mechanism | What it blocks |
|---|---|---|
| 6 | Seccomp-BPF | Syscalls outside the ~70-call allowlist |
| 5 | Cgroup v2 | Memory limits, swap=0, OOM-group kill semantics |
| 4 | Network namespace | Ambient network access (sealed by default; egress-filtered when an allowlist is declared) |
| 3 | UTS namespace | Hostname disclosure (randomized per capsule) |
| 2 | Mount namespace | Host filesystem visibility (private tmpfs only) |
| 1 | User namespace | Privileged operations (UID-mapped to unprivileged) |
| 0 | Crypto shredding | Multi-pass overwrite + Ed25519 attestation |
The kernel enforces these primitives. Nanorix doesn't reimplement isolation — we compose what the Linux kernel already provides and bind the result into a cryptographic proof.
AuditProof structure¶
The AuditProof is an 8-step SHA-512 hash chain plus an Ed25519 signature over the chain. Each step records the destruction of one subsystem.
Step 1: eee_namespace method: procfs_verification
Step 2: eee_tmpfs method: mountinfo_verification
Step 3: eee_memory method: dod_5220_multipass_wipe
Step 4: dire_keys method: ed25519_key_destruction
Step 5: dire_identity method: credential_incineration
Step 6: fgx_forensic method: merkle_tree_verification
Step 7: rzl_audit method: hash_chain_validation
Step 8: capsule_destroy method: capsule_lifecycle_verification
Each step's hash is computed over the previous step's hash plus the step's subsystem + method + timestamp:
chain_hash[i] = SHA-512(
chain_hash[i-1] || subsystem || "destroy" || method || timestamp
)
chain_hash[0] = SHA-512("") (genesis hash)
The Ed25519 signature is over chain_hash[7] rendered as ASCII hex (128 bytes — not raw binary). This is required for cross-implementation verifier compatibility: Rust + Python + TypeScript verifiers compute byte-identical hashes against the same canonical input.
The full canonical-JSON form bound into the signature uses RFC 8785 JCS (JSON Canonicalization Scheme) via serde_jcs. This guarantees: re-canonicalize the same logical JSON object on any supported platform, get the same bytes, get the same hash, get the same signature verification result.
Activity trail¶
Beyond the AuditProof, every meaningful operation inside the capsule emits one or more ActivityEvent variants into an activity_trail array bound into the AuditProof's canonical hash. Variants currently shipped:
CapsuleStarted— capsule init, withdata_classification,jurisdiction, region.FileUploaded/FileDownloaded— per-file SHA-512 hash + size + direction.ExecutionStarted/ExecutionCompleted/ExecutionOomKilled— per-exec lifecycle bounds.SealedHttpRequest— per outbound HTTPS call. Carries request canonical hash, response body hash, TLS metadata (version, cipher, peer cert SHA-256, validation outcome), duration.StreamingEgressStarted/StreamingEgressChunk/StreamingEgressCompleted/StreamingPolicyViolation— per-chunk SHA-512 + RFC 6962 Merkle root for SSE / chunked-transfer responses.PostgresQueryExecuted/RedisCommandExecuted/MqttMessagePublished/DicomCStoreCompleted/RawTcpConnectionCompleted— per-protocol attestation for non-HTTP TCP egress.McpToolInvoked— per MCPtools/callinvocation. Carriestool_name,tool_args_hash(SHA-512 of canonical JSON of arguments),tool_result_hash(SHA-512 of canonical JSON of result content),duration_ms,outcome,client_session_id.BatchRecordProcessed/BatchCompleted— per-record outcome + Merkle-root binding for batched-into-capsule pipelines.MemoryArtifactLoaded/MemoryArtifactPersisted— for multi-capsule agents using the memory artifact pattern.InputProvenanceVerified/InputProvenanceRejected— when input manifests with cryptographic provenance are declared.SecretsInjected/SecretsInjectionRejected— for env-vars-as-secrets declarations.DestructionInitiated— final event before the destruction chain runs.
Egress model¶
By default, capsules have no network. When a customer declares an egress allowlist (Team tier and above), a persistent network namespace is created with filtered outbound network access.
Inside the capsule, all outbound HTTPS flows through a sealed egress layer that:
- Enforces the destination allowlist (defense-in-depth: runtime egress profile AND per-Capsulefile
egress_declarationboth must allow). - (For MCP-aware capsules) enforces the Capsulefile's
mcp_policy.allowed_toolswhitelist andmcp_policy.prohibited_toolsblocklist on outbound JSON-RPCtools/callenvelopes, rejecting a disallowed call before it is forwarded. - Records each request as a
SealedHttpRequestactivity event with the cryptographic shape (request canonical hash, response body hash, TLS metadata, duration).
Tool-policy inspection reads the transport bytes rather than trusting the client library, so a call made with raw httpx, requests or urllib that carries a well-formed JSON-RPC tools/call envelope reaches the same check. A capsule whose Capsulefile declares no mcp_policy is unrestricted at the tool level and behaves exactly as before the check existed.
The tool check is fail-open on unparseable bodies
A body the daemon cannot parse as a single JSON-RPC tools/call object is forwarded without a tool-level check — including a content-encoded (compressed) body, a spec-legal JSON-RPC batch array, and a malformed envelope. mcp_policy is therefore defense-in-depth against honest clients and misconfiguration, not a containment boundary against an adversarial or non-conforming one. The destination allowlist above is enforced independently and is not affected by this.
Which build enforces this
Tool-policy enforcement was wired in the runtime release that introduced the mcp_policy daemon threading. If you operate Nanorix in your own infrastructure (BYOC), a build predating that release accepts mcp_policy and does not enforce it — the field is still validated and bound into the Capsulefile content hash, but the runtime will not reject a disallowed tool call. Check your deployed runtime version before relying on it as a control. Denied calls are rejected on the wire and are not recorded in the AuditProof, so the proof evidences which tools ran rather than which were blocked.
Declared but not yet enforced at runtime. tls_pinned_certs / tls_ocsp_check (API-declared per ADR-016; not declarable from the Capsulefile YAML in V1) are accepted, shape-validated, and bound into the Capsulefile content hash — so a change forces a re-finalize and is covered by the artifact — but per-host SHA-256 pin verification is not active in the current release. Capsules validate server certificates against system roots. Declaring pins today binds your intent into the artifact; it does not yet change what the runtime accepts, so do not rely on pinning as a control until this note is removed.
The capsule cannot bypass this layer — kernel-level isolation denies raw socket access and the network namespace has no default route.
Metadata + customer attestation¶
Capsules can carry customer-defined metadata (open string-keyed map) — Nanorix prescribes no structured keys (no patient_id, no matter_id, etc.). Customer-defined vocabulary; 4 KB total limit; the nanorix:* prefix is reserved.
For per-event customer attestation, Capsulefiles can declare a signing_config.endpoint — an HTTPS+mTLS service the customer hosts. Each ActivityEvent triggers one POST to that endpoint with the event's canonical hash; the customer's KMS-backed signing service returns an Ed25519 or RSA-PSS signature. Nanorix fire-and-buffers; signatures absorb at capsule destroy and bind into the AuditProof's per-event attestation reserved slot.
This produces two-party attestation: Nanorix attests to the boundary, the customer attests to each event with a key Nanorix never sees.
Compliance binding¶
The nanorix.compliance SDK module produces a regulatory_context reference map binding an AuditProof's activity trail to specific articles of regulatory frameworks: HIPAA Security Rule §164.312, GDPR Articles 5 / 9 / 25 / 30 / 32, SOC 2 Trust Services Criteria CC6 + CC7. The module uses related_to language only — never asserts compliance status. Customer's compliance officer makes the final determination.
The reference module is a static map — Nanorix does not execute compliance evaluations against customer data. The reference frame is the customer's audit prep tool, not a substitute for an audit.
What this means in practice¶
- The design thesis: route the regulated fraction of your operations (typically a minority of workloads) through capsules, and let that fraction carry the bulk of your compliance evidence burden.
- The customer's ML/AI workloads, business logic, and data shape are theirs — Nanorix does not inspect, classify, or score data content.
- The customer holds compliance authority. Nanorix produces evidence; the customer's compliance team interprets it.
- Verifiers (regulators, auditors, customers' compliance partners) can replay the AuditProof offline using the Rust CLI, the Python SDK module, or the TypeScript SDK module — all three reproduce identical hash chains via RFC 8785 + RFC 6962.
Where to go next¶
- Quickstart: Get your first AuditProof in 5 minutes
- Reference Capsulefile bundles: five copy-paste pipelines (med-AI extraction / claims / eDiscovery / voice / long-running agent) — distributed via design-partner program; contact [email protected]
- Verification: Verify an AuditProof offline
- Threat model: What Nanorix attests to + what it doesn't
- Regulatory binding: Compliance frameworks supported
- API reference: All endpoints + schemas