Replace @vercel/postgres, Blob, and Upstash with lib/sql.js, MinIO object
storage, and CT 102 Redis rate limits. Add Dockerfile for Dokploy deploy,
homelab runbooks, Neon data-copy helper, and point CI smoke/visual at the
homelab URL instead of Vercel previews.
Co-authored-by: Cursor <cursoragent@cursor.com>
Extract ScannedCardItem with per-card metadata controls and ownership
lookup via GET /api/cards/[id]/ownership. Propagate condition, foil,
and quantity through owned/collection/deck POST paths.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add per-row in-flight locks so double-tap cannot duplicate owned POSTs.
Pass bulk action/target directly instead of setTimeout state races.
Log collection card adds via logCollectionActivity and fix rows.length
checks in the collection cards POST handler.
Co-authored-by: Cursor <cursoragent@cursor.com>
Closes P0 #5 from PARTIAL to RESOLVED. Sweeps the remaining 24 pages/api/** handlers that carried the identical scaffolded wildcard-CORS + OPTIONS preflight pattern (Brief 4 cleaned login + register; this finishes the job). Adds a blocking forbidden-cors-headers CI job modeled on forbidden-endpoints to lock the cleanup against future regression. 25 files changed (+29/-261). Local: lint 128 baseline, vitest 21/21, zero CORS matches, YAML valid. CI: Playwright smoke 3/3 in 3.3s against post-removal preview (login/verify flow still works), new forbidden-cors-headers job passes in 4s, all gates green. PR #19 architect-commit ec22b70, implementer-commit a843736.
Follow-up to fix-auth-bypass Brief 2 (commit 258e479). Brief 2 made
getUserFromRequest return null for unauthenticated requests. POST, PUT,
and DELETE branches of pages/api/collections/[identifier]/cards.js
were dereferencing user.userId without a guard → NPE → HTTP 500.
Security side was already fixed by Brief 2 (no more
anonymous-write-as-admin on collections owned by userId: 1). This patch
adds the cosmetic 500 → 401 cleanup the Brief 2 reviewer flagged.
Three identical 'if (!user) return 401' guards added, one per write
branch. GET branch was already guarded via the ternary pattern.
Sibling endpoints under pages/api/collections/** were re-audited by the
implementer and confirmed correctly guarded (thumbnails, permissions,
activity all have early null checks; [identifier].js uses optional
chaining throughout). No further hotfixes needed for that route group.
Convoy: fix-auth-bypass / Brief 6 (post-architect hotfix)
Co-authored-by: Cursor <cursoragent@cursor.com>
🐛 Multiple API Fixes:
- Fixed SQL DISTINCT/ORDER BY conflict in thumbnails API
- Fixed SQL result structure (.rows) in cards API
- Fixed SQL result structure (.rows) in permissions API
- Restored accidentally removed code in cards API
✅ Technical Corrections:
- Removed DISTINCT from thumbnails query to fix ORDER BY conflict
- Updated all APIs to use collectionResult.rows instead of direct access
- Updated all result mappings to use .rows property
- Fixed validation checks to use .rows.length
🎯 Expected Results:
- Thumbnails API should now work without SQL errors
- Cards API should load collection cards properly
- Permissions API should work for collection management
- New card layout thumbnails should display correctly
All collection APIs should now work properly! 🚀
🔗 Automatic ID to Slug Redirects:
- Collection detail page now automatically redirects from ID URLs to slug URLs
- Maintains backwards compatibility for all existing links
- SEO-friendly permanent redirects using router.replace()
✏️ Collection Edit/Delete Functionality:
- Added edit modal directly in collection detail page
- Added delete confirmation modal with proper warnings
- Edit functionality updates name, description, image, and visibility
- Automatic slug regeneration when collection name changes
- Proper permission checks (only owners can edit/delete)
🛠️ API Route Restructuring:
- Renamed all [id] routes to [identifier] to resolve Next.js conflicts
- Updated all APIs to handle both slugs and numeric IDs
- Fixed 'different slug names for same dynamic path' error
- Consistent identifier handling across all endpoints
📁 Updated API Endpoints:
- /api/collections/[identifier] - Main collection CRUD
- /api/collections/[identifier]/cards - Collection cards management
- /api/collections/[identifier]/thumbnails - Thumbnail generation
- /api/collections/[identifier]/permissions - Permission management
- /api/collections/[identifier]/activity - Activity tracking
🎨 UI/UX Improvements:
- Edit and Delete buttons only show for collection owners
- Clean modal interfaces with proper form validation
- Loading states and error handling
- Confirmation dialogs for destructive actions
- Consistent styling with fire theme
🔧 Technical Enhancements:
- Smart identifier detection (slug vs numeric ID)
- Proper error handling and user feedback
- Database transaction safety for updates
- Automatic collection timestamp updates
- Permission-based access control
Now users can seamlessly edit collections and get beautiful SEO-friendly URLs! 🚀✨