Fix the cursor pagination for the admin user list

Review the AI's codeEasy12 min

Your task

The admin user list paged with LIMIT 50 OFFSET n, and while people signed up, QA saw some users twice and some never. The team is moving to keyset pagination: each page starts right after the previous page's last row, found by its sort key, not by a row count.

An assistant wrote keyset_page(rows, cursor, page_size). It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • rows: the users table as it is now, one string per row: "id|created_at", such as "u03|2026-01-03".
  • cursor: the last row of the previous page, in the same "id|created_at" form, or "" for the first page.
  • page_size: the most ids to return.
  • Return the ids on the page, in page order.

Rules the tests check:

  • A page_size of 0 or less returns an empty list.
  • Skip a row that does not split on | into exactly 2 parts, or whose id or created_at is empty.
  • Order the rows newest first: created_at descending, then id descending. Compare both as plain strings, character by character, with no date parsing. So "u9" comes before "u10".
  • Two rows with the same id and the same created_at are one row. The same id with a different created_at is a different row.
  • With an empty cursor, or one that does not split into 2 non-empty parts, return the first page_size rows of that order.
  • Otherwise return the first page_size rows that come strictly after the cursor in that order.
  • The cursor's row may no longer be in rows, because a user was deleted between pages. The page still starts right after the place the cursor's key has in the order.

Examples

keyset_page(rows: list[str], cursor: str, page_size: int) -> list[str]
Example 1
Inputkeyset_page(["u03|2026-01-03", "u01|2026-01-01", "u05|2026-01-03", "u02|2026-01-02", "u04|2026-01-04"], "", 2)
Output["u04", "u05"]
Example 2
Inputkeyset_page(["u03|2026-01-03", "u01|2026-01-01", "u05|2026-01-03", "u02|2026-01-02", "u04|2026-01-04"], "u05|2026-01-03", 2)
Output["u03", "u02"]
Example 3
Inputkeyset_page(["u03|2026-01-03", "u01|2026-01-01", "u05|2026-01-03", "u02|2026-01-02", "u04|2026-01-04", "u06|2026-01-05"], "u05|2026-01-03", 2)
Output["u03", "u02"]