Enclave
Mirrors
packages/hub/src/capsule/enclave-aes/in thenoy-dbrepo. 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.subtleonly): 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 anat-*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 theclassifiedservice.index.ts— the barrel: the only file the rest of the hub is allowed to import from this folder. Theenclave-barrel-onlycheck inscripts/check-architecture.mjsenforces 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:
- Enclave — raw keys.
- Kernel — DEK handles and plaintext, never raw key bytes.
- Services (
with-*layers) — plaintext, but opt-in and scoped. - Families (
to-/on-/at-/in-/by-/as-packages) — ciphertext only, or post-decrypt data as an ordinary authorized consumer. - Sister repos (klum-db, noy-db-to, noy-db-ui) — the published surface only.
- 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
| Consumer | Binds | Reaches |
|---|---|---|
| apps · noy-db-ui · noy-db-docs | the 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 fork | the frozen enclave barrel, by replacing the capsule/enclave-aes/ folder in its own build | supplies 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.