Skip to content

Feat/set row collapsing threshold#1127

Open
lissavxo wants to merge 2 commits intomasterfrom
feat/set-row-collapsing-threshold
Open

Feat/set row collapsing threshold#1127
lissavxo wants to merge 2 commits intomasterfrom
feat/set-row-collapsing-threshold

Conversation

@lissavxo
Copy link
Collaborator

@lissavxo lissavxo commented Mar 19, 2026

Related to #953

Description

Allow users to adjust the CSV collapse threshold directly from account settings.

  • Added a csvCollapseThreshold parameter to the UserProfile

  • Added an input field in account settings to configure csvCollapseThreshold

  • Updated CSV generation logic to use the csvCollapseThreshold value from UserProfile

Test plan

  1. Go to Payments and generate a CSV file
  2. Navigate to Account Settings and update the CSV Collapse Threshold value
  3. Return to Payments and generate a new CSV
  4. Verify that the collapsing behavior reflects the updated threshold value

Summary by CodeRabbit

Release Notes

  • New Features
    • Added CSV Collapse Threshold setting in your Account page. Configure this threshold to control how data is collapsed and grouped when downloading transaction files.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 19, 2026

📝 Walkthrough

Walkthrough

A new user-configurable CSV collapse threshold setting is implemented across the full stack. A React component allows users to input and validate the threshold through the Account page. A new API endpoint persists the validated value to the database via Prisma, and CSV download endpoints now incorporate this user preference.

Changes

Cohort / File(s) Summary
Frontend UI Components
components/Account/ChangeCsvCollapseThreshold.tsx, components/Account/account.module.css, pages/account/index.tsx
New component for editing CSV collapse threshold with validation; accompanying CSS styling for input, container, and button elements; integrated into Account page with user profile binding.
Backend API Endpoint
pages/api/user/csvCollapseThreshold/index.ts
New PUT endpoint that validates csvCollapseThreshold as a non-negative integer, rejects invalid values with 400 errors, calls service function on valid input, and returns 405 for non-PUT methods.
Database Schema & Migrations
prisma-local/schema.prisma, prisma-local/migrations/20260317024924_csv_collapse_threshold/migration.sql
Added csvCollapseThreshold integer field to UserProfile model with default value of 1; migration file adds the column to the table.
Service & Data Access
services/userService.ts
New updateCsvCollapseThreshold function persists the threshold value to the database via Prisma update.
API Integration Points
pages/api/paybutton/download/transactions/[paybuttonId].ts, pages/api/payments/download/index.ts
Updated CSV download endpoints to pass csvCollapseThreshold from user profile to downloadTxsFile function.
Test Utilities
tests/mockedObjects.ts
Updated mock user profile objects to include csvCollapseThreshold: 0 field for test consistency.

Sequence Diagram

sequenceDiagram
    participant User
    participant Component as ChangeCsvCollapseThreshold
    participant API as PUT /api/user/csvCollapseThreshold
    participant Service as userService
    participant Database as Prisma/DB

    User->>Component: Input threshold value
    Component->>Component: Validate input (non-negative integer)
    Component->>Component: Enable Update button if changed
    User->>Component: Submit form
    Component->>API: PUT request with new threshold
    API->>API: Validate csvCollapseThreshold (non-null, numeric, non-negative)
    alt Invalid value
        API-->>Component: 400 error response
        Component->>Component: Display error message
    else Valid value
        API->>Service: updateCsvCollapseThreshold(userId, threshold)
        Service->>Database: UPDATE UserProfile SET csvCollapseThreshold
        Database-->>Service: Confirmation
        Service-->>API: Promise resolved
        API-->>Component: 200 success response
        Component->>Component: Show success message (3s auto-clear)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hop! The CSV threshold now takes the stage,
Users collapse rows, turn o'er a new page,
From component to service, validation so neat,
Database and downloads—the feature's complete! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feat/set row collapsing threshold' clearly describes the main change: adding user-configurable CSV row collapse threshold settings.
Description check ✅ Passed The description follows the template structure with Related issue, Description, and Test plan sections. All required sections are completed with relevant details.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/set-row-collapsing-threshold
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can disable sequence diagrams in the walkthrough.

Disable the reviews.sequence_diagrams setting to disable sequence diagrams in the walkthrough.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
services/userService.ts (1)

159-166: Add a small service-layer guard for invalid threshold values.

This method currently trusts callers completely. Adding an integer/non-negative check here prevents bad writes from any non-API caller path.

Proposed hardening
 export async function updateCsvCollapseThreshold (id: string, csvCollapseThreshold: number): Promise<void> {
+  if (!Number.isInteger(csvCollapseThreshold) || csvCollapseThreshold < 0) {
+    throw new Error(RESPONSE_MESSAGES.BAD_REQUEST_400.message)
+  }
   await prisma.userProfile.update({
     where: { id },
     data: {
       csvCollapseThreshold
     }
   })
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/userService.ts` around lines 159 - 166, The
updateCsvCollapseThreshold service blindly writes any number; add a guard in
updateCsvCollapseThreshold to validate the input is an integer and non-negative
before calling prisma.userProfile.update: check
Number.isInteger(csvCollapseThreshold) && csvCollapseThreshold >= 0 (or
coerce/convert input and then validate), and if the check fails throw a
descriptive error (e.g., InvalidArgumentError / new Error('csvCollapseThreshold
must be a non-negative integer')) so bad values are rejected at the service
layer rather than persisted by prisma.userProfile.update.
tests/mockedObjects.ts (1)

531-533: Consider keeping base fixture defaults aligned with production defaults.

Using csvCollapseThreshold: 0 in shared base profiles can silently alter CSV behavior in unrelated tests. Prefer 1 in base fixtures and override to 0 only in edge-case-specific tests.

Fixture alignment tweak
-  csvCollapseThreshold: 0
+  csvCollapseThreshold: 1
...
-  csvCollapseThreshold: 0
+  csvCollapseThreshold: 1

Also applies to: 547-549

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/mockedObjects.ts` around lines 531 - 533, Update the shared base
fixture in tests/mockedObjects.ts so the csvCollapseThreshold default is aligned
with production by setting csvCollapseThreshold to 1 (instead of 0) in the base
profile object (the block that contains proUntil and csvCollapseThreshold), and
only set csvCollapseThreshold: 0 in individual edge-case tests where collapsing
must be disabled; adjust any other base-profile occurrences (e.g., the similar
block around lines 547-549) to the same default to avoid silently changing CSV
behavior across tests.
components/Account/ChangeCsvCollapseThreshold.tsx (1)

39-41: Clear the success timer on unmount to avoid stale state updates.

The timeout callback can run after unmount. Add timer cleanup for reliability.

Proposed fix
-import React, { ReactElement, useState } from 'react'
+import React, { ReactElement, useEffect, useRef, useState } from 'react'
@@
 export default function ChangeCsvCollapseThreshold ({ csvCollapseThreshold }: IProps): ReactElement {
+  const successTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
@@
+  useEffect(() => {
+    return () => {
+      if (successTimerRef.current !== null) {
+        clearTimeout(successTimerRef.current)
+      }
+    }
+  }, [])
@@
-        setTimeout(() => {
+        if (successTimerRef.current !== null) clearTimeout(successTimerRef.current)
+        successTimerRef.current = setTimeout(() => {
           setSuccess('')
         }, 3000)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Account/ChangeCsvCollapseThreshold.tsx` around lines 39 - 41, The
success timeout in the ChangeCsvCollapseThreshold component currently calls
setTimeout to clear setSuccess('') but doesn't clear it on unmount; modify the
effect (or wherever setTimeout is called) to capture the timer id (const timer =
window.setTimeout(...)) and return a cleanup that calls clearTimeout(timer) so
the callback can't run after the component unmounts; ensure the timer id type
matches the environment (use number from window.setTimeout or NodeJS.Timeout in
server contexts) and set timer to null after clearing if using state/refs.
pages/api/user/csvCollapseThreshold/index.ts (1)

26-27: Add a defensive guard for missing session.userId before Prisma update.

If session is unavailable, this currently falls through to a DB error path instead of a clear auth response.

Proposed fix
   if (req.method === 'PUT') {
     const session = req.session
+    if (!session?.userId) {
+      res.status(401).json({ message: 'Unauthorized' })
+      return
+    }
     const { csvCollapseThreshold } = req.body
@@
-    await userService.updateCsvCollapseThreshold(session.userId, threshold)
+    await userService.updateCsvCollapseThreshold(session.userId, threshold)
     res.status(200).json({ success: true })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/api/user/csvCollapseThreshold/index.ts` around lines 26 - 27, Add a
defensive guard that checks for a valid session and session.userId before
calling userService.updateCsvCollapseThreshold; if session or session.userId is
missing, immediately respond with an auth error (e.g., res.status(401).json({
success: false, error: 'Unauthorized' })) and return so you never call
userService.updateCsvCollapseThreshold with an undefined id.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/Account/ChangeCsvCollapseThreshold.tsx`:
- Around line 18-19: The input parsing currently uses parseInt (e.g., in
ChangeCsvCollapseThreshold’s handling of inputValue) which silently truncates
decimals; replace parseInt usage with Number() to parse the value and then
validate using Number.isInteger(newThreshold) and newThreshold >= 0, rejecting
NaN or non-integer (decimal) values explicitly (apply the same change for the
other occurrence referenced at the second spot around the lines corresponding to
the existing parseInt usage), and update any validation/error paths to reflect
"must be a non-negative integer" instead of relying on parseInt truncation.
- Around line 74-80: Change the input in the ChangeCsvCollapseThreshold
component to be an accessible numeric control: replace type="text" with
type="number", add step="1" and keep min="0" so HTML5 numeric validation works,
and provide an associated label element referencing id="csvCollapseThreshold"
(or add aria-label if a visible label isn't desired) to ensure accessibility;
update any related handlers like handleInputChange to handle numeric values
(parseInt/Number) from the inputValue before using it.

In `@pages/api/user/csvCollapseThreshold/index.ts`:
- Around line 15-23: The current validation for csvCollapseThreshold (variable
csvCollapseThreshold and computed threshold) is too permissive; change it to
first reject empty or whitespace-only string inputs (if typeof
csvCollapseThreshold === 'string' check trim().length === 0) then parse to a
number and validate using Number.isFinite(threshold) and
Number.isInteger(threshold) and threshold >= 0; return 400 with an appropriate
message if any of these checks fail so decimals, Infinity/NaN, and blank inputs
are rejected before persisting the Int.

---

Nitpick comments:
In `@components/Account/ChangeCsvCollapseThreshold.tsx`:
- Around line 39-41: The success timeout in the ChangeCsvCollapseThreshold
component currently calls setTimeout to clear setSuccess('') but doesn't clear
it on unmount; modify the effect (or wherever setTimeout is called) to capture
the timer id (const timer = window.setTimeout(...)) and return a cleanup that
calls clearTimeout(timer) so the callback can't run after the component
unmounts; ensure the timer id type matches the environment (use number from
window.setTimeout or NodeJS.Timeout in server contexts) and set timer to null
after clearing if using state/refs.

In `@pages/api/user/csvCollapseThreshold/index.ts`:
- Around line 26-27: Add a defensive guard that checks for a valid session and
session.userId before calling userService.updateCsvCollapseThreshold; if session
or session.userId is missing, immediately respond with an auth error (e.g.,
res.status(401).json({ success: false, error: 'Unauthorized' })) and return so
you never call userService.updateCsvCollapseThreshold with an undefined id.

In `@services/userService.ts`:
- Around line 159-166: The updateCsvCollapseThreshold service blindly writes any
number; add a guard in updateCsvCollapseThreshold to validate the input is an
integer and non-negative before calling prisma.userProfile.update: check
Number.isInteger(csvCollapseThreshold) && csvCollapseThreshold >= 0 (or
coerce/convert input and then validate), and if the check fails throw a
descriptive error (e.g., InvalidArgumentError / new Error('csvCollapseThreshold
must be a non-negative integer')) so bad values are rejected at the service
layer rather than persisted by prisma.userProfile.update.

In `@tests/mockedObjects.ts`:
- Around line 531-533: Update the shared base fixture in tests/mockedObjects.ts
so the csvCollapseThreshold default is aligned with production by setting
csvCollapseThreshold to 1 (instead of 0) in the base profile object (the block
that contains proUntil and csvCollapseThreshold), and only set
csvCollapseThreshold: 0 in individual edge-case tests where collapsing must be
disabled; adjust any other base-profile occurrences (e.g., the similar block
around lines 547-549) to the same default to avoid silently changing CSV
behavior across tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 95c08745-b5d8-43aa-988d-626badf50bae

📥 Commits

Reviewing files that changed from the base of the PR and between f1cc9f2 and 56ef258.

📒 Files selected for processing (10)
  • components/Account/ChangeCsvCollapseThreshold.tsx
  • components/Account/account.module.css
  • pages/account/index.tsx
  • pages/api/paybutton/download/transactions/[paybuttonId].ts
  • pages/api/payments/download/index.ts
  • pages/api/user/csvCollapseThreshold/index.ts
  • prisma-local/migrations/20260317024924_csv_collapse_threshold/migration.sql
  • prisma-local/schema.prisma
  • services/userService.ts
  • tests/mockedObjects.ts

Comment on lines +18 to +19
const newThreshold = parseInt(inputValue, 10)
if (isNaN(newThreshold) || newThreshold < 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

git ls-files | grep -i "ChangeCsvCollapseThreshold"

Repository: PayButton/paybutton-server

Length of output: 119


🏁 Script executed:

fd -i "changecsvcollapsethreshold" --type f

Repository: PayButton/paybutton-server

Length of output: 119


🏁 Script executed:

cat -n components/Account/ChangeCsvCollapseThreshold.tsx

Repository: PayButton/paybutton-server

Length of output: 3610


🏁 Script executed:

node <<'EOF'
// Verify parseInt behavior
console.log("parseInt('1.5', 10):", parseInt('1.5', 10));
console.log("parseInt('12abc', 10):", parseInt('12abc', 10));
console.log("parseInt('abc', 10):", parseInt('abc', 10));
console.log("isNaN(parseInt('abc', 10)):", isNaN(parseInt('abc', 10)));
console.log("isNaN(parseInt('1.5', 10)):", isNaN(parseInt('1.5', 10)));
console.log("Number.isInteger(Number('1.5')):", Number.isInteger(Number('1.5')));
console.log("Number.isInteger(Number('12')):", Number.isInteger(Number('12')));
EOF

Repository: PayButton/paybutton-server

Length of output: 286


parseInt silently truncates decimal input; use strict integer validation instead.

Values like 1.5 are accepted by isNaN() and truncated to 1 without warning. Use Number() with Number.isInteger() to enforce strict integer validation and reject decimal input explicitly.

Proposed fix
-    const newThreshold = parseInt(inputValue, 10)
-    if (isNaN(newThreshold) || newThreshold < 0) {
+    const normalized = inputValue.trim()
+    const newThreshold = Number(normalized)
+    if (normalized === '' || !Number.isInteger(newThreshold) || newThreshold < 0) {
       setError('Please enter a valid non-negative number')
       return
     }
@@
-    const numValue = parseInt(value, 10)
-    if (!isNaN(numValue) && numValue >= 0 && numValue !== threshold) {
+    const normalized = value.trim()
+    const numValue = Number(normalized)
+    if (normalized !== '' && Number.isInteger(numValue) && numValue >= 0 && numValue !== threshold) {
       setDisabled(false)
       setError('')

Also applies to: lines 56-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Account/ChangeCsvCollapseThreshold.tsx` around lines 18 - 19, The
input parsing currently uses parseInt (e.g., in ChangeCsvCollapseThreshold’s
handling of inputValue) which silently truncates decimals; replace parseInt
usage with Number() to parse the value and then validate using
Number.isInteger(newThreshold) and newThreshold >= 0, rejecting NaN or
non-integer (decimal) values explicitly (apply the same change for the other
occurrence referenced at the second spot around the lines corresponding to the
existing parseInt usage), and update any validation/error paths to reflect "must
be a non-negative integer" instead of relying on parseInt truncation.

Comment on lines +74 to +80
<input
id="csvCollapseThreshold"
type="text"
min="0"
required
value={inputValue}
onChange={handleInputChange}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd "ChangeCsvCollapseThreshold.tsx" --type f

Repository: PayButton/paybutton-server

Length of output: 119


🏁 Script executed:

wc -l components/Account/ChangeCsvCollapseThreshold.tsx

Repository: PayButton/paybutton-server

Length of output: 122


🏁 Script executed:

cat -n components/Account/ChangeCsvCollapseThreshold.tsx

Repository: PayButton/paybutton-server

Length of output: 3610


Add an accessible label and use a numeric input type.

The input currently lacks an accessible label and type="text" makes the min="0" attribute ineffective. With manual validation expecting an integer, type="number" is more semantically appropriate and enables proper HTML5 validation.

Proposed fix
         <div className={style.threshold_row}>
+          <label htmlFor="csvCollapseThreshold">CSV collapse threshold</label>
           <input
             id="csvCollapseThreshold"
-            type="text"
+            type="number"
             min="0"
+            step="1"
+            inputMode="numeric"
             required
             value={inputValue}
             onChange={handleInputChange}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Account/ChangeCsvCollapseThreshold.tsx` around lines 74 - 80,
Change the input in the ChangeCsvCollapseThreshold component to be an accessible
numeric control: replace type="text" with type="number", add step="1" and keep
min="0" so HTML5 numeric validation works, and provide an associated label
element referencing id="csvCollapseThreshold" (or add aria-label if a visible
label isn't desired) to ensure accessibility; update any related handlers like
handleInputChange to handle numeric values (parseInt/Number) from the inputValue
before using it.

Comment on lines +15 to +23
if (csvCollapseThreshold === undefined || csvCollapseThreshold === null) {
res.status(400).json({ message: 'csvCollapseThreshold is required' })
return
}

const threshold = Number(csvCollapseThreshold)
if (isNaN(threshold) || threshold < 0) {
res.status(400).json({ message: 'csvCollapseThreshold must be a non-negative number' })
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify JS coercion edge-cases that affect current validation logic.
node - <<'NODE'
const inputs = ['', '   ', '1.5', 'Infinity', null, undefined, '12abc'];
for (const v of inputs) {
  console.log(JSON.stringify(v), '=> Number:', Number(v), 'isFinite:', Number.isFinite(Number(v)));
}
NODE

Repository: PayButton/paybutton-server

Length of output: 330


🏁 Script executed:

find . -type f -name "*.ts" -path "*/pages/api/user/csvCollapseThreshold*" | head -20

Repository: PayButton/paybutton-server

Length of output: 116


🏁 Script executed:

cat -n pages/api/user/csvCollapseThreshold/index.ts

Repository: PayButton/paybutton-server

Length of output: 1301


🏁 Script executed:

# Check the userService to understand what updateCsvCollapseThreshold expects
find . -type f -name "userService.ts" | head -5

Repository: PayButton/paybutton-server

Length of output: 95


🏁 Script executed:

cat -n services/userService.ts | head -100

Repository: PayButton/paybutton-server

Length of output: 4017


🏁 Script executed:

# Search for the updateCsvCollapseThreshold function specifically
rg -A 15 "updateCsvCollapseThreshold" services/userService.ts

Repository: PayButton/paybutton-server

Length of output: 520


🏁 Script executed:

# Check if there's a Prisma schema that defines csvCollapseThreshold type
find . -type f \( -name "schema.prisma" -o -name "*.prisma" \)

Repository: PayButton/paybutton-server

Length of output: 98


🏁 Script executed:

rg -A 3 -B 3 "csvCollapseThreshold" ./prisma-local/schema.prisma

Repository: PayButton/paybutton-server

Length of output: 275


🏁 Script executed:

# Also check the UserProfile model in the schema
rg -A 50 "model UserProfile" ./prisma-local/schema.prisma | head -80

Repository: PayButton/paybutton-server

Length of output: 1930


Harden threshold validation to reject blank, non-finite, and non-integer values.

Current coercion accepts invalid inputs like empty strings, whitespace, decimals, and Infinity. Since csvCollapseThreshold is defined as an Int in the database schema, these invalid inputs could cause unintended behavior or persist incorrect values.

Proposed fix
-    if (csvCollapseThreshold === undefined || csvCollapseThreshold === null) {
+    if (
+      csvCollapseThreshold === undefined ||
+      csvCollapseThreshold === null ||
+      (typeof csvCollapseThreshold === 'string' && csvCollapseThreshold.trim() === '')
+    ) {
       res.status(400).json({ message: 'csvCollapseThreshold is required' })
       return
     }

-    const threshold = Number(csvCollapseThreshold)
-    if (isNaN(threshold) || threshold < 0) {
-      res.status(400).json({ message: 'csvCollapseThreshold must be a non-negative number' })
+    const threshold = Number(csvCollapseThreshold)
+    if (!Number.isFinite(threshold) || !Number.isInteger(threshold) || threshold < 0) {
+      res.status(400).json({ message: 'csvCollapseThreshold must be a non-negative integer' })
       return
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (csvCollapseThreshold === undefined || csvCollapseThreshold === null) {
res.status(400).json({ message: 'csvCollapseThreshold is required' })
return
}
const threshold = Number(csvCollapseThreshold)
if (isNaN(threshold) || threshold < 0) {
res.status(400).json({ message: 'csvCollapseThreshold must be a non-negative number' })
return
if (
csvCollapseThreshold === undefined ||
csvCollapseThreshold === null ||
(typeof csvCollapseThreshold === 'string' && csvCollapseThreshold.trim() === '')
) {
res.status(400).json({ message: 'csvCollapseThreshold is required' })
return
}
const threshold = Number(csvCollapseThreshold)
if (!Number.isFinite(threshold) || !Number.isInteger(threshold) || threshold < 0) {
res.status(400).json({ message: 'csvCollapseThreshold must be a non-negative integer' })
return
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/api/user/csvCollapseThreshold/index.ts` around lines 15 - 23, The
current validation for csvCollapseThreshold (variable csvCollapseThreshold and
computed threshold) is too permissive; change it to first reject empty or
whitespace-only string inputs (if typeof csvCollapseThreshold === 'string' check
trim().length === 0) then parse to a number and validate using
Number.isFinite(threshold) and Number.isInteger(threshold) and threshold >= 0;
return 400 with an appropriate message if any of these checks fail so decimals,
Infinity/NaN, and blank inputs are rejected before persisting the Int.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant