Verified #018 established that different clocks can disagree about expiry. #019 asks a harder question: what if one clock first crosses expiry and later moves backward, making the old time value appear valid again after the execution history has changed?

ACTIVE→EXPIRED→CLOCK ROLLBACK→ACTIVE?

The same record visibly performs a Temporal ABA.

With one durable idempotency record expiring at 7,000,060, the service was queried at three logical wall-clock values:

A

7,000,050 → ACTIVEThe record is before expiry.

B

7,000,070 → EXPIREDThe expiry boundary has been crossed.

A

7,000,050 → ACTIVE againThe scalar returned to its old value.

Across all three observations the remote effect remained COMMITTED / effect_count=1. The value returned; the history did not.

Same wall-clock value ≠ same temporal state after history advances.

Unsafe · cleanup advances history, rollback resurrects replay permission.

The unsafe case committed one remote effect, lost the acknowledgement, then crossed expiry. Maintenance removed the expired dedupe record and advanced a monotonic temporal epoch:

EXPIRED→GC removes record→epoch 1 → 2

The wall clock then rolled back from 8,000,070 to 8,000,050, numerically before the original expiry. An un-fenced worker treated the old TTL window as safe replay territory and sent the same Idempotency-Key again.

same key→rolled-back time→APPLIED→2 EFFECTS

Final remote state: effect_count=2 / CONFLICT.

Safe A · monotonic temporal epoch fences the old decision.

Recovery bound itself to temporal epoch 2. Expiry cleanup advanced the service to epoch 3. After wall-clock rollback, the same-key retry still carried the old execution epoch.

expected epoch 2≠current epoch 3→HTTP 409→FENCED OUT

The service returned temporal_epoch_mismatch, preserved effect_count=1, and recovery reconciled authoritative COMMITTED.

Safe B · monotonic time watermark refuses to move backward.

The second safe control retained the largest time already observed in the trajectory:

seen 10,000,070→wall clock 10,000,050→effective now 10,000,070

The temporal state remained EXPIRED. Recovery reconciled the committed remote effect and made no second POST.

What #019 adds to TTP.

I35

SAME WALL-CLOCK VALUE ≠ SAME TEMPORAL STATE AFTER HISTORY ADVANCESA timestamp is not a history identifier.

I36

RETIRED SAFETY EPOCH MUST NOT BE RESURRECTED BY CLOCK ROLLBACKPast permission does not return with an old time value.

I37

TIME-BASED EXECUTION SHOULD BIND TO MONOTONIC HISTORYUse a temporal epoch, fence or monotonic watermark.

I38

CLOCK ROLLBACK AFTER IRREVERSIBLE TEMPORAL TRANSITION IS EVIDENCE CONFLICTFence or reconcile instead of replaying.

Evidence.

GitHub Actions run 31470122034 completed successfully. Artifact resonance-idempotency-clock-rollback-v1.0 has ID 9093020263 and digest sha256:6132fb3a357952eedcd54aac4d15b48cd429684f9630ed152f3c3b65674b9dce.

The run used PostgreSQL 17.6, psycopg 3.2.9 and a separate python:3.12-slim HTTP service with persistent SQLite effect/idempotency state. The container image digest was python@sha256:229a2c5bfa27522db7815ea81f9bed70af17ccb9de9fc7ad142b1877b5830d36.

Interpretation boundary.

The clock sequence is deterministic logical benchmark time. The experiment does not test operating-system clock rollback, NTP/PTP/chrony, leap seconds, hardware drift, distributed consensus time, multi-region timing or universal exactly-once guarantees. The TTL and timestamps are benchmark parameters, not production recommendations.

  1. Canonical report
  2. Benchmark harness
  3. TTP Temporal ABA rule
  4. Previous · Verified Report #018

Verdict: a reversible clock value must not be allowed to resurrect an execution state whose temporal history has already advanced.

RESONANCE Verified #019

clock rollback → temporal ABA → monotonic history → safe recovery.

Read TTP v1.0