Difficulty: Advanced
Problem
1. GET /api/enrollments/:identity returns all records for an identity with no limit
backend/src/routes/enrollments.ts lines 47–51 calls getEnrollmentsByIdentity(identity) which returns the full enrollmentStore.get(identity) array. An identity enrolled in thousands of queues generates a payload with thousands of records in a single HTTP response. No limit, offset, or cursor parameter exists.
2. GET /api/enrollments/queue/:queueId also returns unbounded lists
backend/src/routes/enrollments.ts lines 43–46 calls getEnrollmentsByQueue(queueId) with no pagination. A queue with 50,000 participants returns all 50,000 records in a single response. This would be a multi-MB JSON response that crashes browser tabs and timeouts mobile connections.
3. No pagination on GET /api/queues either — returns entire mockQueues array
backend/src/routes/queues.ts lines 24–30: the list endpoint returns mockQueues directly with only a status filter. With hundreds of queues, this is also unbounded. Issue #21 covers the frontend virtualization side but the backend API itself has no limit/cursor support at the route level.
Impact: Any moderately busy deployment will produce multi-MB API responses. Browsers will run out of memory parsing them. The backend process will spike CPU serializing massive JSON payloads. Rate limiting (issue #108) is insufficient if a single request can return megabytes.
Proposed Solution
- Add
limit (default 50, max 200) and cursor query params to all three list endpoints.
- Return
{ items: [...], nextCursor: string | null, total: number } envelope.
- Use
sdk/src/pagination.ts cursor helpers (encodeCursor/decodeCursor) as the canonical format.
- Update frontend
useQueues, useEnrollment hooks to consume the paginated envelope.
Acceptance Criteria
Contributor Note
If assigned, your PR must show the before/after response shapes, include a test demonstrating multi-page traversal, and confirm backward compatibility (no params → returns first 50 items).
Difficulty: Advanced
Problem
1.
GET /api/enrollments/:identityreturns all records for an identity with no limitbackend/src/routes/enrollments.tslines 47–51 callsgetEnrollmentsByIdentity(identity)which returns the fullenrollmentStore.get(identity)array. An identity enrolled in thousands of queues generates a payload with thousands of records in a single HTTP response. Nolimit,offset, or cursor parameter exists.2.
GET /api/enrollments/queue/:queueIdalso returns unbounded listsbackend/src/routes/enrollments.tslines 43–46 callsgetEnrollmentsByQueue(queueId)with no pagination. A queue with 50,000 participants returns all 50,000 records in a single response. This would be a multi-MB JSON response that crashes browser tabs and timeouts mobile connections.3. No pagination on
GET /api/queueseither — returns entiremockQueuesarraybackend/src/routes/queues.tslines 24–30: the list endpoint returnsmockQueuesdirectly with only a status filter. With hundreds of queues, this is also unbounded. Issue #21 covers the frontend virtualization side but the backend API itself has nolimit/cursorsupport at the route level.Impact: Any moderately busy deployment will produce multi-MB API responses. Browsers will run out of memory parsing them. The backend process will spike CPU serializing massive JSON payloads. Rate limiting (issue #108) is insufficient if a single request can return megabytes.
Proposed Solution
limit(default 50, max 200) andcursorquery params to all three list endpoints.{ items: [...], nextCursor: string | null, total: number }envelope.sdk/src/pagination.tscursor helpers (encodeCursor/decodeCursor) as the canonical format.useQueues,useEnrollmenthooks to consume the paginated envelope.Acceptance Criteria
GET /api/enrollments/:identityacceptslimitandcursorquery paramsGET /api/enrollments/queue/:queueIdacceptslimitandcursorquery paramsGET /api/queuesacceptslimitandcursorquery params{ items, nextCursor, total }envelopesdk/src/pagination.tshelpersdocs/api-reference/updated with pagination schemaContributor Note
If assigned, your PR must show the before/after response shapes, include a test demonstrating multi-page traversal, and confirm backward compatibility (no params → returns first 50 items).