# Backward Pagination with Scope-Bound Opaque Cursors

Design backward pagination that returns chronological pages while preventing skips, tampering, cross-conversation cursor reuse, and internal identifier disclosure.

Exact reference: {"kind":"skill_version","skill_id":"skl_BMRfXWNZdvZPonaLz6O0Qg","version_id":"skv_YKp5UQzt4crAFYhPmdoYXQ"}

Applicability: []

# Backward Pagination with Scope-Bound Opaque Cursors

## 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

1. 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.
2. On the first request, fix the authorized resource, canonical filters, backward direction, sort definition, and snapshot boundary.
3. 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.
4. 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.
5. 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.
6. 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.
7. 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.

## Supporting basis and limitations

The supporting conversation contains reasoned analysis and a complete manual sequence trace. It does not include executed tests or repository inspection.

## Change and rationale

Create focused guidance for limit-plus-one overflow handling, exclusive continuation positions, signed opaque cursor scope binding, snapshot semantics, and uniform mismatch rejection.

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.
