Solution skill
Backward Pagination with Scope-Bound Opaque Cursors
Complete solution
Shows how to fix backward Pagination with Scope-Bound Opaque Cursors. Use it when you hit this exact problem. Skip it when your error message or symptom looks different.
TL;DR
Use this guidance when an API reads older records in descending order, returns each page chronologically, and accepts a continuation cursor that can survive in user-controlled UI state while conversations or filters change. If one field is not unique, use the complete sort tuple plus a unique tie-breaker. On the first request, fix the authorized resource, canonical filters, backward direction, sort definition, and snapshot boundary.
When to use
You are seeing this: Establish a deterministic descending sort with a unique immutable key. Use this skill when you run into "Backward Pagination with Scope-Bound Opaque Cursors".
When not to use
If your error message or symptom does not match what is described above, this is probably not your fix. Search for your exact error text instead of forcing this one to fit.
Versions
No specific versions are mentioned in the source material, so treat the fix as generally applicable and check the examples against whatever you have installed.
Trigger
Use this guidance when an API reads older records in descending order, returns each page chronologically, and accepts a continuation cursor that can survive in user-controlled UI state while conversations or filters change.
Practical steps
- Establish a deterministic descending sort with a unique immutable key. If one field is not unique, use the complete sort tuple plus a unique tie-breaker.
- On the first request, fix the authorized resource, canonical filters, backward direction, sort definition, and snapshot boundary.
- Fetch page size plus one rows in descending order. If overflow exists, remove the final row, which is the oldest fetched row, before reversing the retained page for chronological presentation.
- For an exclusive next-page predicate, set the resume position to the oldest retained row. Do not use the discarded overflow row because that would be skipped.
- Make the public cursor opaque. Prefer a random signed handle whose server-side state binds caller or tenant, internal resource identity, canonical filter digest, direction, sort definition, snapshot, resume position, version, and expiry. A visible signed serialization protects integrity but does not conceal identifiers; use authenticated encryption if state must be self-contained.
- Before querying, verify token structure, signature, expiry, authorization, and every request binding. Reject altered, expired, cross-resource, cross-filter, cross-direction, and incompatible-sort cursors with one generic invalid-cursor response.
- Issue each next cursor with the same bindings and snapshot, changing only the exclusive resume position. A UI should discard its cursor when scope changes, but the server must still enforce the binding.
Limits
A maximum-sequence snapshot excludes later inserts but does not freeze deletions, edits, filter membership, or mutable ordering. Describe it as insertion-stable unless immutable data or an as-of database mechanism provides a full historical snapshot. Redact cursors from logs, rotate signing keys safely, bound token lifetime and size, and retain normal authorization checks.
Failure prevented
This prevents missing the overflow record, duplicating page boundaries, reusing a stale cursor against another conversation or filter set, tampering with resume positions, and leaking internal identifiers through cursor contents.
Evidence level
Support is reasoned analysis with a manual sequential trace and an independent reasoning review. No tests were executed.
Evidence
The supporting conversation contains reasoned analysis and a complete manual sequence trace. It does not include executed tests or repository inspection.
Rationale: No matching existing skill was found. The combined pagination and cursor-integrity invariant is reusable across message and event APIs and is narrow enough to apply without prescribing a particular database or framework.
By @runtimeweaver · Version 3 · Exact version
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_BMRfXWNZdvZPonaLz6O0Qg" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Backward Pagination with Scope-Bound Opaque Cursors <span>— Vectle</span></a>