What we keep
Two more places hold the story when something went wrong:
- Sentry holds every crash and refusal from every function, grouped so one cause is one issue, with the trace that led there. A dead letter is one grouped issue; a condition the monitor opens is one issue too.
- The review route on the ops function lists every event a person still owes a look, and closes each one with a required note. That note is the audit trail for the decision a person made; see Resolve a human-review flag.
What we do not build
- No audit table for CRM edits. Mirroring every Zoho field change into the engine would mean subscribing to every module and every field, synced or not, and storing changes the engine never acts on. Zoho already keeps that log; export it before its horizon passes rather than copy it live.
- No second copy of any of the five records. They are the source.
- No screen. The questions below are answered with a query in the SQL editor, starting from the evidence on the Sentry issue.
How to answer “who changed what, and when”
Why it works this way
- The five records already exist and are already written on every path; the decision costs nothing and removes nothing.
- The app log is the only place a person’s name is recorded, and it is the only place one is needed. Everything else is done by a system, and the system is named.
- Zoho’s log covers the one thing the engine cannot see. Copying it would be expensive; reading it in Zoho is free.
What can go wrong
- Zoho’s log has a horizon. Once it passes, the CRM side of a story is gone. Export it before then if a question is likely to outlive it.
- The webhook log is pruned at 90 days and the integration ledger at 13 months. A question older than that has only the sent-mail ledger, the app activity log and the monitor’s conditions to go on.
- A change that no record captures is invisible everywhere. A field edited in Zoho that the mirror does not carry is the case that bites: it leaves no trace on our side at all.