--- name: drop-public-setup classification: convoy success_metric: | No hardcoded admin credentials in repo (source or README). setup-neon-db.js requires ADMIN_INITIAL_PASSWORD env var. New env-var setup documented in README. Existing deployed admin user (if hash matches the known-weak default) is either rotated or flagged for manual rotation. skip: - role-design-system-auditor - role-a11y-auditor - role-ux-reviewer - role-ia-architect - browser-smoke status: open created: 2026-05-23 parent: ship-readiness addresses: P0 #3 depends_on: - bump-next-js (shipped) - fix-auth-bypass (shipped — already removed pages/api/setup-database.js) --- # Drop public setup Close P0 #3 from `.convoys/ship-readiness.md`: remove the hardcoded admin credentials (`admin@tcgvault.com` / `admin123`) from the seed script and the README. ## Scope (verbatim from ship-readiness P0 #3) - **`scripts/setup-neon-db.js` lines 130-138** — currently creates the admin user with a hardcoded `admin123` bcrypt hash. Change to require an `ADMIN_INITIAL_PASSWORD` env var with no default. Fail loudly (exit non-zero with a clear message) if the env var is unset. - **`README.md`** — strip the "Default Admin Account" section. Replace with "run `npm run setup-db` and follow the prompt" (or however the architect decides to phrase it; the spec is "no credentials in README"). - **`pages/api/setup-database.js`** — already deleted by fix-auth-bypass Brief 3 (commit fc0dd73). Not in scope here; just noting for completeness. ## Out of scope - Migration tooling (`migration-tool` convoy, P1 #11) - Renaming the admin email from `admin@tcgvault.com` to anything else (branding decision belongs to `pick-a-name` convoy, P1 #12) - Any other `scripts/seed-*.js` or `scripts/add-*.js` files (those are one-off historical jobs per no-go-zones) - Any change to `pages/api/auth/*.js` (fix-auth-bypass shipped; further hardening lives in `cors-tighten` / `add-rate-limiting`) ## Architect's questions 1. **Existing-admin story.** If a deployed environment already has the admin row with `bcrypt.hash('admin123', ...)`, this convoy alone does NOT rotate that password — it only prevents the weak default on *new* envs. Options: a. Going-forward only. Flag for manual rotation; assume any environment with the default already needs operator attention. b. Add a one-time idempotent script under `scripts/migrations/` that checks the admin row's password_hash against the known weak default and forces a reset / requires `ADMIN_RESET_PASSWORD` env var. c. Add a startup check to the deploy pipeline that fails the deploy if the admin row matches the weak hash. Recommend the architect pick (a) for simplicity and queue (b) as a follow-up if needed. (a) is consistent with how Brief 1 of fix-auth-bypass handled the JWT_SECRET — going-forward fix-loud, not a sweep of existing data. 2. **`setup-neon-db.js` no-go-zones rule.** The rule says "do NOT edit `scripts/setup-neon-db.js` in place — it's idempotent and meant for first-time setup only." That rule is about *schema* changes (adding columns, etc.). This convoy edits the script's admin-creation logic to add an env-var gate — operational, not schema. Architect should confirm this reading and document the distinction in the brief. 3. **Test coverage.** Brief 5 of fix-auth-bypass introduced vitest. Does this convoy add tests for the env-var-required path? Probably not (setup scripts are typically tested via manual smoke, not unit tests). Architect decides. ## Expected size 1-2 briefs, ~3 files total, no UI, no API surface, no migration. Should ship as a single PR (no fan-out).