Closes the pick-a-name convoy. Applies D1-D5 + Risk 4 PRESERVE per
operator gate-1 ratification.
Infrastructure renames:
- lib/rate-limit.js: 5 Redis key prefixes tcgvault:* → deckhearth:* (D5).
One-time per-15-min / per-1-hour counter reset accepted; no user impact
because counter windows are short anyway. Existing rate-limit state in
Upstash will accumulate at the new prefix on first request.
- package.json: name field tcg-vault → deck-hearth (D2)
- package-lock.json: regenerated for the name change; STOP-on-churn
protocol confirmed only the two name lines changed (no dep churn)
- All three test users (admin/alice/bob) renamed to @deckhearth.com (D4)
- One-off migration script scripts/migrations/2026-05-24-rename-admin-
email.js (NEW): ESM, idempotent, UNIQUE-collision-safe. Per the
no-go-zones rule for new migrations. Operator MUST run post-deploy.
- README.md + TESTING_GUIDE.md operator-caveat blockquotes flagged
- pages/login.js demo-credential pre-fill updated
PRESERVED per Risk 4:
- test/lib/permission-middleware.test.js literal admin@tcgvault.com
with 7-line architect-authored "why" comment block. This is the
documented pre-fix-auth-bypass bug shape; the regression-lock
literal stays as historical truth.
Verification:
- npm run lint: 128 problems (baseline preserved)
- npm run test:run: 21/21 pass (preserved literal keeps green)
- Grep across full repo: 0 hits for TCG Vault / tcgvault / tcg-vault
except the explicit preserve in the test file + .convoys/ historical
- lib/rate-limit.js: 5 deckhearth: prefixes, 0 tcgvault: prefixes
- node --check on the new migration script: exit 0
- git diff package-lock.json: only the 2 "name": lines changed (no churn)
Operator post-merge action:
- Run `node scripts/migrations/2026-05-24-rename-admin-email.js` against
the production Neon DB. Order matters: migration FIRST, then any
subsequent `npm run setup-db` invocation. Migration script will refuse
to run if collision detected (means setup-db already ran post-rename).
Architect brief: .convoys/pick-a-name/brief-2-infrastructure-and-email-migration.md
Architect commit: 50ce9ab
Operator gate-1: D1-D5 + Risk 4 PRESERVE ratified.
Co-authored-by: Cursor <cursoragent@cursor.com>
Closes P0 #3 from .convoys/ship-readiness.md.
scripts/setup-neon-db.js:
- Read ADMIN_INITIAL_PASSWORD env var at the top of setupNeonDatabase()
before any DB connection. Fail loudly (process.exit(1)) with an
actionable message if unset or empty.
- Replace bcrypt.hash('admin123', 12) with bcrypt.hash(adminPassword, 12).
- Delete the two console.log lines that echoed admin user + password to
stdout (R3 - stdout leak into CI logs).
- Keep ON CONFLICT (email) DO NOTHING unchanged. Re-running setup-db
on an env with the admin row already present is a no-op for the
password (R4 - silent rotation prevention). Rotation of existing
weak-hash admin rows is out of scope (Decision A - queued for the
rotate-default-admin follow-up convoy).
README.md:
- Add ADMIN_INITIAL_PASSWORD to the install-step env-example block
with a CI-secret note (and add KV_REST_API_URL/KV_REST_API_TOKEN
for completeness; they're optional for local dev).
- Replace the "Default Admin Account" section with "First-time
admin setup", documenting the env var, openssl rand suggestion,
and the operator rotation note for envs that predate this change.
- Zero occurrences of 'admin123' remain in README.md (the operator
rotation note refers to "the prior weak default" instead of naming
the literal string, so grep verification A2 holds).
Decisions A1 (going-forward only), B (operational change allowed),
C1 (no vitest coverage - manual smoke in PR description) per
.convoys/drop-public-setup.md section Decisions.
Smoke output: see PR description.
Co-authored-by: Cursor <cursoragent@cursor.com>
Removes four unauthenticated dev endpoints that were shipped to production:
- pages/api/simple.js (info leak)
- pages/api/test-auth.js (auth diagnostic / token-mint side door)
- pages/api/test-db.js (DB connection diagnostic)
- pages/api/setup-database.js (public POST that ran DDL + seeded admin)
setup-database is the highest-impact removal: it was a public endpoint
that triggered schema bootstrap and seeded the default admin credentials
(admin@tcgvault.com / admin123). AGENTS.md gotcha #5.
Also adds a new `forbidden-endpoints` job to .github/workflows/ci.yml
that fails the build if any of the four deleted paths re-appear OR if
any new pages/api/test-*.js file is added. Cheap insurance against a
future agent re-introducing a dev endpoint from an outdated tutorial.
README: drops the single `GET /api/test-db` line under "Health Check".
Rest of the API list is intentionally left for the doc-writer pass.
Verified locally:
- npm run build exits 0 (no source callers — confirmed via grep across
pages/, components/, lib/)
- CI guard local simulation: clean → OK; with test-fake.js → FAIL; OK
after cleanup
Resolves AGENTS.md gotcha #5. Brief 1/2/4/5 still pending in convoy.
Convoy: fix-auth-bypass / Brief 3
Co-authored-by: Cursor <cursoragent@cursor.com>
- Redesigned card display with 2.5:3.5 aspect ratio and image-only view
- Added infinite scroll to replace pagination
- Implemented authentic card back placeholders for MTG, Pokemon, and Lorcana
- Added rarity-based particle effects with tiered intensity (mythic/enchanted/rare/uncommon)
- Enhanced hover details panel with structured card information
- Fixed search functionality with debouncing and Enter key support
- Improved filter system with working TCG, rarity, set, and price filters
- Added favorite system for cards in both hover and detail views
- Updated card detail page with comprehensive metadata and actions
- Fixed API filtering with proper Vercel Postgres implementation
- Added particle animations and rarity glow effects
- Improved overall UX with better visual hierarchy and interactions