devsafe verifyPaid
Proves your backup is restorable without trusting the storage provider. Zero-knowledge: DevSafe verifies the integrity of every git bundle in user-owned storage against a signed commitment, then tells you whether a full restore would succeed.
Usage
$ devsafe verify <repo-id>
The repo-id is the identifier shown by devsafe status. You can also pass a local path and DevSafe will resolve the repo ID automatically.
What it does
When you run devsafe verify, three things happen in order:
- Chain check. DevSafe reads the sequence of encrypted git bundles stored in your user-owned storage. It verifies that every bundle's Merkle hash links to the previous one, forming an unbroken chain. If any bundle was modified, deleted, or reordered, the chain breaks and verification fails.
- AEAD check. Each bundle was encrypted with nonce-unique AEAD (AES-256-GCM). DevSafe decrypts each bundle locally and checks the authentication tag. If even a single bit was changed after encryption, the tag fails and verification stops.
- Restorability check. DevSafe runs
git bundle verifyon each decrypted bundle to confirm it contains valid git objects with all required prerequisites. This proves the backup could be restored to a working repository right now.
The result is a yes-or-no answer: can this backup be fully restored? No partial results, no "probably fine." Either every bundle passes all three checks, or verification fails.
Example output
$ devsafe verify api-server → fetching bundle inventory from R2... → found 47 bundles (sequence 001–047) → verifying chain integrity... ✓ Merkle chain intact (47/47 links) → verifying AEAD authentication tags... ✓ all 47 bundles pass authentication → verifying git bundle restorability... ✓ all 47 bundles pass git bundle verify ✓ api-server: VERIFIED bundles: 47 total size: 284 MB (encrypted) chain root: a3f8c1...d902 latest commit: e7b4f2...1a08 (main, 12 minutes ago) proof signature: sig_v1_9c4a...bf21
If verification fails, DevSafe tells you exactly which bundle broke and why:
$ devsafe verify design-tokens → fetching bundle inventory from R2... → found 23 bundles (sequence 001–023) → verifying chain integrity... ✗ chain break at bundle 019 expected hash: 7f2a91...c403 actual hash: b8d0e4...1f7a ✗ design-tokens: FAILED cause: bundle 019 was modified after encryption action: run "devsafe backup --force design-tokens" to create a fresh chain
Flags
--verbose- Print each bundle's hash and verification result as it is checked. Useful for large repositories with hundreds of bundles.
--json- Output the full verification result as JSON. Useful for CI pipelines and automation.
--all- Verify every repository tracked by DevSafe, not just one. Exits with code 1 if any repository fails.
--skip-restorability- Skip the
git bundle verifystep. Only checks the Merkle chain and AEAD tags. Faster, but does not prove the backup is actually restorable.
devsafe export-proof
Sometimes you need to prove a backup is valid to someone who does not have your encryption key. For example, an auditor, a compliance team, or a future version of yourself on a different machine.
devsafe export-proof creates a standalone verification proof that is decoupled from the backup lifecycle. The proof contains the Merkle root, chain metadata, and a cryptographic signature, but no encryption keys and no repository data.
$ devsafe export-proof api-server --out api-server-proof.json ✓ proof exported to api-server-proof.json repo: api-server bundles covered: 47 chain root: a3f8c1...d902 signed with: prod-2026 (public key embedded) proof format: v1
The exported proof file is small (typically under 10 KB) and safe to share. It contains no secrets.
--out <path>- Where to write the proof file. Defaults to
<repo-id>-proof.jsonin the current directory. --format <json|cbor>- Output format. JSON is human-readable. CBOR is compact and better for machine consumption.
devsafe verify-proof
Verifies a standalone proof file created by devsafe export-proof. This command needs only the proof file and the signer's public key. It does not need access to the backup, the encryption key, or the storage provider.
$ devsafe verify-proof api-server-proof.json --pubkey prod-2026.pub ✓ signature valid ✓ chain root: a3f8c1...d902 (47 bundles) ✓ proof timestamp: 2026-07-01T14:23:08Z ✓ VERIFIED: this proof was signed by the holder of prod-2026
This is useful for three scenarios:
- Audits. Hand the proof file and public key to an auditor. They can verify without accessing your storage or your encryption key.
- Team verification. Share the proof with teammates so they can confirm backups are intact without needing your credentials.
- Disaster recovery planning. Store proof files alongside your recovery phrase. If you need to restore on a new machine, you can verify the backup chain is intact before downloading anything.
--pubkey <path>- Path to the signer's public key file. If omitted, DevSafe checks
~/.devsafe/keys/for a matching key.
devsafe server-verify
Runs verification on the server side (your user-owned storage) without needing the encryption key on the verifying machine. This checks the Merkle chain and bundle sequence, but cannot check AEAD authentication tags or git bundle restorability because those require decryption.
Server-verify is designed for monitoring. You can run it from a CI job, a cron schedule, or a separate machine to continuously confirm that your storage provider has not lost or corrupted any bundles.
$ devsafe server-verify api-server → checking bundle inventory (no decryption)... → found 47 bundles (sequence 001–047) ✓ sequence complete (no gaps) ✓ Merkle chain intact (47/47 links) ✓ all bundle sizes within expected range ✓ api-server: SERVER-VERIFIED note: AEAD and restorability checks require the encryption key run "devsafe verify api-server" for a full verification
It confirms that your storage provider still has all the bundles in the right order. It cannot confirm that the contents are intact or restorable. Run a full devsafe verify periodically (weekly or monthly) to get complete assurance.
CI integration
You can run verification in a CI pipeline to catch storage problems automatically. Use --json for machine-readable output and check the exit code.
# .github/workflows/verify-backups.yml name: Verify Backups on: schedule: - cron: '0 6 * * 1' # every Monday at 6am jobs: verify: runs-on: ubuntu-latest steps: - name: Install DevSafe run: curl -fsSL https://get.devsafe.com | sh - name: Server-verify all repos run: devsafe server-verify --all --json
Exit codes
0- Verification passed.1- Verification failed. At least one check did not pass.2- Could not reach the storage provider. Network or credential issue.3- No bundles found for the given repo ID.