fix(api): query pagination accepts non-integer limit/page → fractional OFFSET/LIMIT

Abierto
#785 1 comentario 0 reacciones 0 asignados Ver en GitHub

@Devesh36 ya está trabajando en esto.

Desde el 21/9/2026.

  • #858 de @Devesh36 — fusionado

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
76/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
typescript

Línea de trabajo

Comienza con DynamicQueryRequestSchema y validatePaginationFields en apps/api/src/schemas/query-schemas.ts y apps/api/src/routes/query.ts; después inspecciona QuerySchema en packages/ai/src/query/index.ts y los builders de limit/offset. Reproduce las entradas fraccionarias descritas en el issue y añade cobertura de regresión. Se considera terminado cuando los valores no finitos o no enteros de limit/page reciben la respuesta de validación 400 esperada, mientras que la paginación válida sigue construyendo cláusulas compatibles con enteros.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Describe the bug
POST /v1/query DynamicQueryRequest accepts non-integer limit/page without validation and produces fractional LIMIT/OFFSET that fail ClickHouse Int32 binding.

Affected code:

  • apps/api/src/schemas/query-schemas.ts:49-50 DynamicQueryRequestSchema: t.Optional(t.Number()) — no minimum/integer constraint.
  • apps/api/src/routes/query.ts:294-308 validatePaginationFields only checks <1 and >10000/<1 for page, not Number.isInteger/isFinite.
  • apps/api/src/routes/query.ts:1040-1041 limit: request.limit || 100, offset: request.page ? (request.page-1)*(request.limit||100) :0 → with limit=1.5, page=1.5 yields offset=0.75 (fractional).
  • packages/ai/src/query/simple-builder.ts:1148-1154 buildLimitClause/buildOffsetClause emit LIMIT 1.5 OFFSET 0.75 vs. builders LIMIT {limit:Int32} OFFSET {offset:Int32} (packages/ai/src/query/builders/pages.ts:182, sessions.ts:318, etc.).
  • Internal packages/ai/src/query/index.ts:61-62 QuerySchema: z.number().min(1).max(1000) also allows floats (missing .int()).

To Reproduce

  1. Authenticated request:
POST /v1/query?website_id=<id>&timezone=UTC
Content-Type: application/json
{
  "parameters": ["top_pages"],
  "startDate": "2026-01-01",
  "endDate": "2026-01-02",
  "limit": 1.5,
  "page": 1.5
}
  1. Also try {"limit": 0.5}, {"page": 1.5}, {"limit": 1.5, "page": 2.3}.

Expected behavior
400 VALIDATION_ERROR with details like:

{ "field":"limit", "message":"Limit must be an integer" }
{ "field":"page", "message":"Page must be an integer" }

limit/page should require finite integer, limit 1..10000, page 1...

Actual behavior
No validation error; request reaches ClickHouse with fractional values. Reproduced locally with copy of validatePaginationFields (D:\tmp\repro_pagination.js):

float limit {limit:1.5} => errors=[] limit=1.5 offset=0  BUG non-integer passed
float page {page:1.5} => errors=[] limit=100 offset=50  BUG
both float => offset 0.75 BUG not integer
Infinity/NaN similarly slip through (JSON NaN not encodable but Elysia coercion from query string can produce floats).

buildLimitClause(NaN) → '' (unbounded), buildLimitClause(0) → ''.

Screenshots
N/A

Environment

  • OS: Windows, Bun 1.4.2 (package.json:30 [email protected] pinned)
  • Commit: 92c15273d (origin/staging)

Additional context

  • limit default fallback || 100 masks 0/NaN in apps/api/src/routes/query.ts:1040, simple-builder.ts:1149 fallback similarly.
  • limit max mismatch: API allows 10000 (validatePaginationFields:301), internal QuerySchema allows 1000 — not part of this bug but worth aligning.
  • No existing open issue covers this (checked gh issue list).
  • Minimal fix proposal: tighten DynamicQueryRequestSchema (TypeBox minimum), add Number.isInteger/isFinite in validatePaginationFields, add .int() to QuerySchema (packages/ai/src/query/index.ts:61-62), add regression test.

AI disclosure
Issue drafted with assistance from Muse Spark (opencode/muse-spark-1.2-contributor-free) and human-verified via local reproduction (node D:\tmp\repro_pagination.js).

Lenguaje dominante
TypeScript
Estrellas
1.2k
Forks
227
Métricas de merge de PR
Sin PR fusionados en 30 d

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.