Time-travel debugger

Record the app's ChangeEvent timeline and scrub a table's rows back and forward through it — read-only point-in-time replay, env-gated + redacted, surfaced in the DevTools / cloud Time-travel panel.

The time-travel debugger records the app's ChangeEvent stream into a bounded, redacted ring and lets you scrub any table's rows back and forward through it — replaying what the data looked like at any recorded point. Read-only: replay reconstructs a row-set by reversing the recorded changes over the live rows; it never writes.

Turn it on

Recording is env-gated and off by default in production (volume + PII are the real cost — use OTLP for prod forensics). Set VOLTRO_TIMELINE:

value records
off (also 0 / false) nothing
interesting (also on / 1 / true) user tables only (skips _voltro_* framework noise)
all every table (except the timeline's own writes)

The default is interesting outside production, off in production — the same environment-aware default the durable trace persistence uses.

Sensitive-looking columns (password / secret / token / api_key / authorization / cookie / ssn / credit_card / cvv / …) are redacted before a row enters the ring — PII never sits in the debug buffer.

Scrub it

Open the Time-travel panel in the DevTools dashboard (or the cloud dashboard, for a deployed app): pick a table, drag the scrubber across the recorded sequence, and the panel reconstructs that table's rows as of the selected point. The event log shows every recorded change; click one to scrub to just before it. "Jump to now" returns to live.

The endpoint

The panel reads two read-only inspect endpoints:

  • GET /_voltro/inspect/timeline — the recorded events (?table=&tenantId=&from=&to=&limit=) plus the current sequence (currentSeq).
  • GET /_voltro/inspect/timeline/replay?table=<t>&seq=<n><t>'s row-set as of sequence <n>.
# Gated by the same inspect auth as every /_voltro/inspect/* endpoint.
curl "http://localhost:4000/_voltro/inspect/timeline?table=todos&limit=50"
curl "http://localhost:4000/_voltro/inspect/timeline/replay?table=todos&seq=42"

Limits

  • Read-only. Time-travel never writes — restoring a past value is the universal-undo primitive's job (and only for safe inverses).
  • In-memory ring (bounded, per-process) in v1 — it is for scrubbing recent history, not durable forensics: it resets on restart, and a replay is correct only as long as the events after your target sequence are still in the ring.
  • The inspect surface is a voltro dev / DevTools concern; out-of-band DB writes (not in the app's ChangeEvent stream) aren't recorded, and production should use OTLP for forensics.