diff --git a/.convoys/drop-public-setup.md b/.convoys/drop-public-setup.md new file mode 100644 index 0000000..16638f8 --- /dev/null +++ b/.convoys/drop-public-setup.md @@ -0,0 +1,88 @@ +--- +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).