- Correct all passwords (were wrong/outdated) - Add full table of current seeded users (superadmin, admins, candidates) - Document 3 bugs fixed 2026-02-24: - superadmin placeholder hash (seeder fix) - users.status VARCHAR(20) crash loop (migration fix) - PASSWORD_PEPPER alignment requirement - Add bash ! expansion gotcha for curl testing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.4 KiB
🧪 Test Users & Credentials — GoHorseJobs
All accounts below are provisioned by seeder-api against the DEV environment (local.gohorsejobs.com / api-local.gohorsejobs.com).
Last verified: 2026-02-24 Environment: Coolify DEV (Redbull VPS) Auth endpoint:
POST https://api-local.gohorsejobs.com/api/v1/auth/login
Login Payload Format
{ "email": "<identifier OR email>", "password": "<password>" }
The "email" JSON key accepts both the username (identifier) and the actual e-mail address. The backend resolves WHERE email = $1 OR identifier = $1.
👑 SuperAdmin
| Identifier | Password | Role | |
|---|---|---|---|
lol |
lol@gohorsejobs.com |
Admin@2025! |
superadmin |
superadmin |
admin@gohorsejobs.com |
Admin@2025! |
superadmin |
Both identifiers grant full system access. lol is the primary dev account; superadmin is the alias created by migration 010.
🏢 Admins / Recruiters
| Identifier | Password | Role | Company | |
|---|---|---|---|---|
takeshi_yamamoto |
takeshi@techcorp.com |
Takeshi@2025 |
admin | TechCorp |
kenji |
kenji@appmakers.mobile |
Takeshi@2025 |
admin | AppMakers |
maria_santos |
maria@designhub.com |
User@2025 |
recruiter | DesignHub |
wile_e_coyote |
wile@acme.corp |
MeepMeep@123 |
admin | ACME Corporation |
🙋 Candidates
Unified Users (identifier-based login)
| Identifier | Password | Name | |
|---|---|---|---|
paulo_santos |
paulo@email.com |
User@2025 |
Paulo Santos |
maria_email |
maria@email.com |
User@2025 |
Maria Reyes |
Legacy Candidates (email-based login)
| Password | Name | |
|---|---|---|
ana.silva@example.com |
User@2025 |
Ana Silva |
carlos.santos@example.com |
User@2025 |
Carlos Santos |
maria.oliveira@example.com |
User@2025 |
Maria Oliveira |
pedro.costa@example.com |
User@2025 |
Pedro Costa |
juliana.ferreira@example.com |
User@2025 |
Juliana Ferreira |
🌱 Seeding & Reset
# Reset all data (drops and recreates all public tables)
curl -X POST https://s-local.gohorsejobs.com/reset
# Re-seed everything (locations, users, companies, jobs, applications)
curl https://s-local.gohorsejobs.com/seed/stream
# After reset+seed, the backend must be reachable so migrations have already run.
# The seeder does NOT apply Go migrations — they run on backend startup.
Order matters after a full DB wipe:
- Wait for the backend container to finish running migrations (check
GET /api/v1/jobsreturns[])- Then run
POST /reset→GET /seed/stream
⚠️ Known Issues / Gotchas
1. superadmin login broken after DB reset (FIXED 2026-02-24)
Bug: Migration 010_seed_super_admin.sql creates the superadmin user with a hardcoded placeholder hash ($invalid-placeholder-run-seeder$). The seeder previously only updated lol's hash, leaving superadmin permanently unable to log in after a DB reset.
Root cause: ON CONFLICT DO NOTHING in migration 010 means the user exists in the DB but with an unusable hash. The seeder's upsert only covered the lol identifier.
Fix (commit 6b1c058): seeder-api/src/seeders/users.js now also upserts superadmin with the same runtime-generated hash as lol:
// Uses the same bcrypt(pass + PASSWORD_PEPPER) hash already computed for lol
await pool.query(`
INSERT INTO users (identifier, password_hash, ...) VALUES ('superadmin', $1, ...)
ON CONFLICT (identifier) DO UPDATE SET password_hash = EXCLUDED.password_hash, status = 'active'
`, [superAdminHash]);
Affected versions: All environments before 6b1c058. Triggered on every fresh DB seed.
2. users.status column too short — backend crash loop on startup (FIXED 2026-02-24)
Bug: Migration 009_unify_schema.sql defined status VARCHAR(20). Migration 010_seed_super_admin.sql tried to insert 'force_change_password' (21 chars), crashing the backend with pq: value too long for type character varying(20) on every restart.
Fix (commit e5e4397):
009:VARCHAR(20)→VARCHAR(30)010: initial status changed from'force_change_password'→'pending'- New migration
046_fix_user_status_varchar.sql:ALTER TABLE users ALTER COLUMN status TYPE VARCHAR(30)for existing deployments
3. PASSWORD_PEPPER must match between seeder and backend
All password hashes are stored as bcrypt(password + PASSWORD_PEPPER). Both the seeder-api and backend must have the same PASSWORD_PEPPER env var, or all logins return 401 invalid credentials.
DEV value: gohorse-pepper
Confirmed in: Coolify backend env + Coolify seeder env
If logins break after a deploy: check docker inspect <backend_container> --format '{{.Config.Env}}' for PASSWORD_PEPPER, then re-run the seeder.
4. Bash ! expansion breaks login tests via curl
When testing logins from the shell, passwords containing ! (e.g. Admin@2025!) must be in a file or use $'...' syntax. Using "Admin@2025!" in double-quotes causes bash history expansion (\!), producing invalid JSON and a 400 Invalid Request.
# WRONG (bash expands !)
curl ... -d '{"email":"lol","password":"Admin@2025!"}' # OK in single quotes
curl ... -d "{\"email\":\"lol\",\"password\":\"Admin@2025!\"}" # BROKEN
# CORRECT — use a file
cat > /tmp/login.json << 'EOF'
{"email":"lol","password":"Admin@2025!"}
EOF
curl -X POST .../auth/login -d @/tmp/login.json