fix(manager-core): F-P-012 keyset cursor on app_user_repo::list (created_at, id) tiebreaker
ORDER BY created_at DESC, id DESC but cursor was `WHERE created_at <
$2` — when two users were created at the same instant, pagination
could skip the second row at a page boundary or return it twice.
- Add ListCursor { created_at, id } with `<rfc3339>_<uuid>` encode /
decode helpers.
- Change WHERE predicate to `(created_at, id) < ($2, $3)` matching the
ORDER BY.
- Surface the opaque cursor string through UsersListOpts /
UsersListPage / users_admin_api ListUsersResponse instead of the raw
DateTime — keeps the wire format stable while the id half stops the
boundary bug.
Same shape as F-P-005 (execution_logs).
AUDIT.md anchor: F-P-012.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -560,7 +560,10 @@ impl UsersService for UsersServiceImpl {
|
||||
.list(
|
||||
cx.app_id,
|
||||
RepoListOpts {
|
||||
cursor: opts.cursor,
|
||||
cursor: opts
|
||||
.cursor
|
||||
.as_deref()
|
||||
.and_then(crate::app_user_repo::ListCursor::decode),
|
||||
limit,
|
||||
},
|
||||
)
|
||||
@@ -584,7 +587,7 @@ impl UsersService for UsersServiceImpl {
|
||||
.collect();
|
||||
Ok(UsersListPage {
|
||||
items,
|
||||
next_cursor: page.next_cursor,
|
||||
next_cursor: page.next_cursor.as_ref().map(|c| c.encode()),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user