deckhearth/pages
Randall Stillwell cc99e74c89 refactor(db): collapse @neondatabase/serverless onto @vercel/postgres + delete lib/database.js
Convoy: single-sql-client (P1 quality, launch sequence step 8)
Addresses: AGENTS.md Gotcha #1, .convoys/ship-readiness.md P1 #8

## Decisions

- D1: Caller inventory = 2 files (1 source + 1 test), not "~3 based on graph".
  Only pages/api/auth-utils.js imports `db`; test/api/auth-utils.test.js mocks
  it purely to satisfy the import graph (the 5 tests exercise
  generateToken/verifyToken, not isAdmin/getUserById).
- D2: Migrate both call sites (isAdmin, getUserById) to @vercel/postgres
  tagged-template SQL. Queries are SELECT-only, single-table,
  single-numeric-parameter — byte-equivalent translation; same result shape
  ({rows, rowCount}); no transaction or pool semantics differ.
- D3: KEEP @neondatabase/serverless as a dep. 11 scripts/* files still use
  `neon()` directly (setup-neon-db.js, migrations/, reset-db.js, 8 historical
  add-*/fix-*/seed-* jobs). They are out of scope per the no-go-zones rule
  and the convoy spec; purging the dep entirely would be its own convoy
  (queued as `purge-neondatabase-serverless-fully`, blocked on migration-tool).
- D4: sql.unsafe audit — NOT a real injection vector with current callers
  (userId comes from a verified JWT, is a numeric SERIAL id). Security
  finding: NO. Pure refactor + foot-gun removal that prevents the FUTURE
  caller that would have been the incident.
- D5: Test mock cleanup — drop the now-unneeded `vi.mock('../../lib/database.js')`
  call + unused `vi` import. Test count + assertions unchanged (5/5).

## Per-file changes

- pages/api/auth-utils.js: swap `import { db } from '../../lib/database.js'`
  for `import { sql } from '@vercel/postgres'`; rewrite isAdmin's
  `db.query(SELECT … WHERE id = $1, [userId])` and getUserById's same shape
  to `sql\`SELECT … WHERE id = ${userId}\``. Same try/catch, same
  result.rows[0] access, same error returns.
- test/api/auth-utils.test.js: drop vi.mock for lib/database.js + the unused
  `vi` import. 5/5 tests still pass.
- lib/database.js: DELETED (47 lines removed; manual-interpolation + sql.unsafe
  wrapper is gone).
- .convoys/single-sql-client.md: NEW (the convoy file documenting all
  decisions + caller inventory + verification + risks + follow-ups).

## Verification

- npm run lint → 128 problems (baseline preserved, no regression)
- npm run test:run → 21/21 pass (vitest)
- Grep "lib/database" --type js -l → 0 hits anywhere
- Grep "@neondatabase/serverless" --type js -l → still matches the 11
  scripts/* sites (expected; out of scope per D3)
- node --check pages/api/auth-utils.js → exit 0

## Scope note

This convoy collapses the lib/database.js abstraction onto the canonical
@vercel/postgres surface for pages/api/**. It does NOT eliminate
@neondatabase/serverless from the dependency tree — that would require
migrating the scripts/* helpers, which is out of scope here (no-go-zones
rule + convoy spec). Queued as a follow-up.

## Live smoke

Deferred. The two migrated functions (isAdmin, getUserById) are only
reachable via pages/api/admin/index.js which requires an admin Bearer
token and a populated users table in prod Neon. Byte-equivalent SQL +
identical result shape gives high confidence; rollback is a single-commit
revert if a post-merge admin action 500s.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 22:50:58 -05:00
..
admin feat(security): rate-limit search/upload/import + gate import routes (P0 #6 - closes last P0) 2026-05-24 22:59:59 -05:00
api refactor(db): collapse @neondatabase/serverless onto @vercel/postgres + delete lib/database.js 2026-05-26 22:50:58 -05:00
card fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
collection Major Scanner Improvements 2025-07-29 14:19:48 -05:00
community Major Scanner Improvements 2025-07-29 14:19:48 -05:00
deck fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
invite 🎉 COMPLETED: Full Collaborative Collections System 2025-07-25 08:34:28 -05:00
_app.js Major redesign: Enhanced card display with particle effects, improved filters, and search functionality 2025-07-23 21:26:54 -05:00
cards.js Major Scanner Improvements 2025-07-29 14:19:48 -05:00
collections.js 🔧 Fix System Collections & Database Schema Issues 2025-07-27 19:17:55 -05:00
dashboard.js Major Scanner Improvements 2025-07-29 14:19:48 -05:00
deck-builder.js fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
decks.js fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
index.js Major Scanner Improvements 2025-07-29 14:19:48 -05:00
login.js feat(brand): unify on Deck Hearth across in-repo strings + infra (P1 brand decision) 2026-05-25 02:28:29 -05:00
logout.js 🎨 Restructured Layout System 2025-07-25 11:28:04 -05:00
my-cards.js Major Scanner Improvements 2025-07-29 14:19:48 -05:00
profile.js fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
scanner.js fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
settings.js fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
signup.js 🎨 Enhanced Signup with Username & Profile Images 2025-07-28 11:18:58 -05:00