Docs

What keel is and how to use it.

keel decides whether a new version of your software is allowed to replace the running one. You import it into the deploy you already have. It does not deploy, run servers, or hold your keys. You supply those steps; keel makes the yes-or-no call and records it.

Quick start

Four commands, no account.

The quick path exercises the real library. It does not call a network service or ask for a secret.

  1. git clone https://github.com/acoyfellow/keelclone the repo
  2. bun installinstall, zero runtime dependencies
  3. bun test75 deterministic checks across the gate
  4. bun run examples/refuse-bad-self-update/run.tswatch a bad candidate get refused

Concepts

The five parts.

A new version is named by its content. These five parts decide whether it is allowed to replace the one running now.

Proof
An Ed25519, artifact-bound record of what the verifier observed. A proof is admitted only for the exact content digest it names.
Keyring
Verifier keys with validity windows, rotation, and revocation. A valid signature from a revoked or rotated-out key is refused.
Threshold
k-of-n distinct trusted keys must sign. One compromised key cannot admit a candidate alone.
Promote
Compare-and-swap against the known baseline. A candidate cannot clobber production if the baseline moved underneath it.
Decision
Every step is hash-chained and signed, survives a restart, and an edited or removed entry is detectable.

Examples

What each example proves.

Every example runs on its own and writes a short receipt: what it checked, and where it could still be wrong.

  • refused

    Bad live candidate refused

    A candidate that builds but fails a real request cannot promote.

    bun run examples/refuse-bad-self-update/run.ts promotion denied; known-good restored
  • refused

    Stolen token inert

    A valid write token cannot promote a different artifact without a fresh proof.

    bun run examples/stolen-token-useless/run.ts ref unchanged after replay and forgery attempts
  • refused

    One key cannot ship

    A 2-of-3 threshold blocks a single compromised verifier key.

    bun run examples/one-key-cant-ship/run.ts single signer refused; edited log detected
  • accepted

    Audit survives restart

    Trust state and signed decisions survive reload and detect tamper.

    bun run examples/audit-survives-restart/run.ts 7 checks pass after reload and tamper injection
  • accepted

    Hand-rolled gate deleted

    A toy worker deletes local deploy-gate logic by importing keel.

    bun run examples/delete-the-handrolled-gate/run.ts 41 owner lines shrink to 25 while attacks flip to refused

Deploy

It is a library you import.

Import keel where your deploy already runs and give it four steps: deploy, verify, roll back, and store. keel makes the call; your steps do the work. There is nothing to host.

  1. import { verifySignedProof, Keyring } from './keel/src/index.ts'path import; keel is not published to npm
  2. bun testkeel ships 75 checks; test your own ports the same way

Limits

What keel does not do.

These are the known edges. The default runner and store are starting points to replace, and the gaps below are written down on purpose.

Live smoke
The default runner boots a built server and sends one request. It is a reference runner, not a hosted preview environment.
Minting
The minting role and scoped token are enforced in the model. Production must back the minting role with a real, separately held credential.
Persistence
The default store is file-backed with a checksum. A KV, Durable Object, or D1 adapter implements the same interface.
Trust root
Threshold raises the cost of a single compromise. It does not remove the owner root as ultimate authority.
Leverage
The delete-the-gate result is real inside this repo. An out-of-tree worker doing the same against its live deploy is recorded as unproven.