b1rdmania makes Mike exports defensible with cryptographic proof

The fork gives project exports a way to show whether a received document is the same version held in the workspace.

compliancesecurity

For teams sharing AI-assisted legal work beyond their own system, this is a meaningful trust upgrade. Each new document version receives a cryptographic fingerprint, and a project export now carries a manifest tying those fingerprints to the acceptance and rejection record.

  • Tamper checks: recipients can compare a document against the exported record to spot altered files.
  • Optional signing: organisations with managed signing keys can add independent proof that the manifest came from their deployment; others can still export an unsigned record.
  • Public verification key: recipients can obtain the trusted key separately, rather than relying on a key included in an editable export.
  • Honest limits: older documents are labelled unverifiable, not quietly presented as checked.

The work stops short of proving when a document existed, but it makes the chain of custody around current exports far clearer.

So what Managing partners, GCs and legal-ops teams handling sensitive AI-assisted documents should care if they need a credible answer to: is this the file our workspace actually held?

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

2 commits from b1rdmania/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
562a8139 feat: content hashes on document versions + signed project export manifest Andy 2026-07-31 ↗ GitHub
commit body
Stores a SHA-256 of every document version's bytes at write time and adds a
per-project export manifest listing them alongside the accept/reject trail, so
an exported file set can be checked against what the workspace held.

The manifest carries a SHA-256 digest over a canonical form of its body,
Ed25519-signed when MANIFEST_SIGNING_KEY is set. Signing is optional so a
self-hosted deployment without key custody can still export; a malformed key
throws rather than silently downgrading to unsigned. The signature covers a
versioned context string and a NUL byte before the digest bytes, so it cannot
be replayed as a signature over another object, and it verifies with any
Ed25519 library. The public key is served at GET /manifest-signing-key.

Rebase of #181 onto current main, plus the signing requested on that PR.
18a00513 Address review on the export manifest Andy 2026-07-31 ↗ GitHub
commit body
- canonicalize rejects non-plain objects. A Date serialised as {}, a
  Buffer enumerated its indices, a Map became {}. None can reach a
  manifest body today, but a silently wrong serialisation is the same
  failure class as the non-finite number already rejected, and every
  digest rests on this function.
- Validate MANIFEST_SIGNING_KEY at boot. A malformed key previously
  surfaced when a user's first export failed; it now stops startup with
  the same message, and a working key logs its key id.
- Bulk copy takes size_bytes from the bytes being hashed rather than
  inheriting it from the active version, so size and content_sha256
  always describe the same content. A verifier that stats a file before
  hashing it should not see a size that disagrees with the hash.
- README notes that soft-deleted versions stay in the manifest. Dropping
  them would weaken the attestation, but it makes their filenames and
  timestamps visible to anyone with project access, which is worth
  stating rather than leaving to be discovered.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-1321.md from inside the repo you want the changes in.

⬇ Download capture-thread-1321.md