paperclip/server
aperim-agent d58a862549
fix(issues): coerce anchor.createdAt to Date before postgres binding (PRO-3144) (#5220)
## Thinking Path

> - Paperclip orchestrates AI agents in a control plane backed by
Postgres + drizzle-orm
> - `listComments` is the cursor-paginated comment listing on the issues
service; the cursor branch uses Drizzle's `gt`/`lt`/`eq` against
`issueComments.createdAt`
> - On postgres.js v3.4.8, passing a `Date` instance through the
comparison helpers triggers `TypeError [ERR_INVALID_ARG_TYPE]: The
"string" argument must be of type string or an instance of Buffer or
ArrayBuffer. Received an instance of Date`
> - The driver's binding path expects a Date constructed via the
standard runtime, but drizzle's `select` returns instances that don't
satisfy that check in this version
> - This PR coerces `anchor.createdAt` through `toISOString()` → `new
Date(...)` so the comparison helpers always receive a binding-safe Date,
then folds in a follow-up that hoists the Date into a single allocation
reused across all four `gt`/`lt`/`eq` call sites
> - The benefit is `listComments` cursor pagination stops 500-ing on Pg
v3.4.8 with one Date allocation per call instead of four, exercised by
both ascending and descending cursor tests

## What Changed

- `server/src/services/issues.ts` — coerce `anchor.createdAt` to a
binding-safe `Date` once and reuse the same instance across all four
cursor comparisons (`gt` / `lt` / `eq`)
- `server/src/__tests__/issues-service.test.ts` — add an
ascending-cursor sibling test so both `gt` and `lt` cursor paths are
exercised; the existing descending test continues to pass

## Verification

```bash
# Both cursor branches
pnpm --filter @paperclipai/server exec vitest run \
  src/__tests__/issues-service.test.ts -t "anchor comment"
# → 2 passed, 41 skipped

# Production smoke
curl -s "$PAPERCLIP_API_URL/api/issues/<issueId>/comments?after=<commentId>&order=asc" \
  -H "Authorization: Bearer $PAPERCLIP_API_KEY"
# Expect: JSON array, no 500 TypeError
```

## Risks

- Low risk. Pure cursor-pagination internals in `listComments`; no
schema, migration, or external contract changes
- Drizzle's `gt`/`lt`/`eq` continue to receive a `Date` for the
timestamp column, producing the same bound parameter as before
- Behavioural surface is exercised by ascending + descending cursor
tests against a real Postgres test database

## Model Used

- Claude Opus 4.7 (`claude-opus-4-7`), no extended-thinking mode, used
for the hoist+test follow-up commit

## Fixes

Closes #2612, Closes #3661, Closes #3830

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots — n/a, backend-only
- [x] I have updated relevant documentation to reflect my changes — n/a,
no docs touched
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Elena Voronova <elena@paperclip.ing>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Devin Foley <devin@devinfoley.com>
2026-06-02 15:26:59 -07:00
..
scripts fix(server): use stable tsx/cli entry point in dev-watch 2026-03-28 06:42:03 +07:00
src fix(issues): coerce anchor.createdAt to Date before postgres binding (PRO-3144) (#5220) 2026-06-02 15:26:59 -07:00
CHANGELOG.md chore: release v0.3.1 2026-03-12 13:09:22 -05:00
package.json Add built-in grok_local adapter (#6087) 2026-05-16 09:51:09 -07:00
tsconfig.json Fix root TypeScript solution config 2026-03-09 14:09:30 -05:00
vitest.config.ts Stabilize serialized server route tests (#4448) 2026-04-24 19:27:00 -05:00