Ghost Rows in the Audit Log — JavaScript Bug Hunt
The audit-log API of an internal admin tool paginates records for the dashboard.
- Language: JavaScript
- Layer: Backend
- Difficulty: Medium
- Modelled on: Every admin dashboard
- Visible tests: page 1 starts at the first record; page 2 continues without overlap; final partial page disables hasNext
- Reward: 50 XP for a complete fix
Briefing
The audit-log API of an internal admin tool paginates records for the dashboard. Customers report that page 1 is missing the newest records, and the same rows appear on two different pages.
The Express handler and the mock data layer are locked — the bug is isolated in paginate.js, the pure helper the handler delegates to.
Make the whole suite green without touching the locked files.
Bug report
BUG-3341 · Priority: High · Reported by: platform-eng
The dashboard shows 10 rows per page. With 25 records in the table:
- Page 1 starts at record #11 instead of record #1
- Records #21–25 appear on BOTH page 2 and page 3
- The "next page" arrow stays enabled on the final page, leading to an empty page 4
API contract (see handler.js): page is 1-based; response = { items, page, hasNext }.
Logs
GET /api/audit?page=1&limit=10 -> items[0].id = 11 (expected 1)
GET /api/audit?page=3&limit=10 -> hasNext = true (expected false)The code as shipped
src/api/paginate.js (editable)
// Pure pagination helper used by the audit-log handler.
// page is 1-based. Returns { skip, take, hasNext }.
exports.getPageWindow = function (page, limit, totalCount) {
var skip = page * limit;
var take = limit;
var hasNext = skip + take <= totalCount;
return { skip: skip, take: take, hasNext: hasNext };
};
Read-only context: src/api/db.js, src/api/handler.js.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.