Documentation

Overview

flare-encrypt is a bring-your-own-Cloudflare secrets manager — the AWS/GCP KMS envelope pattern on a Worker, D1, and a master key you hold. Operator-held, portable, multi-tenant, any-runtime.

What flare-encrypt is

flare-encrypt is a bring-your-own-Cloudflare (BYOC) secrets manager. It runs the same envelope-encryption pattern AWS KMS and Google Cloud KMS use — a data key encrypts the data, a wrapping key wraps the data key — and deploys it toyour own Cloudflare account: a Worker, one D1 database, and a master key you hold. Nothing runs on a vendor's control plane, and no plaintext file ever touches disk.

The whole runtime is Cloudflare primitives you already own. A D1 read yields only ciphertext andwrapped data keys; the master key lives outside D1, in Cloudflare Secrets Store or a plain Worker Secret. Every value is encrypted under a per-tenant data key, and a mandatory encryption context binds each ciphertext to its exact row, so a blob copied between tenants fails to decrypt.

Beside secrets, the store is also a signing oracle: server-sidesigning keys (Ed25519 or ECDSA P-256/ES256) whose private key is generated inside the store, wrapped under the same master key, and never returned over the API — callers send a message and get a signature; verifiers need only the public key. That covers token issuance, artifact signing, and mTLS identity, and fills a managed-KMS gap: AWS KMS cannot sign Ed25519, and its ES256 wire needs a DER conversion this store never does.

Four properties

The design meets one target — the smallest secrets manager you can fully own — through four properties:

  • Operator-held. Every byte of key material and ciphertext lives in your account. There is no hosted vault and nothing in the read path that you do not run.
  • Portable. The store is data in D1 you can export plus a master key you hold. A break-glass path decrypts an export offline with the SDK and the key — no Worker required.
  • Multi-tenant by construction. A per-environment wrapping key (KEK) wraps per-tenant data keys (DEKs), so a key compromise stops at the environment boundary. The encryption context binds each ciphertext to { tenant, column, dek_ver }.
  • Any-runtime injection. The fe CLI streams secrets into a child process via execve — never a .env file, on any runtime.

Quickstart

There are two ways in. Deploy the store to run a real app with secrets off the filesystem, or embed the library to encrypt per-tenant values inside your own app with nothing to deploy.

Deploy your own store

fe init --dry-run prints the ordered deploy plan — create the D1 database, apply migrations, provision the KEK, deploy the Worker, bootstrap and mint a first admin token — as thewrangler/D1 commands you run yourself, so nothing touches your account implicitly. Thenfe run injects secrets into any process:

npm i -g @fractalboxdev/flare-encrypt-cli

fe init --dry-run           # print the deploy plan: create D1, migrate, provision KEK, deploy, mint admin token
fe run -- node server.js    # export once, inject via execve — no .env, no tmpfile, no shell history

fe run does one export round-trip, holds the values in process memory, and hands them to the child through execve's environment — with ulimit -c 0 set on the child so a crash can't dump plaintext to a core file. The CLI writes no plaintext file. SeeDeployment & CLI.

Embed the library

@fractalboxdev/flare-encrypt-sdk is the envelope library on Web Crypto — zero runtime dependencies, byte-identical under Cloudflare Workers and Node 20+. Encrypt and decrypt take a structured context and derive the encryption context internally, so a caller cannot bind the wrong one:

pnpm add @fractalboxdev/flare-encrypt-sdk
import { encrypt, decrypt } from "@fractalboxdev/flare-encrypt-sdk";

const ctx = { aadFmt: 1, tenantId: "t", column: "c1", dekVer: 1 };
const enc = await encrypt(dek, "s3cr3t", ctx);   // Result<CipherRecord, …>
if (!enc.ok) return handle(enc.error);           // branch on enc.error._tag
const dec = await decrypt(dek, enc.value, ctx);  // Result<string, …>

See the full surface in the API reference.

The four packages

Each layer is the smallest piece that fits a job. Start with the library; adopt the store for sharing, audit, and rotation.

PackageWhat it isAdopt when
@fractalboxdev/flare-encrypt-sdkThe embeddable Web-Crypto envelope library. Zero runtime dependencies; identical on Workers and Node 20+.You encrypt per-tenant values inside your own app and deploy no service.
@fractalboxdev/flare-encrypt-clientA thin HTTP/RPC transport for a deployed store. Depends only on the SDK.You call a store over the wire without hand-rolling the protocol.
@fractalboxdev/flare-encrypt-workerThe deployable BYOC store: Worker + D1 + master key, scoped-token auth, hash-chained audit.You want a shared, audited store on your own account.
fe (@fractalboxdev/flare-encrypt-cli)The injector: secrets into any runtime through execve, plus fe init, rotation, and break-glass.You run secrets for any process, off the filesystem.

The same SDK runs in two hosts — an embedded app runtime and the operator's standalone Worker — which is why the store is never on a consumer's encrypt/decrypt hot path over a network hop.

Honest scope

flare-encrypt makes a D1 read alone worthless, makes relocation fail, anchors freshness so a D1-write rollback fails on read, and makes key destruction O(1). It does not provide access control (tenant isolation rests on scoped tokens), and a fully-compromised Cloudflare account — one that can both call decrypt and read D1 — defeats every layer. These boundaries are stated as facts, not marketed past. See the Security model.

Against SOPS + age, flare-encrypt is not the smaller tool: SOPS wins on pure-offline, zero-infra — one file in git and one key. flare-encrypt runs a Worker, a D1 database, and a master-key binding for what SOPS structurally cannot do: per-tenant crypto-shred, a queryable audit trail, scoped tokens, runtime injection without a plaintext file, and rotation without rewriting git history. For a single offline file with one tenant, SOPS + age is the right answer.

Where to go next

  • Cryptography — the three-tier envelope, the frozen encryption context and golden vectors, GCM hardening, rotation, and the error taxonomy.
  • API reference — the SDK surface and the deployed store's /v1 HTTP API.
  • Signing keys — the Ed25519/ES256 signing oracle: sign-only tokens, key rotation, and the never-exported private key.
  • Data model — the D1 schema, the version axes, the freshness anchor, and the audit log.
  • Deployment & CLI — deploy to your own account, KEK custody, rotation runbook, and break-glass.
  • Security model — what each layer defends and what it does not.