deckhearth/.convoys/pick-a-name/brief-1-display-and-comment-sweep.md
varutasu 9abbab6c21
feat(brand): unify on Deck Hearth across in-repo strings + infra (P1 brand decision)
Resolves the launch-blocking 'TCG Vault vs Deck Hearth' inconsistency called out in AGENTS.md line 5 since project setup. Operator gate-0 decision: Deck Hearth wins. Two briefs applied serially. B1 (mechanical): 7-file display + comment sweep. B2 (infrastructure): Redis prefix rename in lib/rate-limit.js (5 prefixes, accept one-time counter reset), package.json + lockfile regen (STOP-on-churn confirmed only name lines changed), admin/alice/bob email rename in seed scripts + login pre-fill + NEW idempotent migration script scripts/migrations/2026-05-24-rename-admin-email.js. Risk 4 PRESERVE applied: test/lib/permission-middleware.test.js retains admin@tcgvault.com literal with 7-line architect-authored why comment (documents pre-fix-auth-bypass bug shape; preserves historical truth per project's gotcha-documentation convention). All 5 D-decisions ratified at gate-1 (Deck Hearth / deck-hearth / deckhearth / admin@deckhearth.com / full deckhearth Redis prefix). Local: lint 128 baseline (B1 + B2), vitest 21/21 (B1 + B2). CI all green: Playwright smoke 3/3 against rebranded preview in 1m4s, forbidden-cors-headers pass, forbidden-endpoints pass, Screenshot diff pass, Vercel deployment complete. Cross-validation lineage: 4th convoy where the same 3-test smoke spec defends auth surface through sweeping change (after PR #15 Layout default-user, PR #19 CORS, PR #20 rate-limit, now this PR #21 brand rename). OPERATOR POST-MERGE ACTION REQUIRED: run 'node scripts/migrations/2026-05-24-rename-admin-email.js' against prod Neon DB before next admin login (ordering: migration FIRST, then any subsequent setup-db invocation). Migration is ESM, idempotent, UNIQUE-collision-safe. PR #21 architect-commit 50ce9ab, B1 ac8c998, B2 1c18d21.
2026-05-25 02:28:29 -05:00

23 KiB

convoy brief_number depends_on files
pick-a-name 1
AGENTS.md
.cursor/rules/ui-and-theming.mdc
.cursor/rules/auth-and-permissions.mdc
scripts/README.md
pages/api/cards/import-lorcana.js
pages/api/cards/import-pokemon.js
scripts/import-lorcana.js

Brief 1: In-repo display + comment sweep (User-Agent strings, branding notes, rule descriptions)

Goal (1 sentence)

Sweep the seven repo files whose ONLY brand references are display / comment / external-HTTP-User-Agent strings (NOT emails, NOT Redis prefixes, NOT package.json identifiers), renaming each occurrence of TCG Vault, TCG-Vault, and standalone-product-identity tcg-vault to the operator-ratified Deck Hearth / Deck-Hearth / deck-hearth per D1 + D2, while leaving every literal-repo-name reference (cd tcg-vault, directory-tree diagrams, workflow YAML comments) byte-identical because the repo + Vercel project rename is the queued rename-repo-and-vercel-project convoy.

Files in scope (do not edit anything else)

The 7 files listed in files: above (all modified, no new files, no deletions).

Files explicitly out of scope (do not touch even if it seems related):

  • README.md — title + admin-email mentions are in Brief 2 (file-disjoint per the slice plan; B2 owns README to keep the title + email changes atomic with the migration). Do NOT touch README in B1.
  • TESTING_GUIDE.md — title + test-user email table are in Brief 2 (same reason).
  • lib/rate-limit.js, package.json, package-lock.json, scripts/setup-neon-db.js, scripts/reset-db.js, scripts/create-test-users.js, pages/login.js, test/lib/permission-middleware.test.js, scripts/migrations/2026-05-24-rename-admin-email.js — all in Brief 2 (infrastructure + emails).
  • components/Layout.js, components/AnimatedFireLogo.js, components/ShareModal.js, pages/index.js, pages/login.js (welcome copy at lines 76 + 158), pages/signup.js, styles/globals.css — already render Deck Hearth correctly. Do NOT touch.
  • Repo-name references (literal tcg-vault describing the GitHub repo / Vercel project / directory): README.md lines 30 + 105, AGENTS.md line 1, .github/workflows/ci.yml lines 12 + 123, .github/workflows/visual-diff.yml line 5, .agent-context-manifest.yml lines 84/89/99/104/109/114. These stay byte-identical — the queued rename-repo-and-vercel-project convoy will sweep them when the repo + Vercel project are actually renamed. Per .convoys/pick-a-name.md § "Keep the repo tcg-vault for now". Do NOT rename in this brief.
  • AGENTS.md Gotcha #4 (line 53, admin@tcgvault.com reference) and AGENTS.md Gotcha #12 (rate-limit env-var explanation) — the doc-writer pass at convoy close updates these to reflect the post-migration admin email + post-rename Redis prefix. Do NOT preempt that edit here.
  • AGENTS.md line 1 (# AGENTS.md — AI collaboration (tcg-vault)) and AGENTS.md line 13 (Project overview admin@tcgvault.com mention) — repo-name reference (line 1) and email reference (line 13). Line 1 stays per the repo-rename scoping rule above; line 13 is updated by the doc-writer pass at convoy close (same as Gotcha #4) because it's email-bound and would otherwise contradict B2's migration outcome. Do NOT preempt those edits here.
  • .convoys/** history files — append-only per .cursor/rules/no-go-zones.mdc. The 30+ tcgvault / Deck Hearth references inside .convoys/ describe historical state at write-time and stay byte-identical. Doc-writer pass at this convoy's close ADDS a new "As-shipped" section to .convoys/pick-a-name.md; it does NOT rewrite history in other convoy files.
  • scripts/seed-collections-*.js, scripts/add-*.js, scripts/fix-*.js, components/Layout.js.backup — historical / legacy per .cursor/rules/no-go-zones.mdc § Append-only / historical. Do NOT touch.
  • pages/login.js quick-login fixture emails (lines 172, 184) — these are in Brief 2 because the email rename must coordinate with the seed scripts + migration. Do NOT touch login.js in B1.
  • tests/**, test/** — smoke spec, visual spec, and unit tests are untouched by B1. test/lib/permission-middleware.test.js line 87's negative regression assertion is in B2 (email-bound). The Playwright smoke spec's text matchers ('sign in' regex, /api/health) are brand-agnostic — verified at architect time.

Conventions to follow

Decisions from the convoy file (cite when implementing)

  • D1 (operator-ratified at gate-1): The canonical display string is "Deck Hearth" — two words, internal cap, space-separated. Use this for every user-facing-style replacement (titles, branding notes, descriptions).
  • D2 (operator-ratified at gate-1): The canonical kebab string is deck-hearth — used in User-Agent HTTP headers per the lowercase-hyphenated convention of HTTP user-agent product tokens (e.g. Mozilla/5.0, curl/8.4.0).

Repo conventions (cite + match)

  • .cursor/rules/no-go-zones.mdc. None of the 7 source files are listed under no-go zones. The "Card-import jobs" entry warns "Don't run them ad-hoc against prod data; use staging" — this brief edits only the User-Agent string sent in the HTTP request; the import behavior itself (Scryfall / Pokémon TCG / Lorcana API calls) is byte-identical post-edit.
  • .cursor/rules/ui-and-theming.mdc § Branding — line 61 currently states "The repo says 'TCG Vault' everywhere except components/Layout.js, which renders 'Deck Hearth' and 'DH' logo. A naming convoy is open. Until resolved, do not introduce a third name in new copy." That advice expires the moment the operator ratifies D1; the verbatim replacement copy is in the per-file Acceptance criteria below.
  • No fail-loud test gate for this kind of edit. There's no CI grep job that fails on tcgvault (we don't want one — convoy history references the literal). Validation is via per-file git diff review + the post-edit cross-file Repo-wide grep clean check in § Cross-file checks below.

Acceptance criteria

AGENTS.md (modified)

Replace line 5 — the branding note — with a one-line post-decision callout. Keep every other line byte-identical.

Current line 5:

> Branding note: the repo, README, and seed data say "TCG Vault" and `admin@tcgvault.com`, but the Layout component renders "Deck Hearth". Pick one before launch — see `.convoys/` for tracking.

Replace with:

> Branding note: **Deck Hearth** is the canonical product brand (ratified 2026-05-24 in the `pick-a-name` convoy). The repo directory name `tcg-vault` stays for now — see queued `rename-repo-and-vercel-project`. The seed admin email migrated from `admin@tcgvault.com` to `admin@deckhearth.com` in the same convoy; see Gotcha #4 + `.convoys/pick-a-name.md` for the rotation flow.

Acceptance:

  • Line 5 matches the verbatim replacement above (including the leading > blockquote marker, the two **-emphasis spans, the four backtick-quoted identifiers, and the trailing period).
  • Lines 1-4 and lines 6-end stay byte-identical. Do NOT touch line 1 (# AGENTS.md — AI collaboration (tcg-vault) — repo-name reference, scoped to rename-repo-and-vercel-project convoy).
  • Do NOT touch line 13 (Project overview Auth bullet's admin@tcgvault.com mention) — the doc-writer pass at convoy close updates that line together with Gotcha #4 to reflect the post-migration admin email; preempting here would contradict B2's migration outcome and create merge conflicts.
  • Do NOT touch Gotcha #4 (line 53) or Gotcha #12 (line 61-77) — those are doc-writer pass at convoy close.
  • Net diff: 1 line changed, 0 lines added, 0 lines deleted.

.cursor/rules/ui-and-theming.mdc (modified)

Replace line 61 — the "Branding" subsection content — with a post-decision sentence. Keep the heading ## Branding (the line ABOVE it, line 60 in the unedited file) byte-identical.

Current line 61:

The repo says "TCG Vault" everywhere except `components/Layout.js`, which renders "Deck Hearth" and "DH" logo. A naming convoy is open. Until resolved, **do not introduce a third name** in new copy.

Replace with:

The canonical product brand is **Deck Hearth** (two words, internal cap), ratified 2026-05-24 in the `pick-a-name` convoy. The repo directory + GitHub project name remain `tcg-vault` until the queued `rename-repo-and-vercel-project` convoy ships. New UI copy MUST use `Deck Hearth` verbatim — do not introduce a third name, do not abbreviate to "DH" outside the logo glyph (currently used in `components/Layout.js` lines 621, 714 as the sidebar logo monogram).

Acceptance:

  • Line 61 matches the verbatim replacement above.
  • Every other line in the file stays byte-identical.
  • Net diff: 1 line changed, 0 lines added, 0 lines deleted.
  • The two referenced line numbers in the new copy (621, 714) are architect-verified against the current components/Layout.js — those are the two <span className="text-white font-bold text-sm">DH</span> lines.

.cursor/rules/auth-and-permissions.mdc (modified)

Replace line 2 — the frontmatter description: value — with the new product name. Keep lines 1 (---), 3 (globs: ...), and 4 (---) byte-identical.

Current line 2:

description: Auth model + permission model for tcg-vault (JWT + collection roles)

Replace with:

description: Auth model + permission model for Deck Hearth (JWT + collection roles)

Acceptance:

  • Line 2 matches the verbatim replacement above (no trailing whitespace).
  • Frontmatter delimiters and globs: line stay byte-identical.
  • Every line below the frontmatter (# Auth + permissions heading down) stays byte-identical. In particular, do NOT touch the body's tcgvault references — there are none in this file outside the frontmatter description.
  • Net diff: 1 line changed.

scripts/README.md (modified)

Replace line 1 — the title. Keep every other line byte-identical (line 3 contains the generic phrase TCG card data referring to trading-card-game card data, NOT the product brand "TCG Vault"; preserve unchanged).

Current line 1:

# TCG Vault Bulk Import Scripts

Replace with:

# Deck Hearth Bulk Import Scripts

Acceptance:

  • Line 1 matches the verbatim replacement above.
  • Line 3 (This directory contains scripts for bulk importing TCG card data into the database.) stays byte-identical — TCG card data is the generic acronym for "trading card game", NOT the product brand.
  • Every other line stays byte-identical.
  • Net diff: 1 line changed.

pages/api/cards/import-lorcana.js (modified)

Replace the User-Agent product token on line 14. This is the external HTTP identity sent to the Lorcana API and is part of our brand contract with the upstream service (Lorcana operators may rate-limit or contact us via this UA — better that they see the current brand name).

Current line 14:

          'User-Agent': 'TCG-Vault/1.0',

Replace with:

          'User-Agent': 'Deck-Hearth/1.0',

Acceptance:

  • Line 14 matches the verbatim replacement above (preserves the surrounding 10-space indent, the trailing comma, the version 1.0).
  • No other line in the file changes. Specifically: the auth check (line 2 getUserFromRequest import), the rate-limit check (line 3 checkImportRateLimit import), the delay() helper, fetchWithRetry() retry logic, and the handler body all stay byte-identical. The add-rate-limiting Brief 1 contract for this file (auth → admin-role → import rate-limit gate ordering) is preserved.
  • Net diff: 1 line changed.

pages/api/cards/import-pokemon.js (modified)

Same change as import-lorcana.js — replace the User-Agent product token on line 14.

Current line 14:

          'User-Agent': 'TCG-Vault/1.0',

Replace with:

          'User-Agent': 'Deck-Hearth/1.0',

Acceptance:

  • Line 14 matches the verbatim replacement above.
  • No other line in the file changes (including the Pokémon TCG fetch + INSERT loop, the fetchWithRetry + delay helpers, and the add-rate-limiting-installed gates).
  • Net diff: 1 line changed.

scripts/import-lorcana.js (modified — standalone CLI variant)

Replace the User-Agent product token on line 20. This is the CLI-script variant of the Lorcana importer (independent of the API route); per .cursor/rules/no-go-zones.mdc § "Card-import jobs" the script runs against external APIs with rate limits — same brand-identity argument as the API route.

Current line 20:

          'User-Agent': 'TCG-Vault/1.0',

Replace with:

          'User-Agent': 'Deck-Hearth/1.0',

Acceptance:

  • Line 20 matches the verbatim replacement above.
  • No other line in the file changes.
  • Net diff: 1 line changed.

Cross-file checks

  • npm run lint exit code unchanged. The baseline is whatever the convoy/pick-a-name branch tip currently reports — none of B1's edits introduce ESLint surface (no new code, no removed imports, no new syntax). If the count changes by even 1, investigate before commit.

  • npm run test:run (vitest) passes 21/21. No test file is touched in B1. Re-run after the sweep to confirm.

  • npm run build exit 0. Turbopack should compile cleanly — all edits are string literals or markdown.

  • Smoke spec still passes 3/3 (npm run test:smoke against a preview, or skip locally — the smoke spec's text matchers are 'sign in' regex + /api/health + HTTP status < 500, brand-agnostic).

  • Repo-wide grep check (post-B1, expect B2 still pending). After running B1, the following rg invocations should show ONLY the still-pending B2 surfaces (no B1 surfaces should remain):

    # B1 should have eliminated these:
    rg "TCG-Vault/1.0" .
    

    Expected: zero matches. (Architect verified pre-B1: 3 matches — the three User-Agent strings touched by B1.)

    rg '"TCG Vault"' AGENTS.md .cursor/rules/ scripts/README.md
    

    Expected: zero matches in the listed paths. (Architect verified pre-B1: 1 match in AGENTS.md line 5, 1 match in .cursor/rules/ui-and-theming.mdc line 61, 0 in scripts/README.md — the # TCG Vault Bulk Import Scripts title is unquoted.)

    rg "for tcg-vault" .cursor/rules/
    

    Expected: zero matches. (Architect verified pre-B1: 1 match in auth-and-permissions.mdc line 2.)

  • No collateral damage in .convoys/. The 30+ historical references stay byte-identical:

    rg "TCG Vault|tcgvault|tcg-vault" .convoys/ | wc -l
    

    Expected: same count as pre-B1 (architect-verified: ~25 lines across .convoys/).

  • No collateral damage in already-correct files. The seven Deck Hearth-correct files (components/Layout.js, components/AnimatedFireLogo.js, components/ShareModal.js, pages/index.js, pages/login.js welcome copy, pages/signup.js, styles/globals.css) stay byte-identical:

    git diff --stat -- components/Layout.js components/AnimatedFireLogo.js components/ShareModal.js pages/index.js pages/signup.js styles/globals.css
    

    Expected: no diff for those six. (pages/login.js is touched by B2 — that's the only listed file with expected B2-side changes.)

  • Diff hygiene. git diff main..HEAD --stat (after B1 commit only) should show:

    • AGENTS.md: 1 line + / 1 line -.
    • .cursor/rules/ui-and-theming.mdc: 1 line + / 1 line -.
    • .cursor/rules/auth-and-permissions.mdc: 1 line + / 1 line -.
    • scripts/README.md: 1 line + / 1 line -.
    • pages/api/cards/import-lorcana.js: 1 line + / 1 line -.
    • pages/api/cards/import-pokemon.js: 1 line + / 1 line -.
    • scripts/import-lorcana.js: 1 line + / 1 line -.
    • No whitespace-only changes elsewhere.
    • Total: ~7 lines + / ~7 lines -.

Manual verification (in addition to CI on push)

  • Visual sanity. Open AGENTS.md and .cursor/rules/ui-and-theming.mdc in an editor. The branding-note paragraphs should read coherently — no orphaned "see .convoys/ for tracking" reference left after the rewrite.
  • Import job smoke (optional, against staging only). If a staging Postgres is available, run one of the gated import jobs (POST /api/cards/import-mtg with an admin token + a small set code like neo) and confirm the response succeeds. The User-Agent change is observed by the upstream API, not by the response — but the request should still 200 if our auth + rate-limit + admin-role chain is intact. Skip if no staging is available. Per .cursor/rules/no-go-zones.mdc § Card-import jobs: do NOT run against prod.
  • Read the convoy file's § "Boot-the-brief findings" below before commit to make sure no architect note was missed.

Boot-the-brief findings (preempted by the architect; do not re-investigate)

Finding 1 — None of the 7 B1 files have NPM dependency churn

Architect-verified: every edit in B1 is a string-literal replacement inside an already-committed file. Zero new imports, zero new dependencies, zero version pin changes. package.json and package-lock.json are NOT in B1's files: (they're in B2).

Finding 2 — User-Agent rename is observable to external services (not user-facing)

The three User-Agent strings on line 14 of import-lorcana.js, line 14 of import-pokemon.js, and line 20 of scripts/import-lorcana.js are sent in the fetch() headers to the respective upstream APIs. They identify OUR app to the upstream — Scryfall (MTG; note: import-mtg.js does NOT set a custom UA, falling back to Node's default), Pokémon TCG, and the Lorcana API. Renaming aligns with the post-D1 brand. Upstream API responses are not affected by the UA string change (they use the UA for logging / contact, not for routing).

Architect ran rg "User-Agent" pages/api/cards/ scripts/ at brief time — exactly three matches (the three lines above). No fourth import-mtg.js UA setting was found; Scryfall is fine with Node's default UA.

Finding 3 — AGENTS.md line 5 rewrite must NOT pre-empt Gotcha #4 / #13 updates

The convoy file's .convoys/pick-a-name.md § Known constraints explicitly notes that AGENTS.md line 5 is the "canonical historical record of the inconsistency" and that "the doc-writer pass MUST update it from 'Pick one before launch' to ''". This brief does the line-5 callout rewrite; the doc-writer pass at convoy close adds an "As-shipped" milestone entry to .convoys/pick-a-name.md AND updates Gotcha #4's admin-email caveat to reflect the migration outcome AND adds a NEW Gotcha #13 (or amends #12) for the Redis prefix rename. Do NOT preempt those Gotcha edits in B1. The line-5 callout rewrite is the line that needs to "stop saying the brand is unresolved" — that's what unlocks the rest of the doc-writer's milestone copy.

Finding 4 — .cursor/rules/auth-and-permissions.mdc line 2 is a YAML frontmatter description, not body markdown

Architect-verified by reading lines 1-4 of the file: it's standard Cursor .mdc rule frontmatter. The description: field shows in the rule-picker UI when a user is browsing rules. Changing it from tcg-vault to Deck Hearth updates the human-facing tag in the rule picker. Do NOT add a body-markdown edit chasing other tcgvault strings in the file body — architect ran rg "tcgvault" .cursor/rules/auth-and-permissions.mdc and found ZERO matches outside line 2.

Finding 5 — scripts/README.md line 3's "TCG card data" is the GENERIC acronym, not the product

Architect read line 3 in full: "This directory contains scripts for bulk importing TCG card data into the database."TCG here is "trading card game" (the industry generic), NOT "TCG Vault" the product. Architect verified this elsewhere in the file: lines 14, 18, 29, 33 use "TCGs", "Magic", "Pokemon", "Lorcana" all in the trading-card-game generic sense. Only line 1 (the title) is the product-brand reference. Replace line 1 only.

Finding 6 — Workflow YAML comments referring to "tcg-vault" describe the literal repo, not the product

.github/workflows/ci.yml line 12 (# NOTE: tcg-vault is JavaScript (not TypeScript). …) and line 123 (# The tcg-vault frontend and API are served from the same Vercel deployment …), and .github/workflows/visual-diff.yml line 5 (# Paths are tcg-vault-specific …) all use tcg-vault as the literal repo / deployment name. Per the convoy seed § "Keep the repo tcg-vault for now" and § "GitHub rename is a separate concern … track as a queued follow-up convoy rename-repo-and-vercel-project", these stay byte-identical. Do NOT add .github/workflows/*.yml to B1's files: — they're out of scope.

Finding 7 — .agent-context-manifest.yml source: "tcg-vault-local" tags stay (internal sync-tracking)

Architect read the manifest: 6 entries reference source: "tcg-vault-local" as an internal source identifier for the sync-agent-context skill's drift detection. The skill compares an installed artifact's content against the "tcg-vault-local" source to detect drift. Renaming the source tag to deck-hearth-local could break the sync skill's behavior (it tracks "what shipped from this source"); the rename belongs to rename-repo-and-vercel-project when the actual repo name changes. Do NOT touch .agent-context-manifest.yml in B1.

Out of scope (do not do these)

  • Do NOT edit README.md, TESTING_GUIDE.md, lib/rate-limit.js, package.json, package-lock.json, scripts/setup-neon-db.js, scripts/reset-db.js, scripts/create-test-users.js, pages/login.js, or test/lib/permission-middleware.test.js — all in B2.
  • Do NOT touch any file under .convoys/ (append-only history per no-go-zones).
  • Do NOT touch components/Layout.js.backup (legacy snapshot per no-go-zones).
  • Do NOT touch scripts/seed-collections-*.js, scripts/add-*.js, or scripts/fix-*.js (historical migration jobs per no-go-zones).
  • Do NOT touch repo-name references (README.md cd / tree, AGENTS.md line 1, .github/workflows/*.yml, .agent-context-manifest.yml source tags) — those are in rename-repo-and-vercel-project.
  • Do NOT touch AGENTS.md Gotcha #4 / Gotcha #12 — doc-writer pass at convoy close.
  • Do NOT touch AGENTS.md line 1 (# AGENTS.md — AI collaboration (tcg-vault)) or line 13 (project overview Auth bullet's admin@tcgvault.com mention).
  • Do NOT preempt visual-baseline regeneration. tests/visual/__screenshots__/ does not exist; the queued seed-visual-baselines-on-linux convoy seeds it AFTER pick-a-name lands.
  • Do NOT introduce a new file (no migration scripts, no helper modules). All B1 edits are in-place.
  • Do NOT bump any dependency or run npm install (that's a B2 step for the package.json name change).

Rationale (≤3 sentences)

B1 is the lowest-risk, lowest-blast slice of the convoy: 7 files, ~7 lines net, no infrastructure changes, no test or DB impact — purely the in-repo display / comment / external-HTTP-User-Agent strings that match the operator-ratified D1 ("Deck Hearth") and D2 (deck-hearth) decisions. Splitting it from B2 keeps the email-migration + Redis-prefix-rename + lockfile-regen blast radius isolated, AND lets the conductor dispatch both briefs in parallel via /multitask because their files: sets are disjoint. The only soft scope edge — repo-literal references like cd tcg-vault — is explicitly deferred to the queued rename-repo-and-vercel-project convoy so this brief stays mechanical.