- fix(seeder): add PASSWORD_PEPPER to all bcrypt hashes (admin + candidates/recruiters)
- fix(seeder): add created_by field to jobs INSERT (was causing NOT NULL violation)
- feat(backend): add custom job questions support in applications
- feat(backend): add payment handler and Stripe routes
- feat(frontend): add navbar and footer to /register and /register/user pages
- feat(frontend): add custom question answers to job apply page
- feat(frontend): update home page hero section and navbar buttons
- feat(frontend): update auth/api lib with new endpoints
- chore(db): add migration 045 for application answers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Update ListConfiguredServices to use correct service names
- Add fcm_service_account, appwrite, smtp to BootstrapCredentials
- Remove unused payment_gateway from frontend schema
- Rename firebase to fcm_service_account in frontend
- Remove duplicate setLoading calls in loadBackoffice
- Add proper error handling with catch for all API calls
- Wrap useEffect initialization in try/catch/finally
- Move backoffice functionality into settings page as new tab
- Remove standalone backoffice page and sidebar link
- Add edit/delete buttons for credentials management
- Update credentials service to allow overwriting existing credentials
- Add API documentation for system credentials endpoints
jobs/page.tsx:
- Edit dialog now exposes all UpdateJobRequest fields: employmentType,
workMode, salaryMin/max/type/currency, salaryNegotiable, languageLevel,
visaSupport, location, status, isFeatured, description
- Fix AdminJob type to include all JobWithCompany fields returned by API
- Fix jobRows mapping that was hardcoding location/type/workMode/isFeatured
- Add isFeatured to CreateJobPayload type
applications/page.tsx:
- Fix status mismatch: reviewing→reviewed, interview→shortlisted, accepted→hired
- Align statusConfig labels/keys with backend constraint (pending/reviewed/
shortlisted/rejected/hired)
- Update stats counters to use corrected status keys
companies/page.tsx:
- Add logoUrl and yearsInMarket to create and edit forms
- Populate editFormData from company object on edit open
- Send logoUrl/yearsInMarket in update payload
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The countQuery was missing LEFT JOIN companies c, causing a PostgreSQL
error when the search filter referenced c.name ILIKE. This made every
keyword search return a 500 error instead of results.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add workMode, languageLevel, visaSupport, salaryNegotiable to form
- Add all 10 currency options and all 8 employment types (including dispatch/voluntary)
- Add status selector (draft/review/open/paused/closed)
- Add location autocomplete with country dropdown and city/region search
- Add application channel (email/url/phone) with conditional inputs
- Add resumeRequirement selector and requirements map in payload
- Load companies via adminCompaniesApi (no registration — user is already logged in)
- Extend CreateJobPayload type with workMode, cityId, regionId, languageLevel,
visaSupport, requirements, expanded currency and status options
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both routes are fully replaced by /jobs/new. Deleted directories entirely
instead of keeping redirects.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Consolidates the two public job posting routes into the single canonical
flow at /jobs/new. The /publicar-vaga route already redirected there.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Frontend (jobs/new):
- Replace isValidCNPJ (checksum algorithm) with isValidDocument: accepts
any tax document with 5–30 alphanumeric chars (CNPJ, EIN, VAT, etc.)
- Add cleanPhone(): strips formatting chars (dashes, spaces, parens) and
keeps only digits + optional leading '+'; replaces cleanDigits+prepend
- Phone sent as '+5511999998888' if user typed '+55...', or '11999998888'
if no country code was provided — no '+' blindly prepended anymore
- Company document sent stripped of all non-alphanumeric before API call
- Update label placeholder from '00.000.000/0000-00' to 'CNPJ, EIN, VAT...'
- Rename error key invalidCnpj → invalidDocument in all 3 locales (pt, en, es)
Backend (create_company use case):
- Add SanitizePhone() to utils/sanitizer.go: strips all non-digit chars
except a leading '+'; '(11) 99999-8888' → '11999998888'
- Apply SanitizePhone to input.Phone before persisting to DB
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace free-text location input with debounced autocomplete
- On country select, fetch its numeric ID from /api/v1/locations/countries
and use it to scope the search results to that country
- Typing ≥2 chars in location field triggers GET /api/v1/locations/search
with 350ms debounce; results show city (blue) and state (green) badges
- On result selection, stores cityId + regionId and sets the display label
to "Name, Region" format; IDs are included in the job creation payload
- Spinner shown while searching; dropdown closes on outside click / select
- CEP search button preserved alongside the autocomplete
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add password + confirm-password fields to billing step (Step 3) so the
recruiter creates their account credentials during the job posting flow
- Validate password length (≥8) and confirmation match before proceeding
- Extract company `id` from POST /auth/register/company response and send
it as `companyId` in the job creation payload (was missing — caused 400)
- Pass `contact` (full name) to company registration endpoint
- Remove hardcoded "Temp@123456" password; use the user-provided one
- Remove hardcoded "+55" phone prefix; send raw digits with "+" prefix
- Add translations (pt-BR, en, es) for password fields and error messages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add validateCreateJobRequest() checking required fields (companyId,
title ≥5 chars, description ≥20 chars) and enum values
(employmentType, workMode, status) before hitting the DB
- Catch *pq.Error in handler: check_violation (23514) and
foreign_key_violation (23503) now return 400; unique_violation (23505)
returns 409; other DB errors return 500 without leaking raw pq messages
- Fix test fixtures: description and companyId now meet validation
requirements
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Antes: 010_seed_super_admin.sql tinha hash bcrypt fixo amarrado a um pepper
específico. Qualquer mudança no PASSWORD_PEPPER quebrava todos os logins
silenciosamente após reset do banco.
Agora:
- migration 010: insere superadmin com placeholder inválido + force_change_password.
ON CONFLICT DO NOTHING preserva o hash se o seeder já rodou.
- seeder users.js: faz upsert de 'lol' com bcrypt(senha + env.PASSWORD_PEPPER)
em runtime. Mudar o pepper e re-rodar o seeder é suficiente para atualizar
as credenciais sem tocar em nenhuma migration.
- docs/AGENTS.md: atualiza gotcha #1 explicando o novo fluxo migrate → seed
- docs/DEVOPS.md: fix opção 1 do troubleshooting inclui re-deploy do seeder
Fluxo correto após reset do banco (coberto pelo start.sh opções 2, 6, 8):
npm run migrate → superadmin criado, hash = placeholder
npm run seed → hash recalculado com PEPPER do ambiente, status = active
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>