Start
Best practices
Most of these come down to one idea: a sealed record is permanent. Decisions you would normally take casually about logging become decisions you cannot revisit, so it is worth a few minutes before your first event.
1. Never send secrets
Passwords, API keys, tokens, session cookies, private keys, card numbers. None of them belong in an event, and an event containing one cannot be unsent.
Ordinary logs forgive this because they rotate out. Evidence does not rotate: the whole value of the product is that the record survives and cannot be quietly edited. A leaked secret in a sealed trail is a secret you must rotate, and the record of it stays.
- Log that authentication happened, its outcome, and who it concerned — never the credential.
- If your application already redacts on the way to your log pipeline, redact before enTrail too. The two are separate paths.
- Scan your event builder the way you scan your repository for secrets. The same mistakes appear there.
2. Keep personal data to what the record actually needs
An audit trail needs to identify who, not to describe them. In most cases a stable identifier is enough, and it is a better record than a name because it does not change when someone marries.
| Instead of | Send |
|---|---|
| Full name, address, date of birth | The internal identifier you already use |
| Email address, where it is only used to match records | A hash of it, which proves sameness without carrying it |
| A free-text description quoting the record that changed | What changed, and the identifier of the thing it changed on |
| A whole request or response body | The fields that matter, or a hash of the body |
Fields that commonly carry personal data are marked on the field reference, and several can be sent hashed instead. Two places deserve particular care because nothing validates them: the free-text description, and any custom field you add.
3. Name events so they still make sense in two years
- Dotted, noun then verb:
invoice.approved,record.deleted,agent.decision.approve. Consistency matters more than elegance. - Name the business event, not the code path.
payment.refundedoutlivesrefund_handler_v2_called. - Use the outcome field rather than encoding success and failure into the action name.
- Set a correlation id across the events of one operation. It is what lets you show that an approval followed a recommendation rather than preceded it.
4. Send the identity, whatever kind it is
Service accounts, scheduled jobs, machines and AI agents are actors too. "The system did it" is the answer that makes an audit trail useless, and the actor type field exists precisely so a background job at three in the morning is attributable.
5. One key per sending system, rotated deliberately
Give each application or service its own key so you can revoke narrowly, keep secrets in a secret store rather than the repository, and rotate when someone with access leaves. The two-slot rotation is designed so this costs no downtime. See key lifecycle.
6. Keep the receipt
Store the receipt, or at least the event id and payload hash, alongside your own records. The receipt is what you hand to someone else later, and collecting it at the time is easier than reconstructing which event you meant.
7. Verify before you need to
Run a verification, and the tamper test, before an auditor asks. The first time anyone checks your evidence should not be the day it matters. See verify a receipt.
The shared responsibility model
enTrail is responsible for the integrity of the record. You are responsible for what is in it. That line is sharp, and it is worth stating plainly because the consequences fall on different people.
| enTrail is responsible for | You are responsible for |
|---|---|
| Sealing exactly the bytes you sent, without transforming them | What those bytes contain |
| Making alteration, deletion, reordering and backdating detectable, by us or by anyone holding the storage | Deciding which events are worth sealing in the first place |
| Publishing signed heads off the box, and anchoring them in Bitcoin | Keeping receipts, and storing them with your own records |
| Enforcing the field contract, and refusing what does not validate | Ensuring no secret, password or unnecessary personal data reaches a message, a description or a custom field. Nothing validates free text |
| Running the box, its updates and its availability, for a managed box | Your keys: who holds them, where they are stored, and rotating them |
| Telling you plainly what verification does and does not prove | Your lawful basis for processing, your retention decision, and your own obligations to the people in your records |
A checklist before your first production event
- No secrets, credentials or tokens anywhere in the payload, including inside free text
- Personal data reduced to identifiers, hashed where you only need to match
- Action names agreed and consistent across teams
- Correlation ids set across multi-step operations
- Non-human actors sending their own identity
- One key per sending system, from a secret store
- Retention chosen deliberately: it can be lengthened later, never shortened
- One event verified end to end, including the tamper test
If you are on a pilot or beta box, read before you send real data as well. Those constraints are temporary; these practices are not.