Story 1216: Matter List Numbered Pagination
This walkthrough records the backend contract change for GET /app/matters. The endpoint now supports numbered pagination for pramaan-app while preserving the existing cursor contract during the migration window.
Contract Change
| Surface | Before | After |
|---|---|---|
| Query | cursor plus limit. |
page and page_size are accepted. cursor and limit still work. |
| Response | { matters, nextCursor }. |
{ matters, nextCursor, total, page, pageSize }. |
| Filtering | Status, type, and opened-date parameters were part of the route contract. | The same filters are applied before offset/page pagination and before total counting. |
Compatibility Behavior
Existing consumers that call /app/matters?limit=50 or use nextCursor can keep doing so. When page_size is absent, the response pageSize mirrors the legacy limit. When cursor is supplied, cursor paging wins for row selection, and total still reports the full filtered result count.
First-Run State
A firm with no matters returns { matters: [], nextCursor: null, total: 0, page: 1, pageSize: 50 } for GET /app/matters?page=1&page_size=50. This keeps the app's numbered pagination control usable even before a firm creates its first matter.
OpenAPI Mirror Impact
openapi/app-api.json now exposes page, page_size, and the new response metadata. pramaan-app can sync the mirror and regenerate client schemas without hand-written contract patches.
Verification
Automated coverage was added for empty first-run metadata, numbered page slicing, filtered totals, cursor compatibility, DTO round-trips, and OpenAPI parameter/response shape assertions.
The Docker-backed local test path was run against the isolated Postgres test database with make test-db and make test.