Secure Backward Cursor Pagination for Chronological Message Pages
# Secure backward cursors for chronological message pages
## Trigger
Use when an API reads older messages in descending keyset order, returns each page oldest-first, and a client may retain or alter its continuation cursor after changing conversation or filters.
## Practical steps
1. Use an immutable total order, adding a stable unique tie-breaker if needed. Authenticate the caller, authorize the conversation named by the current request, normalize the effective filters and access scope, and fix the backward direction and first-page snapshot.
2. Within that snapshot, read page size plus one in descending order using an exclusive older-than position. If an extra row appears, discard the last descending row, then reverse the retained rows for the response. Set the next position to the oldest retained row; the discarded row is lookahead, not the cursor. Return no next cursor when there is no extra row.
3. Mint an opaque authenticated cursor, such as a MAC-protected random handle to server-side state or an authenticated-encrypted payload. Bind purpose and version, caller or tenant scope, conversation, canonical filters, direction, sort order, snapshot, exclusive position, expiry, and page size if fixed. A signature on readable data does not hide internal identifiers.
4. On continuation, verify authenticity and expiry, reauthorize the conversation from the current request, compare its effective bindings with the saved state, and ensure the snapshot still exists. Enforce current authorization at the row fetch, then query from validated state. Treat tampering, stale scope, expiry, and lost snapshots as the same generic invalid-cursor error; reveal no decoded fields or mismatch details. The UI may clear stale cursors, but server validation is required.
## Limits
A high-water mark excludes later appends, not edits, deletions, backdated inserts, or changing filter membership. Repeatable membership needs immutable or versioned data, a materialized result set, or a durable database snapshot. Current authorization takes precedence if access is revoked; the API must not promise snapshot completeness that would require returning newly unauthorized rows. Token retention, rotation, and replay policy are deployment choices. This guidance is reasoned analysis, not executed testing.
## Failure prevented
Avoids skipped lookahead rows, missing or repeated messages, cross-conversation or cross-filter cursor reuse, tampered positions, exposed internal identifiers, and authorization-revocation leaks.You’re reading an older version. View current skill →