The persisted cursor was a bare (String, usize) tuple in which usize::MAX meant
"already in replay mode". A real walk position of usize::MAX would have decoded
as a bare state token and its walk would have been skipped silently.
ReconcileCursor now carries the two modes, and the pass is split along the same
boundary: reconcile -> walk_baseline (WalkOutcome: ReplayFrom / Persist /
NoProgress) -> replay_changes.
Behaviour is unchanged; the four walk/replay budget constants move out of the
function body to module level, and the /changes parameter is renamed
max_changes -> initial_changes because it only sizes the first call.
domain/jmap: current_state -> session_state (RFC 8620 Section 2.1, which is not
the Email-collection token that Email/changes wants as sinceState) and
has_more -> has_more_changes (hasMoreChanges). EmailChanges and both trait
methods now carry RFC-referenced docs that spell out why oldState and destroyed
are dropped at the boundary.
It was populated at the client boundary but read nowhere in production -
the doc comment claimed "retained for cursor accounting", yet the cursor
is just new_state. Deletions are dropped at the boundary instead of being
plumbed through and then ignored one layer in.
The upstream crate still returns destroyed; we simply stop carrying it.
Re-add it only when something acts on deletions (e.g. pruning a dedup
key) - keeping an unread Vec costs a copy on every changes page for
nothing.
- worker/state: paginate Email/changes by widening maxChanges on the same
sinceState (jmap-client 0.4.2 has no upToId) to avoid skipping a batch when
advancing per page; make dedup+enqueue atomic via claim_dedup_and_enqueue
(Lua SET NX EX then XADD); scale the XAUTOCLAIM idle threshold by batch size;
XACK payload-less malformed stream entries out of the PEL via ack_malformed;
fail closed on unknown streams (Err); tighten SET NX EX TTL to .max(1);
derive the CSPRNG fallback owner-token from time+PID+counter instead of a
constant; clear the push verification digest on push:disable
- worker: /help menu now lists only the consent triggers the parser accepts
- jmap/config: complete client and configuration validation