stable

Enclave

The kernel's crypto interior behind one frozen door — why encryption cannot be disabled, and why the enclave is the one swappable core.

Mirrors packages/hub/src/capsule/enclave-aes/ in the noy-db repo. Companion: Families and the nested-cores frame this page's arrow-flip belongs to.

noy-db is an encrypted, offline-first document store whose trust boundary is the @noy-db/hub package: all encryption happens inside the hub before data reaches any storage backend. The enclave is where that encryption actually lives — a minimal, self-contained folder inside the hub's kernel that owns the open↔close boundary: the crypto functions, the keys, and the encrypted data format (codec). It depends on no other kernel part and exposes exactly one frozen interface (its barrel file), which makes it the one part of the core that can be replaced wholesale. noy-db ships one enclave — full AES-256-GCM, zero-knowledge.

What's inside the folder

capsule/enclave-aes/ maps to the source tree like this:

  • crypto.ts — the cryptographic primitives, thin wrappers over the Web Crypto API with zero npm crypto dependencies (globalThis.crypto.subtle only): AES-256-GCM record and binary encryption, PBKDF2-SHA256 key derivation (600,000 iterations), AES-KW key wrapping, SHA-256 / HMAC-SHA-256 hashing.
  • record-keys/ — the engines built on those primitives: the per-record codec, sealing (granting an at-* host you control decrypt access to a scoped slice), deterministic encryption (blind-equality lookup), the tombstone (erased-record residue), and the envelope-body access helpers — the sanctioned door onto an envelope's protected fields (_iv, _data, _cek, _sealed).
  • classify/ — blind-index, digest, and k-of-n verify-without-reveal primitives consumed by the classified service.
  • index.ts — the barrel: the only file the rest of the hub is allowed to import from this folder. The enclave-barrel-only check in scripts/check-architecture.mjs enforces that mechanically, and the export list is frozen by a golden test (packages/hub/__tests__/enclave-surface-golden.test.ts) — additive changes only.

The level-0 arrow-flip

The nested-cores frame composes the whole product as rings: kernel inside hub inside noy-db inside the product family. At every ring, the periphery binds the core's frozen contract and the core never imports outward. At level 0 — the innermost ring — the arrow flips: the kernel spine (the always-on orchestration code) consumes the enclave's frozen barrel. Because the crypto is the innermost core, the one-way law protects it from everything outside it, including the kernel spine itself, which may only call through the barrel, never reach past it.

That flip is the security payoff. Application code binds the hub's public API. klum-db — the sister product that orchestrates a fleet of vaults (federation, custody, interchange) — binds the @noy-db/hub/cargo orchestration subpath. Neither has any code path to the enclave, so noy-db's promise that encryption cannot be disabled stays absolute for both: there is nothing an app or a fleet orchestrator can call, wrap, or configure that would reach the keys or the crypto functions directly.

Each ring outward also sheds capability, monotonically — the trust gradient:

  1. Enclave — raw keys.
  2. Kernel — DEK handles and plaintext, never raw key bytes.
  3. Services (with-* layers) — plaintext, but opt-in and scoped.
  4. Families (to- / on- / at- / in- / by- / as- packages) — ciphertext only, or post-decrypt data as an ordinary authorized consumer.
  5. Sister repos (klum-db, noy-db-to, noy-db-ui) — the published surface only.
  6. Docs — published versions only.

Nothing at ring N can reach ring N−1's capabilities except through the seam between them, and no seam lets a caller climb back inward.

Why this holds

The enclave is a minimal, self-contained unit inside the kernel — it has no dependency on other kernel parts or on any with-* service, and it exposes a frozen interface (the enclave barrel, capsule/enclave-aes/index.ts) that is the only door the rest of the hub is allowed to use, mechanically enforced by the enclave-barrel-only check:architecture guard — see Ports → Imports point inward only. Nothing outside that folder can reach past the barrel to touch keys, crypto functions, or the data format directly — there is no code path for an app, klum-db, or a service layer to bypass the enclave, only to call through it.

Who can (and can't) swap it

ConsumerBindsReaches
apps · noy-db-ui · noy-db-docsthe hub's public API (+ chosen service layers; ui also collection.describe())full zero-knowledge; cannot touch the enclave
klum-db@noy-db/hub/cargo (+ /pod, the .noydb container format)full zero-knowledge — orchestrates vaults through the fixed enclave; never swaps it
an enclave forkthe frozen enclave barrel, by replacing the capsule/enclave-aes/ folder in its own buildsupplies its own crypto engine, key story, and protected-body format

klum-db orchestrates serialized vaults across a fleet, but it does so through the fixed enclave like any other consumer — cross-vault orchestration never implies crypto access.

Swapping the enclave is a source-level fork seam, not something a package can opt into at runtime: a sister project replaces the capsule/enclave-aes/ folder wholesale in its own build and honors the frozen barrel (verified by the golden surface test and the test-harnesses/enclave-conformance kit). The seam exists so that a sister project re-implementing the hub foundation against noy-db's published surface can make a different, explicit protection tradeoff for its own use case — an unencrypted envelope, say. Any such tradeoff is opt-in and scoped to the fork alone: it never weakens the invariant for noy-db, klum-db, or any other consumer, because they never load a fork's enclave.

Next

Forking the enclave → — the contract a fork implements to exercise this seam: the frozen barrel surface, refusal semantics, and the conformance kit.