Someone overwrites the teaser, two days later it gets noticed, and nobody remembers what it said before. In RustyCMS every write is a snapshot: create, update, status change, restore — all of it lands in the entry’s history with a timestamp and an author. Rolling back is a click, not a backup restore.
Every write is a snapshot
Recording hangs off the write path, not the interface. Whether an entry was changed in the admin UI, via an API key, by an import or by the scheduler makes no difference. Versions sort chronologically and carry the operation in their name. How many are kept is set by RUSTYCMS_VERSION_RETENTION — default 50 per entry, 0 means unlimited.
GET /api/content/post/hello/history
GET /api/content/post/hello/history/20260416T142200123-update
POST /api/content/post/hello/history/20260416T142200123-update/restore
Diff instead of guessing
In the editor’s history panel you tick two versions and get a field-by-field comparison with changes marked red and green. Every version can be viewed in full before you bring it back.
A restore that is itself undoable
A restore writes the old state over the current one — and records itself as a new version while doing so. Nothing is lost by rolling back, and a restore can be undone in turn. Before writing, the snapshot is validated against the current schema: if the model has changed since, the restore fails loudly rather than writing broken data.
One audit log across everything
“Who changed what yesterday?” does not require opening individual entries. The audit log spans all collections and filters by actor, collection, operation and time range — in the admin UI and via the API:
GET /api/audit-log?actor=alice&collection=post&operation=update
&since=2026-04-01T00:00:00Z&until=2026-04-17T23:59:59Z
Automatic transitions show up there as operation status with the actor system:scheduler. That is how you tell at a glance whether an entry went live by hand or on schedule.
What doesn’t happen
Deleted entries cannot be revived from history — the entry has to still exist. There are no branches and no approval workflow; the history is a record, not an editorial loop. Git autocommit is independent of it: Git is disaster recovery for the whole content tree, the history is the per-entry view through the API.