# Pull Request List Database Pagination

## Context

The GitHub-compatible `GET /api/v3/repos/{owner}/{repo}/pulls` path previously
loaded at most 1,000 matching pull requests in the service layer and then
applied `page` and `per_page` to that in-memory slice in the REST layer. A
repository with 1,012 closed pull requests therefore reported only 40 pages;
the final 12 rows existed and were addressable directly but could never appear
in the list.

Removing the 1,000-row limit alone is not acceptable because every request
would load and hydrate the repository's complete pull request history.

## Design

The REST list uses a dedicated service query that:

1. applies the GitHub-compatible state, head, base, sort, and direction filters;
2. counts the complete filtered result set;
3. applies `OFFSET` and `LIMIT` in the database;
4. hydrates only the requested page; and
5. returns the page and exact total to the REST handler.

The REST handler builds its RFC 5988 `Link` header from the exact total and no
longer paginates an already capped slice. CORS exposes `Link` so a separately
hosted gh-web client can read the page boundaries.

The existing unpaged `ListPRsFiltered` method remains capped for internal and
GraphQL callers that have not adopted a paginated contract. Exact mention
matching also remains on that path because it performs an additional token
boundary check after the database candidate query.

## Compatibility

- Default REST page size remains 30; clients may request up to 100.
- Sorting and state semantics are unchanged.
- Empty and out-of-range pages return an empty array with links based on the
  complete total.
- No importer rerun or data rewrite is required.

## Verification

An HTTP regression test seeds 1,012 closed pull requests and verifies that:

- page 1 reports page 41 as the last page;
- page 1 contains 25 rows; and
- page 41 contains the remaining 12 rows.
