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>
Five decisions routed back for operator gate-1 ratification — none
architect-self-ratifiable, since all five are naming choices rather than
architectural ones. Gate-0 brand winner (Deck Hearth) is captured;
architect's job was to scope and minimize the cost of the rename, not to
re-litigate the brand. No blocking findings surfaced: no npm-package
collision (we don't publish), domain ownership is already a known queued
follow-up, Redis counter reset is the explicitly-accepted trade.
Architecture: 2 file-disjoint briefs that can run in parallel via
/multitask once gate-1 lands. ~75-110 lines net diff across 16 source
files + 1 new migration script (excluding the opaque package-lock.json
regen). Brief 1 is the mechanical display/comment sweep (7 files, ~7
lines) — branding notes, rule descriptions, three User-Agent product
tokens. Brief 2 owns the infrastructure + email-rename blast (10 files
+ 1 new migration script, ~30 edits) — Redis prefix rename in
lib/rate-limit.js (5 lines), package.json + lockfile regen, admin/alice/
bob email rename across seed/reset/test-user scripts + login.js
fixtures + README + TESTING_GUIDE + the test-file regression-lock, plus
the new scripts/migrations/2026-05-24-rename-admin-email.js (idempotent
REPLACE() UPDATE with UNIQUE-constraint fail-loud semantics).
D1-D5 recommendations all biased toward existing-string consistency:
D1 "Deck Hearth" (matches all 7 already-correct user-facing surfaces;
choosing "Deckhearth" would re-sweep them — net-negative cost), D2
`deck-hearth` (matches the existing `deck-hearth-logo-container` CSS
class), D3 `deckhearth` (single token for ID use), D4
`admin@deckhearth.com` (placeholder .com pending point-domain convoy),
D5 full `deckhearth` Redis prefix (the 8-byte/key savings of `dh` are
negligible vs. self-documenting debuggability).
Boot-the-brief findings preempted: lockfile regen is architect-verified
to touch only the 2 `name` field lines (lines 2 + 8 of package-lock.json);
the test-file negative regression assertion's email literal recommendation
is PRESERVE the historical `admin@tcgvault.com` (the literal is a
documented pre-fix-auth-bypass bug shape, not an arbitrary email value);
scripts/reset-db.js line 142's CJS-in-ESM bug is OUT OF SCOPE and queued
as convert-reset-db-to-esm; the in-DB migration's UNIQUE-constraint fail-
loud is the intentional safety behavior. AGENTS.md Gotcha #4 / #12
updates are reserved for the doc-writer pass at convoy close (not
preempted by Brief 1).
Two NEW out-of-scope follow-ups surfaced beyond the convoy seed's four:
convert-reset-db-to-esm (CJS-in-ESM bug in reset-db.js, may fold into
purge-weak-creds-from-helpers) and update-seed-visual-baselines-on-linux-
ordering (the queued seed-visual-baselines convoy MUST run AFTER
pick-a-name so the first Linux baseline captures Deck Hearth strings,
not TCG Vault).
Co-authored-by: Cursor <cursoragent@cursor.com>
Operator gate-0 ratified 2026-05-24: Deck Hearth wins (more distinctive
brand, the brand the rendered Layout header already displays). The trade
is real — already-shipped infrastructure ID is the losing name —
so this convoy is non-trivial-sed and needs architect slicing.
Scoping rules baked into the convoy file:
- Repo + Vercel rename DEFERRED to follow-up convoy
rename-repo-and-vercel-project (auto-redirects make it low-urgency)
- Redis prefix migration IN SCOPE (lib/rate-limit.js uses
tcgvault:auth/search/upload/generate/import; rename atomic; accept
one-time per-15-min / per-1-hour counter reset, no user impact)
- Admin email migration IN SCOPE (admin@tcgvault.com -> proposed
admin@deckhearth.com; needs in-DB UPDATE script)
- package.json name rename IN SCOPE (we don't publish, contained blast)
- DNS / domain OUT OF SCOPE (operator doesn't own the domain yet)
- Brand asset regen OUT OF SCOPE (favicon + OG images need design pass)
5 named decisions (D1-D5) operator-ratified at gate-1: canonical
display string, canonical kebab, canonical camel/lower, canonical admin
email, canonical Redis prefix. No architectural decisions; this is a
pure naming convoy where the architect proposes the canonical shapes
and the operator picks.
Cross-cutting smoke + visual-diff blast flagged (smoke spec text
matchers + visual baselines both predicate on current brand strings;
the adopt-playwright-smoke Decision 4 continue-on-error swallow buys
us cover but the queued seed-visual-baselines-on-linux convoy gets
harder until this lands).
Architect dispatched next on convoy/pick-a-name. No code yet.
Co-authored-by: Cursor <cursoragent@cursor.com>