The preview
Before a human is asked, Warden runs the change inside a transaction, captures the affected rows before and after, and rolls it back. The reviewer sees per-record differences:
A preview with no basis carries no changes at all, so no interface can render an empty diff that reads as “this changes nothing” when the truth is “nobody could tell”.
Previews are produced only when a human will look. Executing and rolling back a change is worth its cost for a reviewer and is pure overhead for a write policy already allows.
now(), defaults — differ between the preview and the commit, and every preview says so rather than letting a reviewer believe the generated ID they saw is the one that will exist.
Previews are masked
A preview reads the target table directly, so its rows hold raw values. They are masked and column-restricted exactly as an agent’s results would be, before the preview is stored. A review queue is rendered in browsers, may be sent to Slack, and outlives the operation; it must never become a way to read what the agent itself cannot.The fence
A human takes time. Between the preview and the click, the data can move. When the proposal is made, Warden records the state of the rows the change targets — for PostgreSQL, each row’sxmin, the system column that changes whenever a row is updated. At approval, the commit transaction re-reads those rows with them locked (FOR UPDATE) and compares. If anything differs, the change is refused:
What a fence catches
- A row the reviewer saw was modified by someone else.
- A row in the affected set was deleted.
- A row that did not match the predicate now does.