Eight months from now, someone disputes an agent's action. "Our systems never did that," says one side. "They did," says the other. Most logging stacks can only escalate that argument. A signed event ends it — because the record itself carries proof of who attested to it. This post explains the per-event signature, the quiet workhorse of the whole product.
TLS proves the pipe. A signature proves the author.
People sometimes ask why transport encryption isn't enough. TLS guarantees the connection between your servers and ours wasn't eavesdropped or altered in flight — and says nothing once the data has landed. Whatever sits in a database afterwards is just bytes; nothing about them proves who produced them. A digital signature is a different animal: it travels with the event, forever, and anyone with the matching public key can check it — at ingest, next quarter, or years later in a dispute neither side saw coming. Pipes protect a moment; signatures protect a history.
What signing an event actually means
Your environment holds a private signing key, generated in your browser, never sent to us. The SDK wraps every event in an envelope and signs the event's canonical content — its identity, timestamp, type, and payload. Change one byte of any of those, anywhere, ever, and the signature stops verifying. "Canonical" is doing quiet work in that sentence: the bytes being signed are assembled by a fixed, documented recipe, so the same event always produces the same signable content — which is also why our Python and TypeScript SDKs can sign interchangeably and verification never wonders which one wrote the record.
The envelope also names which of your keys signed it, so routine key rotation never orphans old events: each one points at the public key that can vouch for it. Rotate every quarter for five years and every event across that whole span stays verifiable — against the key that was current when it was written, which is exactly what an auditor reconstructing 2026 wants in 2031.
Checked at the door
The ingest endpoint verifies the envelope against your registered public key before the event is stored, and events from unregistered keys are rejected outright — no "trust on first use", no unsigned side door. This ordering matters: it means everything in your trail passed the check on arrival. There is no class of "we stored it, verification pending" records to explain to an auditor — and a forged event's fate is decided at the boundary, publicly and mechanically, rather than by an investigation after the fact.
Non-repudiation, in plain terms
The property all this buys is called non-repudiation, and it cuts in both directions. Your organisation cannot later disown an event its own environment signed — which sounds like a constraint until you're the party relying on the record. And nobody else, Wytness included, can manufacture an event in your name, because forging the signature requires the private key only you hold. The record is binding on you and safe from everyone — that combination is what turns a log into evidence.
Return to the dispute this post opened with. With signatures, the argument has a procedure instead of a stalemate: produce the record, verify it against the published key — in the dashboard, with the offline verifier, or with any standard Ed25519 implementation the sceptical side prefers. Either the record verifies, and the "our systems never did that" position collapses, or it doesn't verify, and something genuinely deserves investigation. Both outcomes are progress; neither depends on anyone's word.
One event, or the whole story?
The signature authenticates a single event. Whether the sequence is intact — nothing deleted, nothing inserted, nothing reordered — is a different property with a different mechanism, and it's the subject of Tamper-evidence in practice. Together they answer the two questions every dispute comes down to: is this record real, and is this record complete?
Questions about verification in your audit workflow? Ask us.