Your audit trail is probably unverifiable. Not broken, not missing transfers: just unverifiable. There's a meaningful difference.
A database row recording "file transferred, 14:23:07, operator: svc-account" is a record. You can query it, export it to CSV, and present it during a review. But you cannot prove it hasn't been altered since it was written, and you cannot prove the server presenting it is showing you the real table.
Most MFT vendors give you a log view. We give you a chain you can prove from a terminal.
Records vs chains
A log is a sequence of entries. A chain links each entry to every entry before it, mathematically.
MFTPlus uses SHA-256 hash chaining. When a transfer event is recorded, the system computes a hash over the entry's core fields (transfer reference, file hash, timestamp, operator) combined with the hash of the previous entry. That hash is stored alongside the record.
Alter any field in any entry. Every hash from that point forward produces a different value. The break is visible at exactly the sequence number where it happened.
mftctl audit verify
The command runs two checks.
First: a call to the server-side verification endpoint. The server has access to your organisation's identifier and runs an authoritative check against its own chain state.
Second: the CLI fetches the raw chain entries and recomputes every hash locally. Pipe-separated canonical serialization. SHA-256. PrevHash linkage from entry 1 to N. The complete chain, computed independently.
$ mftctl audit verify TXFR-2847
Fetching chain... 43 entries
Server verification: PASS
Local recomputation... 43/43 checked
Result: PROVEN
Chain integrity verified. 43 entries, 0 discrepancies.
Or, if the chain has been altered:
Result: TAMPERED at seq 28
Local hash at entry 28 does not match chain record.
Server verification: PASS
The server says PASS. Local recomputation says TAMPERED at seq 28. That's the check that matters.
Why two checks?
The server controls both the data and the verification endpoint. An API that reads from a tampered table and returns "verified: true" is internally consistent. It passes a server-side check. It only fails when something outside the server recomputes the math.
This matters most for insider scenarios: an administrator or compromised server process that modifies audit entries and the verification endpoint together. An external attacker altering individual entries without breaking the chain is technically hard. Server-side tampering is not. Local recomputation is the countermeasure.
The Go CLI implements the same canonical serialization as the TypeScript server: same field order, same genesis convention for entry 1, SHA-256 throughout. Two implementations from different codebases. They can diverge on bugs, but they cannot both produce the same wrong hash.
Offline and air-gapped
Export the chain. Load it onto a machine with no network access. Run mftctl audit verify.
The CLI needs no connection to your infrastructure, no dashboard login. SHA-256 is built into every modern runtime. For compliance audits, this is what makes independent verification practical: the auditor requests a chain export, takes it to an isolated environment, and verifies it without access to your systems.
The compliance case
SOC 2, ISO 27001, and POPIA all require demonstrable audit trails for data movement. A log view satisfies the "we have records" requirement. But when an auditor asks to verify the trail hasn't been tampered with, a dashboard screenshot can't prove it.
mftctl audit verify does. PROVEN or TAMPERED at seq X. From a terminal, offline if needed, without trusting the vendor's server.
That's the difference between a record and a proof.
FAQ
What does "PROVEN" mean in the mftctl audit verify output?
Both checks passed: the server-side verification endpoint confirmed the chain, and the CLI independently recomputed every SHA-256 hash and found no discrepancies. No entries have been altered since they were written.
Can I verify the audit chain without internet access?
Yes. Export the chain and run mftctl audit verify on any machine with the CLI installed. It requires only SHA-256, which is built into every modern runtime. No network connection, no dashboard login, no API key.
Why does the CLI run two verification checks instead of one?
The server controls both the data and its own verification endpoint. A compromised server could return "verified" while presenting a tampered chain. The CLI's local recomputation catches this because it uses an independent Go implementation of the same algorithm — the two can't agree on a wrong answer.
Which MFTPlus tier includes audit chain verification?
The SHA-256 hash chain and mftctl audit verify are available from the Starter tier ($150/month) upward. The Community tier has basic operational audit logs but not cryptographic chain verification.
Can third parties implement their own verifiers?
Yes. The canonical serialization format is documented: pipe-separated fields in a fixed order, 64-character zero string as prevHash for the genesis entry, SHA-256 throughout. Any SHA-256 implementation can verify the chain independently.
Verify your first audit chain
Audit chain documentation →