bans: a replayed Block or Undo{Block} can no longer weaken a standing ban master
Chunk-7 finding 5 from the second-opinion re-review. The ban row was last-writer-wins, and the last writer is not the last moderator: a dead-letter redrive, a backfill replay, or a delayed redelivery presents an OLD Block again under a NEW activity id that inbox dedup cannot recognize. Temp ban lapses → moderators escalate to permanent → the old Block replays → expires_at rewinds to the past and Standing() reads unbanned forever (Lemmy sends its Block exactly once). The same last-writer-wins rewrote reason and remove_data, and a redriven stale Undo{Block} deleted a newer ban unconditionally. Both guards live in SQL on the DB clock — the same now() Standing() reads: - Ban(): the upsert's DO UPDATE now refuses a write that is already expired on arrival when the stored ban is in force (guarding the whole SET, not just the expiry), and RETURNING reports the stored row's in-force state, which also moves the pending-delivery cancellation gate off Go's clock — retiring the store half of the three-clocks issue (finding 10). - Lift(): the delete proceeds only when the Undo names no expiry, the standing ban is no stronger than the one being reversed, or the row has lapsed anyway. A refused lift returns retained=true, which the ingest layer surfaces as a counted (tidepool_block_undo_stale_refused), warned, reasoned skip — distinct from "nothing to lift". Documented residuals: an Undo naming no expiry (Lemmy's permanent-ban shape) still lifts unconditionally — the row holds nothing to compare a replay against; and an in-force stale Block may shorten a live ban, indistinguishable from a legitimate re-issue and failing in the mild direction. Both pinned by explicit test assertions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>