A new order inserted before page two can make an earlier row appear again. A deletion can instead cause another row to be skipped.
The independent module records a position within one synthetic selection instead of only an offset into a moving list. It changes no operational company records.
An offset and a position after a row mean different things
Skipping the first few records in a changing source can refer to different rows later. The experiment sorts a copied selection by tick and ID. Its next cursor names the last row’s two ordering values, distinguishing rows that share a tick.
This is not an eternally stable ordering for every service. Production keys may be editable and deleted records need a policy. Values inside this frozen selection do not change, so stability is limited to that boundary. It is not a promise to combine a live latest list with perfectly consistent historical continuation.
Bind the position to its selection
A cursor includes the selection fingerprint as well as its position. The fingerprint covers company, filters, query, revision and selected contents. Reusing a cursor with another condition or changed selection fails. Even reusing the caller’s revision number does not hide changed projected data.
The fingerprint checks agreement; it does not sign or conceal a cursor. The package uses base64 JSON and intentionally tests that a knowledgeable caller can construct another valid position within the same snapshot. Record authorization and any required cursor signing remain responsibilities of the real server.
Separate source changes from continued reading
Tests create a snapshot and then insert a new leading row or clear the original list. The existing result retains its selected rows; a newly created result reflects the changed source. Continuing an earlier read and refreshing to the latest view become different choices instead of an accidental mixture.
A server adopting this approach must decide where snapshots live, how long they last and who may read them later. This module retains Python values only and implements no persistent snapshot service or expiry. It does not claim that closing a browser can recover the same server selection; durable query state is another responsibility.
Do not turn invalid continuation into a normal empty page
Another snapshot’s cursor, malformed text and an unknown position fail explicitly. Returning an empty list would make a reader think the list was exhausted. Normal completion has no next_cursor, while invalid continuation is rejected. Limits also require an integer from one to fifty. Cursor input is bounded to five hundred characters and must decode to exactly the known snapshot and position fields. A boolean is not accepted as a page-size integer even though Python normally treats booleans as integers.
The model does not implement localized recovery UI. A real interface should explain whether to retain conditions and restart or create a new query. Expired selection, permission failure and malformed position can need different responses. Rejecting input in code and helping a person understand the next action require separate verification.
Leave evidence for overlap and omission checks
Tests compare equal-tick ordering, every page against complete output and rejection after query or content changes. Recorded runs show old and new snapshots side by side. They do not add or delete actual company orders or test browser pagination gestures.
A page-number control may look sufficient until business records keep changing. The design must define how the reader’s position relates to current data. I share a case where one comparable read matters more than silently replacing everything with the latest version, with code and stated adoption conditions.