Browse docs
Docs / Guides / Verifiable History

Verifiable History

Version history is only as trustworthy as whoever keeps it. Swarmfile's history is built so you don't have to take our word for it: every commit is hash-chained to the ones before it, the service signs checkpoints of each branch with a published key, and a standalone tool, swarmfile-verify-history, lets you check a project's history yourself - on an audit host or in CI, with no Desktop App or mount.

This page explains what that gives you and where its limits are. For flags and exit codes, see the CLI reference.

Hash-chained commits#

Every commit has a commit hash computed from its own facts: the content-addressed id of the project tree it records (which in turn is built from the ids of every file's contents) and the hashes of its parent commits. Because each commit's hash covers its parents' hashes, a commit's hash covers the whole history behind it. Change one file in one old commit, or remove a commit from the middle, and every hash after it stops matching.

Commits get their hash once they're confirmed. Swarmfile doesn't compute commit hashes on the server: a client derives the commit (the Desktop App does this after a commit, or swarmfile git index on demand), and a second, independent derivation confirms it - a teammate's app, a fetch, or a project API key used in CI; an owner can also allow their own app to self-confirm. Until then a commit is provisional: it's in your history and fully usable, it just isn't part of the hash chain yet. swarmfile git status reports how many commits on a branch are still unconfirmed.

Signed checkpoints#

Hash chaining proves the history is internally consistent. It doesn't, on its own, stop someone who controls the server from replacing the whole chain with a different, equally consistent one. That's what checkpoints are for.

Periodically (hourly, for every branch that has changed since its last checkpoint) the Swarmfile service signs the branch's latest confirmed commit hash with an Ed25519 key. The verifier requires every checkpoint published for a branch to land on the chain it walks, so a history that has lost or replaced a checkpointed commit fails verification. The signing key can be rotated; the service publishes its current and retired public keys so older checkpoints stay verifiable.

Checking it yourself#

swarmfile-verify-history is installed with every Desktop App and runs on its own:

swarmfile-verify-history \
  --hub-url https://hub.swarmfile.com/orgs/<org-id>/projects/<project-id> \
  --org-id <org-id> \
  --project-id <project-id> \
  --branch main \
  --header "Authorization: Bearer $SWARMFILE_API_KEY" \
  --pin-key ./swarmfile-history-key.pub

It fetches the branch head, then walks back commit by commit to the start of history (or to a commit you name with --checkpoint-hash), recomputing every hash and checking every parent link. It then fetches the branch's checkpoints and checks each signature. Any mismatch is a failure with a non-zero exit, so you can gate a release pipeline on it; --json gives a machine-readable report.

Pin the key. Without --pin-key, the verifier checks signatures against the public key the same service is serving you, which proves the checkpoints match that key but not that the key is genuine. Pass the key you recorded out-of-band (from an earlier run, or from us directly) with --pin-key and the run only accepts signatures from keys you supplied. That's the mode that gives you independent assurance. Repeat --pin-key to accept a rotated key alongside the old one.

What it proves, and what it doesn't#

  • It proves that the history the service serves you is internally consistent - no edited commit, no broken link - and, with a pinned key, that the checkpoints on it were signed by the key you trust.
  • It doesn't, by itself, prove that this is the same history you saw last month. The checks run against the checkpoints the service lists, so keep your own record of a commit hash you care about (a release, a delivery) - or of the checkpoints from an earlier run - and confirm it's still on the branch.
  • Provisional commits aren't covered until they're confirmed. A branch with no confirmed commits yet reports that, rather than passing.
  • It needs the service to be reachable. The verifier needs no Desktop App or mount, but it reads the commit objects and checkpoints from the service as it walks; it doesn't verify an exported bundle offline.
  • Checkpoints require a signing key on the service. If the service you're checking hasn't configured one, the verifier says verifiable history isn't enabled there - an informational result unless you pinned a key, in which case it's a failure.

Where you'll see it#

  • Releases of a public project marked commit-pinned name the exact commit hash they were published from. The badge is the pointer; swarmfile-verify-history is how you check it.
  • git clone of a project uses the same confirmed commits: each git commit carries a Swarmfile-Commit: trailer naming the Swarmfile commit it came from. See Cloning a Project with Git.
  • Reproducible checkouts - swarmfile materialize hash:<commit-hash> writes exactly that commit's tree, the most precise pin you can give a CI job (tags can be moved; hashes can't).