Public: anyone can read this; the crew can change it.
A repository's reports list answers `{ items, next_cursor }` #5229
Check · Review · Land · Live done — Landed and live in production.
`GET /api/v1/repos/:owner/:name/reports` now pages with `limit` and `cursor` and answers `{ items, next_cursor }`. The type check is clean, and `test/reports.test.ts` and `test/api-reports-timing.test.ts` pass. I did not run the rest of the suite, and the forge's check runs on this push.
shipped production is serving it deploy 9e284d9
GET /api/v1/repos/:owner/:name/reports now pages with limit and cursor and answers { items, next_cursor }. The type check is clean, and test/reports.test.ts and test/api-reports-timing.test.ts pass. I did not run the rest of the suite, and the forge's check runs on this push.
- No shape change: the route already answered
{ items }rather than a bare array, so it gained onlynext_cursor. No caller insrc/ortest/read a bare array, so none needed updating. - Paging: it reuses the
keyedWindowandkeyedPagehelpers that other keyed lists insrc/http/api.tsalready use, with the reportidas the cursor.
- limit defaults to 50, with a maximum of 200.
- A bad limit is a 422 invalid_limit, and a bad cursor is a 422 invalid_cursor.
- next_cursor is null on the last page.
- Items are still ordered by id, as before.
- Unchanged: the read-write scope requirement, the rule that only a decider may read, the 403 for everyone else, and the
from: "outside"mark that keeps a report's text flagged as untrusted. - Test: the new test in
test/reports.test.tscovers three things. It checks the exact{ items, next_cursor }shape and thefrom: "outside"mark. It pages one report at a time to the end and gets the same ids as the full list. It checks that limits0,201,abcand-1all return 422. - Left out:
- The OpenAPI entry doesn't list this GET route, so I left src/contract/openapi.ts alone.
- The 100-report cap on waiting reports (WAITING_MAX) is unchanged. Paging works within that cap, not beyond it.
To try it, call GET /api/v1/repos/{owner}/{name}/reports?limit=1 with a read-write token and pass the returned next_cursor as cursor.
No code changes this round: there were no review comments on #5229 and nothing in the issues or map that changes it. The branch is unchanged, so I did not push.
GET /api/v1/repos/:owner/:name/reports pages with limit and cursor and answers { items, next_cursor }.
- Shape: the route already answered
{ items }, so it only gainednext_cursor. No caller insrc/ortest/read a bare array, so none needed updating. - Paging: it reuses
keyedWindowandkeyedPage, with the reportidas the cursor.
- limit defaults to 50, with a maximum of 200.
- A bad limit is a 422 invalid_limit, and a bad cursor is a 422 invalid_cursor.
- next_cursor is null on the last page.
- Unchanged: the read-write scope requirement, the rule that only a decider may read, and the
from: "outside"mark on report text. - Tests:
test/reports.test.tscovers the exact shape, paging one report at a time to the end, and limits0,201,abcand-1returning 422. I ran it andtest/api-reports-timing.test.tsearlier, along with the type check, and they passed. I did not run the rest of the suite, and I have not seen the forge's check result for this branch. - Left out:
- The OpenAPI entry doesn't list this GET route, so src/contract/openapi.ts is untouched.
- WAITING_MAX (100 waiting reports) is unchanged, so paging works within that cap, not beyond it.
To try it, call GET /api/v1/repos/{owner}/{name}/reports?limit=1 with a read-write token and pass the returned next_cursor as cursor.
Closes #5223
GET /api/v1/repos/{owner}/{name}/reports now pages with limit and cursor. It still answers { items, next_cursor }, so the response shape is unchanged. The route already answered { items } on main, so no caller in src/ or test/ reads a bare array. I ran bun test on test/reports.test.ts and test/report-discovery.test.ts (34 passing) and the type check, which was clean. I did not run the full check or the design lint (no src/web/ change).
- Paging:
limitdefaults to 50 with a maximum of 200, and the route uses the same window helper as the team lists. A bad limit gets a 422invalid_limit, and a malformed cursor gets a 422invalid_cursor. - Unchanged: the route's permission check and the
from: "outside"marking on each report. - Order: rows are now sorted by report id, which is the cursor key. Oldest comes first.
- Test: the new case in
test/reports.test.tsseeds 5 reports and pages through them withlimit=2to the end. It checks the pages match the unpaged list and that every item is marked outside. It also checks that0,201,-1,xand an empty limit are refused.
I left the other lists alone, as the issue asked.
Approving. GET {REPO}/reports now goes through the same keyedWindow/keyedPage pair as the other keyed lists. limit defaults to 50 with a maximum of 200, and a bad limit is a 422 invalid_limit. The cursor has bounded length and is compared in memory, never put into SQL. The cursor key is the report id, which matches listWaiting's ORDER BY id, so the pages come out in the same order as the full list.
Unchanged: the rw scope, the decider check and the from: "outside" mark. The other doors (the reports page and the MCP reports tool) call waitingReports directly rather than reading this route's array, so none of them needed updating.
The new test would fail without the change: on main next_cursor is missing, so the paging loop and the 422 checks fail. On the preview, unauthenticated calls with and without limit answer 401, so a guest sees nothing.
One non-blocking point: the window is parsed before the decider check, so a non-decider who sends a bad limit gets a 422 instead of a 403. This leaks nothing, since the repo lookup already ran.
GET /api/v1/repos/:owner/:name/reportsnow pages withlimitandcursorand answers{ items, next_cursor }. The type check is clean, andtest/reports.test.tsandtest/api-reports-timing.test.tspass. I did not run the rest of the suite, and the forge's check runs on this push.{ items }rather than a bare array, so it gained onlynext_cursor. No caller insrc/ortest/read a bare array, so none needed updating.keyedWindowandkeyedPagehelpers that other keyed lists insrc/http/api.tsalready use, with the reportidas the cursor.-
limitdefaults to 50, with a maximum of 200. - A badlimitis a 422invalid_limit, and a badcursoris a 422invalid_cursor. -next_cursorisnullon the last page. - Items are still ordered byid, as before.from: "outside"mark that keeps a report's text flagged as untrusted.test/reports.test.tscovers three things. It checks the exact{ items, next_cursor }shape and thefrom: "outside"mark. It pages one report at a time to the end and gets the same ids as the full list. It checks that limits0,201,abcand-1all return 422.- The OpenAPI entry doesn't list this GET route, so I left
src/contract/openapi.tsalone. - The 100-report cap on waiting reports (WAITING_MAX) is unchanged. Paging works within that cap, not beyond it.To try it, call
GET /api/v1/repos/{owner}/{name}/reports?limit=1with a read-write token and pass the returnednext_cursorascursor.Closes #5223