gohorsejobs/docs/AGENTS.md
Tiago Yamamoto fcf960381c fix(auth): corrige hash seed e documenta alinhamento do PASSWORD_PEPPER
- Atualiza hash hardcoded em 010_seed_super_admin.sql para hash válido
  gerado com pepper=gohorse-pepper (o antigo hash estava inválido e causava
  AUTH_INVALID_CREDENTIALS em qualquer reset do banco)
- Corrige valor de PASSWORD_PEPPER e CORS_ORIGINS no DEVOPS.md para
  refletir os valores reais do Coolify DEV
- Adiciona seção de troubleshooting no DEVOPS.md com diagnóstico e fix
  passo-a-passo para mismatch de pepper
- Adiciona seção "Known Gotchas" no AGENTS.md documentando:
  * Regra do PASSWORD_PEPPER (deve ser gohorse-pepper em todos ambientes)
  * Campo de login é email no DTO, não identifier
  * Hashes bcrypt em SQL devem usar arquivo -f, nunca -c ($ é expandido)
  * Credenciais de teste do ambiente DEV

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 11:43:35 -06:00

13 KiB

AGENTS.md - GoHorse Jobs

Last Updated: 2026-02-18 Purpose: Context for AI coding assistants (Claude, Cursor, etc.)


Project Overview

GoHorse Jobs is a B2B SaaS recruitment platform connecting companies with candidates. It is structured as a monorepo with multiple services sharing a single PostgreSQL database.

Business model: Freemium (Free / Pro R$199/month / Enterprise custom pricing).


Repository Structure

gohorsejobs/
├── backend/              # Go 1.24 REST API (Clean Architecture + DDD)
├── frontend/             # Next.js 15 web application (App Router)
├── backoffice/           # NestJS 11 admin/worker API (Fastify adapter)
├── seeder-api/           # Node.js Express database seeder
├── job-scraper-multisite/# Job scraping service
├── k8s/                  # Kubernetes manifests (dev, hml, prd)
├── docs/                 # Central documentation
├── .forgejo/             # Forgejo CI/CD workflows
├── .drone.yml            # Drone CI/CD pipelines
└── start.sh              # Interactive dev startup script

Tech Stack

Service Language Framework Key Libraries
Backend Go 1.24 stdlib net/http JWT v5, lib/pq, GORM, Stripe, AWS SDK v2, RabbitMQ, Firebase Admin, Swaggo
Frontend TypeScript 5 Next.js 15 (App Router) React 19, Tailwind CSS 4, shadcn/ui, Zustand, React Hook Form + Zod, Framer Motion
Backoffice TypeScript 5 NestJS 11 (Fastify) TypeORM, Passport + JWT, Stripe, AMQP, Nodemailer, Pino, Firebase Admin
Seeder JavaScript (ESM) Express 5 pg, bcrypt

Database: PostgreSQL 16+ with UUID v7 primary keys. 43+ SQL migration files in backend/migrations/.


Quick Start

./start.sh   # Interactive menu
Option Action
1 Start Frontend + Backend
2 Reset DB + Seed + Start
3 Start all services (Frontend + Backend + Backoffice)
4 Run migrations only
5 Seed database (append)
6 Full DB reset + migrate + seed
7 Run backend E2E tests
8 Seed reset LITE (skip 153k cities)
9 Run all tests (Backend + Frontend)

Service Ports

Service Port
Backend 8521
Frontend 8963
Backoffice 3001
Swagger (Backend) 8521/swagger/index.html
Swagger (Backoffice) 3001/api/docs

Build & Test Commands

Backend (Go)

cd backend && go run cmd/api/main.go              # Run
go test -v ./... -count=1                         # All unit tests
go test -tags=e2e -v ./tests/e2e/...              # E2E tests
swag init -g cmd/api/main.go --parseDependency --parseInternal  # Swagger
go mod tidy                                       # Dependencies

Frontend (Next.js)

cd frontend
npm install          # Install deps
npm run dev          # Dev server (use -p 8963 for project convention)
npm run build        # Production build
npm run lint         # ESLint
npm run test         # Jest unit tests

Backoffice (NestJS)

cd backoffice
pnpm install          # Uses pnpm
npm run start:dev     # Dev server with watch
npm run build         # Production build
npm run lint          # ESLint with auto-fix
npm run test          # Jest unit tests
npm run test:e2e      # E2E tests

Seeder

cd seeder-api
npm install
npm run migrate       # Run migrations
npm run seed          # Seed data
npm run seed:reset    # Drop all tables
npm run seed:lite     # Seed without 153k cities

Architecture & Conventions

Backend (Go) - Clean Architecture + DDD

backend/internal/
├── api/              # (legacy) HTTP handlers
├── handlers/         # HTTP request handlers (current)
├── middleware/       # Auth, CORS, rate limiting, security headers
├── core/
│   ├── domain/entity/ # Business entities (User, Company, Job, etc.)
│   ├── ports/         # Repository interfaces
│   └── usecases/      # Business logic (LoginUseCase, RegisterUseCase, etc.)
├── infrastructure/
│   ├── auth/          # JWT service
│   ├── persistence/   # PostgreSQL repository implementations
│   └── storage/       # S3/R2 storage adapter
├── services/          # Business services (Email, FCM, Storage, Admin)
├── dto/               # Data Transfer Objects
├── router/            # Route definitions
├── models/            # GORM models (legacy, being migrated)
├── database/          # DB connection & migration runner
└── utils/             # Utilities (JWT, sanitizer)

Patterns:

  • Constructor injection: func NewService(db *sql.DB) *Service
  • All DB operations accept ctx context.Context
  • Error handling: (T, error) return tuples
  • Repository interfaces in core/ports/, implementations in infrastructure/persistence/
  • Test files: *_test.go

Frontend (Next.js) - App Router

frontend/src/
├── app/               # File-based routing (20+ routes)
│   ├── dashboard/     # Protected routes (12+ sub-pages)
│   ├── jobs/          # Job listing & details
│   └── auth/          # Login, register flows
├── components/        # Reusable components (44+)
│   └── ui/            # shadcn/ui primitives (24+)
├── hooks/             # Custom React hooks
├── contexts/          # React contexts (auth, theme)
├── lib/               # Utilities (API calls, validation)
└── i18n/              # Internationalization (PT, EN, ES, JA)

Patterns:

  • Server Components by default; use 'use client' for interactivity
  • Tailwind CSS utility classes
  • Path alias: @/* maps to ./src/*
  • Form validation: React Hook Form + Zod schemas
  • Global state: Zustand stores
  • Test files: *.test.tsx

Backoffice (NestJS) - Modular

backoffice/src/
├── admin/             # Dashboard & statistics
├── auth/              # JWT authentication (Passport)
├── email/             # Email worker (AMQP/LavinMQ consumer)
├── external-services/ # Credential management
├── fcm-tokens/        # Firebase push tokens
├── plans/             # Subscription plans
├── stripe/            # Stripe payment integration
└── tickets/           # Support tickets

Patterns:

  • NestJS module pattern: *.module.ts, *.controller.ts, *.service.ts
  • Guards: @UseGuards(JwtAuthGuard)
  • DTOs: create-*.dto.ts, update-*.dto.ts with class-validator
  • Prettier: single quotes, trailing commas

Authentication & Authorization

  • JWT: HS256 with HttpOnly cookies (web) + Bearer tokens (API/mobile)
  • 4 roles: superadmin > admin > recruiter > candidate
  • Middleware stack: Auth (JWT+RBAC) -> CORS -> Rate Limiting (100 req/min) -> Security Headers -> XSS Sanitizer
  • JWT secret must match between Backend and Backoffice
  • Test credentials: See TEST_USERS.md for all test accounts

Database

  • PostgreSQL 16+ with UUID v7 for primary keys (SERIAL for reference tables)
  • Migrations: backend/migrations/ (43+ SQL files, numbered 000_ through 999_)
  • Core tables: users, companies, user_companies, jobs, applications, favorite_jobs, notifications, tickets, activity_logs, job_payments

API Routes

All backend routes under /api/v1:

  • Auth: /auth/login, /auth/register/candidate, /auth/register/company, /auth/forgot-password, /auth/reset-password
  • Jobs: CRUD at /jobs, moderation at /jobs/moderation
  • Companies: CRUD at /companies, status management
  • Users: /users/me (profile), admin CRUD at /users
  • Applications: /applications with status updates
  • Storage: /storage/upload-url (presigned S3/R2 URLs)
  • Admin: /admin/companies, /admin/email-templates, /admin/email-settings
  • Notifications: /notifications, /tokens (FCM)
  • Chat: /conversations, /conversations/{id}/messages

External Services

Service Purpose
Stripe Payment processing & subscriptions
Firebase (FCM) Push notifications
Appwrite Real-time chat/messaging
LavinMQ (AMQP) Message queue for background jobs
Cloudflare R2 / S3 File/image storage
Resend Transactional email

Deployment

  • Environments: dev (branch: dev), hml (branch: hml), prd (branch: main)
  • CI/CD: Forgejo workflows (.forgejo/workflows/) + Drone (.drone.yml)
  • Container runtime: Podman (Apolo), Coolify/Docker (Redbull), Kubernetes (production)
  • Registry: Forgejo (forgejo-gru.rede5.com.br/rede5/)
  • Coolify UI: https://redbull.rede5.com.br (Redbull VPS DEV environment)

DEV Environments

Server Type URLs
Redbull (Coolify) Auto-deploy via Git local.gohorsejobs.com, api-local.gohorsejobs.com
Apolo (Podman/Quadlet) Manual deploy dev.gohorsejobs.com, api-tmp.gohorsejobs.com

Git Workflow

Remotes

Remote URL Function
origin git@github.com:rede5/gohorsejobs.git GitHub - main development
pipe https://pipe.gohorsejobs.com/bohessefm/gohorsejobs.git Forgejo - mirror/CI

Branches

Branch Environment Description
dev Development Main working branch
hml Staging Pre-production testing
main Production Stable release

Sync Flow

# 1. Pull from GitHub
git pull origin dev

# 2. Push to Forgejo (pipe)
git push pipe dev

Key Things to Know

  1. Backend uses Clean Architecture + DDD; respect layer boundaries (handlers -> usecases -> ports/repositories)
  2. Frontend uses Next.js App Router; pages in src/app/, components in src/components/
  3. Backoffice shares the same PostgreSQL database as the backend
  4. Migrations are plain SQL files, not managed by an ORM
  5. Project supports 4 languages (PT, EN, ES, JA) via i18n
  6. Environment variables in .env files (gitignored)
  7. Use start.sh for local development

⚠️ Known Gotchas

1. PASSWORD_PEPPER must be gohorse-pepper everywhere

All migration seeds (010_seed_super_admin.sql) and the seeder-api use gohorse-pepper as the bcrypt pepper. The Coolify/production env var PASSWORD_PEPPER must match or every login returns AUTH_INVALID_CREDENTIALS.

Location Value
backend/.env (local) gohorse-pepper
seeder-api/.env gohorse-pepper
Coolify DEV (iw4sow8s0kkg4cccsk08gsoo) gohorse-pepper
Migration 010_seed_super_admin.sql hash computed with gohorse-pepper

If you suspect a mismatch, see the full fix procedure in DEVOPS.md.

2. Login API field: email, not identifier

The frontend login form sends { "email": "<username_or_email>", "password": "..." }. The backend core DTO (internal/core/dto/user_auth.go) has field Email, not Identifier. The repository resolves it via WHERE email = $1 OR identifier = $1, so both username and email work.

Do not send { "identifier": "..." } directly to /api/v1/auth/login — the field will be ignored and login will fail silently.

3. Bcrypt hashes in SQL — always use a file, never -c

Shell interprets $ in bcrypt hashes as variable expansions. Example of broken approach:

# ❌ WRONG — $2b gets expanded by shell, hash gets corrupted
docker exec postgres psql -U user -d db -c "UPDATE users SET password_hash='$2b$10$abc...'"

Correct approach — write to file first, then use -f:

cat > /tmp/fix.sql <<'EOF'
UPDATE users SET password_hash = '$2b$10$4759wJhnXnBpcwSnVZm9Eu.wTqGYVCHkxAU5a2NxhsFHU42nV3tzW' WHERE identifier = 'lol';
EOF
docker cp /tmp/fix.sql <postgres_container>:/tmp/fix.sql
docker exec <postgres_container> psql -U gohorsejobs -d gohorsejobs -f /tmp/fix.sql

4. Test credentials (DEV/local.gohorsejobs.com)

Role Identifier Password Email
superadmin lol Admin@2025! lol@gohorsejobs.com
superadmin superadmin Admin@2025! admin@gohorsejobs.com

Documentation Index

Document Location Description
API Reference API.md Endpoints, contracts, examples
API Security API_SECURITY.md Auth, RBAC, permissions
Database Schema DATABASE.md Tables, ERD, migrations
DevOps DEVOPS.md Infrastructure, deployment, diagrams
Test Users TEST_USERS.md Credenciais de teste por role
Roadmap ROADMAP.md Product direction
Tasks TASKS.md Task tracking
Workflows WORKFLOWS.md Deployment workflows
Backend ../backend/BACKEND.md Go API details
Frontend ../frontend/FRONTEND.md Next.js details
Backoffice ../backoffice/BACKOFFICE.md NestJS details
Seeder ../seeder-api/SEEDER-API.md Database seeding & test data