docs: comprehensive documentation update

- DATABASE.md: Complete schema with ER diagram, all tables, migrations history
- ROADMAP.md: Project status, completed/in-progress/backlog items
- TASKS.md: Detailed task list to avoid rework
- README.md: Added documentation links table
- backoffice/README.md: Added auth section (JWT Bearer + Cookie)

Schema notes:
- Core tables use SERIAL (INT): users, companies, jobs
- Newer tables use UUID v4: notifications, tickets, payments
- Schema is unified (removed core_* redundant tables)
This commit is contained in:
Tiago Yamamoto 2025-12-24 11:12:52 -03:00
parent 7d99e77468
commit 017a34c965
5 changed files with 803 additions and 221 deletions

View file

@ -220,8 +220,17 @@ Acesse a documentação interativa em: **http://localhost:8521/docs/index.html**
### Modelagem de Banco ### Modelagem de Banco
Veja a documentação completa do banco de dados em: [docs/DATABASE.md](docs/DATABASE.md) Veja a documentação completa do banco de dados em: [docs/DATABASE.md](docs/DATABASE.md)
### Roadmap ### Roadmap & Tarefas
Acompanhe o desenvolvimento do projeto em: [ROADMAP.md](ROADMAP.md) - 🗺️ **Roadmap:** [docs/ROADMAP.md](docs/ROADMAP.md) - Status e progresso do projeto
- 📋 **Tarefas:** [docs/TASKS.md](docs/TASKS.md) - Lista detalhada para evitar retrabalho
### Documentação por Componente
| Componente | Documentação |
|------------|--------------|
| **Backend** | [backend/README.md](backend/README.md) |
| **Frontend** | [frontend/README.md](frontend/README.md) |
| **Backoffice** | [backoffice/README.md](backoffice/README.md) |
| **Seeder** | [seeder-api/README.md](seeder-api/README.md) |
### Endpoints Principais ### Endpoints Principais

View file

@ -9,6 +9,16 @@ GoHorse Jobs SaaS Administration and Subscription Management API.
- 👥 **User Management** - Admin controls for users - 👥 **User Management** - Admin controls for users
- 🏢 **Company Management** - Tenant administration - 🏢 **Company Management** - Tenant administration
- 📋 **Subscription Plans** - Monthly/yearly plans - 📋 **Subscription Plans** - Monthly/yearly plans
- 🔐 **JWT Authentication** - Bearer token and Cookie support
## Authentication
The backoffice supports **two authentication methods**:
1. **Bearer Token** - `Authorization: Bearer <token>`
2. **JWT Cookie** - `jwt=<token>` (fallback)
This is implemented in `src/auth/jwt-auth.guard.ts`.
## Tech Stack ## Tech Stack
@ -16,6 +26,7 @@ GoHorse Jobs SaaS Administration and Subscription Management API.
- TypeScript - TypeScript
- Stripe SDK - Stripe SDK
- Swagger (OpenAPI) - Swagger (OpenAPI)
- JWT (jsonwebtoken)
## Getting Started ## Getting Started

View file

@ -1,46 +1,69 @@
# Database Schema Documentation # 🗄️ Database Schema Documentation
This document outlines the database schema for the GoHorseJobs platform. Complete database documentation for the GoHorseJobs platform.
## Entity Relationship Diagram > **Last Updated:** 2024-12-24
> **Database:** PostgreSQL 15+
> **ID Strategy:** SERIAL (INT) for core tables, UUID v4 for newer tables
---
## 📊 Entity Relationship Diagram
```mermaid ```mermaid
erDiagram erDiagram
%% Core Entities
users ||--o{ user_companies : "belongs to"
users ||--o{ user_roles : "has roles"
users ||--o{ applications : "submits"
users ||--o{ favorite_jobs : "saves"
users ||--o{ notifications : "receives"
companies ||--o{ user_companies : "has members"
companies ||--o{ jobs : "posts"
jobs ||--o{ applications : "receives"
jobs ||--o{ favorite_jobs : "saved by"
jobs ||--o{ job_payments : "has payments"
regions ||--o{ cities : "contains"
regions ||--o{ companies : "located in"
regions ||--o{ jobs : "located in"
%% Entities
users { users {
int id PK int id PK "SERIAL"
varchar identifier UK varchar identifier UK "login"
varchar password_hash varchar password_hash
varchar role varchar role "enum"
varchar full_name varchar full_name
varchar language varchar email
boolean active varchar name
timestamp created_at int tenant_id FK "nullable"
timestamp updated_at varchar status
timestamp last_login_at }
user_roles {
int user_id PK,FK
varchar role PK "composite key"
} }
companies { companies {
int id PK int id PK "SERIAL"
varchar name varchar name
varchar slug UK varchar slug UK
varchar type varchar type
varchar document varchar document
varchar address text address
int region_id FK int region_id FK
int city_id FK
varchar phone
varchar email varchar email
varchar website varchar website
varchar logo_url
text description
boolean active
boolean verified boolean verified
timestamp created_at boolean active
timestamp updated_at
} }
jobs { jobs {
int id PK int id PK "SERIAL"
int company_id FK int company_id FK
int created_by FK int created_by FK
varchar title varchar title
@ -51,263 +74,550 @@ erDiagram
varchar currency varchar currency
varchar employment_type varchar employment_type
varchar work_mode varchar work_mode
varchar working_hours
varchar location
int region_id FK
int city_id FK
jsonb requirements
jsonb benefits
boolean visa_support
varchar language_level
varchar status varchar status
boolean is_featured boolean is_featured
timestamp created_at
timestamp updated_at
} }
applications { applications {
int id PK int id PK "SERIAL"
int job_id FK int job_id FK
int user_id FK int user_id FK "nullable"
varchar name varchar status
varchar email
varchar phone
varchar line_id
varchar whatsapp
text message text message
varchar resume_url varchar resume_url
jsonb documents
varchar status
text notes
timestamp created_at
timestamp updated_at
} }
regions { regions {
int id PK int id PK "SERIAL"
varchar name varchar name
varchar country_code varchar country_code
varchar code varchar code
} }
cities { cities {
int id PK int id PK "SERIAL"
int region_id FK int region_id FK
varchar name varchar name
} }
user_companies { notifications {
int id PK uuid id PK
int user_id FK int user_id FK
int company_id FK varchar type
varchar role varchar title
jsonb permissions text message
} boolean read
favorite_jobs {
int id PK
int user_id FK
int job_id FK
} }
job_payments { job_payments {
uuid id PK uuid id PK
uuid job_id FK int job_id FK
uuid user_id FK int user_id FK
varchar stripe_session_id
varchar stripe_payment_intent
decimal amount decimal amount
varchar currency
varchar status varchar status
varchar billing_type varchar stripe_session_id
varchar billing_name
varchar billing_email
int duration_days
timestamp created_at
timestamp paid_at
} }
job_posting_prices {
int id PK
varchar name
decimal price
varchar currency
int duration_days
boolean is_featured
varchar stripe_price_id
boolean active
}
users ||--o{ user_companies : "belongs to"
companies ||--o{ user_companies : "has members"
companies ||--o{ jobs : "posts"
users ||--o{ jobs : "creates"
jobs ||--o{ applications : "receives"
users ||--o{ applications : "submits"
jobs ||--o{ job_payments : "has payment"
companies ||--o{ user_companies : "has members"
companies ||--o{ jobs : "posts"
users ||--o{ jobs : "creates"
jobs ||--o{ applications : "receives"
users ||--o{ applications : "submits"
regions ||--o{ cities : "contains"
regions ||--o{ companies : "located in"
cities ||--o{ companies : "located in"
regions ||--o{ jobs : "located in"
cities ||--o{ jobs : "located in"
users ||--o{ favorite_jobs : "saves"
jobs ||--o{ favorite_jobs : "saved by"
``` ```
## Core Tables ---
### Users (`users`) ## 🏗️ Table Overview
Represents system users including Candidates, Recruiters, and Admins.
| Column | Type | Description | | Table | ID Type | Description | Migration |
|--------|------|-------------| |-------|---------|-------------|-----------|
| id | INTEGER | Primary key | | `users` | SERIAL | System users (candidates, recruiters, admins) | 001 |
| identifier | VARCHAR | Unique, Email or Username | | `user_roles` | Composite | Additional roles per user | 020 |
| password_hash | VARCHAR | Bcrypt hash | | `companies` | SERIAL | Employer organizations | 002 |
| role | VARCHAR | `superadmin`, `companyAdmin`, `recruiter`, `jobSeeker` | | `user_companies` | SERIAL | User ↔ Company mapping | 003 |
| full_name | VARCHAR | Display name | | `regions` | SERIAL | States/Provinces/Prefectures | 004 |
| language | VARCHAR | Default: 'pt' | | `cities` | SERIAL | Cities within regions | 004 |
| active | BOOLEAN | Account status | | `jobs` | SERIAL | Job postings | 005 |
| created_at | TIMESTAMP | Creation time | | `applications` | SERIAL | Job applications | 006 |
| updated_at | TIMESTAMP | Last update | | `favorite_jobs` | SERIAL | Saved jobs by users | 007 |
| last_login_at | TIMESTAMP | Last login | | `password_resets` | SERIAL | Password reset tokens | 008 |
| `notifications` | UUID v4 | User notifications | 016 |
| `tickets` | UUID v4 | Support tickets | 017 |
| `ticket_messages` | UUID v4 | Ticket messages | 017 |
| `job_payments` | UUID v4 | Payment records | 019 |
| `job_posting_prices` | SERIAL | Pricing configuration | 019 |
| `login_audits` | SERIAL | Login audit trail | 013 |
| `activity_logs` | SERIAL | Activity logging | 013 |
--- ---
### Companies (`companies`) ## 📋 Core Tables
Represents employer organizations.
| Column | Type | Description | ### `users`
|--------|------|-------------|
| id | INTEGER | Primary key | System users including Candidates, Recruiters, and Admins.
| name | VARCHAR | Company name |
| slug | VARCHAR | URL-friendly identifier | ```sql
| type | VARCHAR | Company type | CREATE TABLE users (
| document | VARCHAR | Houjin Bangou / CNPJ | id SERIAL PRIMARY KEY,
| address | VARCHAR | Physical address | identifier VARCHAR(100) UNIQUE NOT NULL, -- Login (username/email)
| region_id | INTEGER | FK → regions.id | password_hash VARCHAR(255) NOT NULL,
| city_id | INTEGER | FK → cities.id | role VARCHAR(20) NOT NULL, -- 'superadmin'|'companyAdmin'|'recruiter'|'jobSeeker'
| phone, email, website | VARCHAR | Contact info |
| logo_url | VARCHAR | Logo image URL | -- Profile
| description | TEXT | Company description | full_name VARCHAR(255),
| active | BOOLEAN | Active status | email VARCHAR(255),
| verified | BOOLEAN | Verification status | name VARCHAR(255),
phone VARCHAR(30),
-- Candidate Profile Fields (015)
city VARCHAR(100),
state VARCHAR(50),
title VARCHAR(100),
experience VARCHAR(100),
skills TEXT[],
bio TEXT,
objective TEXT,
-- Multi-tenancy (020)
tenant_id INT REFERENCES companies(id),
status VARCHAR(20) DEFAULT 'active',
-- Settings
language VARCHAR(5) DEFAULT 'en',
active BOOLEAN DEFAULT true,
-- Timestamps
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login_at TIMESTAMP
);
```
**Roles:**
- `superadmin` - Platform administrator
- `companyAdmin` - Company administrator
- `recruiter` - Job poster/recruiter
- `jobSeeker` - Candidate/job seeker
--- ---
### Jobs (`jobs`) ### `user_roles`
Represents job postings.
| Column | Type | Description | Additional roles per user (for multi-role support).
|--------|------|-------------|
| id | INTEGER | Primary key | ```sql
| company_id | INTEGER | FK → companies.id | CREATE TABLE user_roles (
| created_by | INTEGER | FK → users.id | user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
| title | VARCHAR | Job title | role VARCHAR(50) NOT NULL,
| description | TEXT | Full job description | PRIMARY KEY (user_id, role)
| salary_min | DECIMAL | Minimum salary | );
| salary_max | DECIMAL | Maximum salary | ```
| salary_type | VARCHAR | `hourly`, `daily`, `weekly`, `monthly`, `yearly` |
| currency | VARCHAR | `BRL`, `USD`, `EUR`, `GBP`, `JPY` |
| employment_type | VARCHAR | `full-time`, `part-time`, `contract`, `temporary`, `training`, `voluntary`, `permanent`, `dispatch` |
| work_mode | VARCHAR | `onsite`, `hybrid`, `remote` |
| working_hours | VARCHAR | e.g. "9:00-18:00" |
| location | VARCHAR | Location string |
| region_id | INTEGER | FK → regions.id |
| city_id | INTEGER | FK → cities.id |
| requirements | JSONB | Skills/requirements array |
| benefits | JSONB | Benefits array |
| visa_support | BOOLEAN | Visa sponsorship |
| language_level | VARCHAR | `N5`, `N4`, `N3`, `N2`, `N1`, `beginner`, `none` |
| status | VARCHAR | `draft`, `open`, `closed`, `published`, `paused`, `expired`, `archived`, `reported`, `review` |
| is_featured | BOOLEAN | Featured job flag |
--- ---
### Applications (`applications`) ### `companies`
Represents job applications.
| Column | Type | Description | Employer organizations that post jobs.
|--------|------|-------------|
| id | INTEGER | Primary key | ```sql
| job_id | INTEGER | FK → jobs.id | CREATE TABLE companies (
| user_id | INTEGER | FK → users.id (nullable for guests) | id SERIAL PRIMARY KEY,
| name | VARCHAR | Applicant name | name VARCHAR(255) NOT NULL,
| email | VARCHAR | Contact email | slug VARCHAR(255) UNIQUE NOT NULL, -- URL-friendly name
| phone | VARCHAR | Phone number | type VARCHAR(50) DEFAULT 'company', -- 'company'|'agency'|'system'
| line_id | VARCHAR | LINE ID | document VARCHAR(100), -- CNPJ/Tax ID
| whatsapp | VARCHAR | WhatsApp number |
| message | TEXT | Cover message | -- Location
| resume_url | VARCHAR | Resume file URL | address TEXT,
| documents | JSONB | Additional documents | region_id INT REFERENCES regions(id),
| status | VARCHAR | `pending`, `reviewed`, `shortlisted`, `rejected`, `hired` | city_id INT REFERENCES cities(id),
| notes | TEXT | Recruiter notes |
-- Contact
phone VARCHAR(30),
email VARCHAR(255),
website VARCHAR(255),
-- Branding
logo_url TEXT,
description TEXT, -- JSON or plain text
-- Status
active BOOLEAN DEFAULT true,
verified BOOLEAN DEFAULT false,
-- Timestamps
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
--- ---
## Reference Tables ### `jobs`
### Regions (`regions`) Job postings created by companies.
| Column | Type | Description |
|--------|------|-------------|
| id | INTEGER | Primary key |
| name | VARCHAR | Region name |
| country_code | VARCHAR | e.g. "JP", "BR" |
| code | VARCHAR | Region code |
### Cities (`cities`) ```sql
| Column | Type | Description | CREATE TABLE jobs (
|--------|------|-------------| id SERIAL PRIMARY KEY,
| id | INTEGER | Primary key | company_id INT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
| region_id | INTEGER | FK → regions.id | created_by INT NOT NULL REFERENCES users(id),
| name | VARCHAR | City name |
-- Job Details
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
-- Salary
salary_min DECIMAL(12,2),
salary_max DECIMAL(12,2),
salary_type VARCHAR(20), -- 'hourly'|'daily'|'weekly'|'monthly'|'yearly'
currency VARCHAR(3), -- 'BRL'|'USD'|'EUR'|'GBP'|'JPY'
-- Employment
employment_type VARCHAR(30), -- 'full-time'|'part-time'|'contract'|'dispatch'|...
work_mode VARCHAR(10), -- 'onsite'|'hybrid'|'remote'
working_hours VARCHAR(100),
-- Location
location VARCHAR(255),
region_id INT REFERENCES regions(id),
city_id INT REFERENCES cities(id),
-- Requirements & Benefits
requirements JSONB, -- Array of skills/requirements
benefits JSONB, -- Array of benefits
-- Visa & Language
visa_support BOOLEAN DEFAULT false,
language_level VARCHAR(20), -- 'N5'|'N4'|'N3'|'N2'|'N1'|'beginner'|'none'
-- Status
status VARCHAR(20) DEFAULT 'open', -- 'draft'|'open'|'closed'|'published'|...
is_featured BOOLEAN DEFAULT false,
-- Timestamps
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
**Status Values:**
- `draft` - Not published yet
- `open` - Accepting applications
- `published` - Live and visible
- `paused` - Temporarily hidden
- `closed` - No longer accepting
- `expired` - Past expiration date
- `archived` - Archived by employer
- `reported` - Flagged for review
- `review` - Under admin review
--- ---
## Junction Tables ### `applications`
Job applications from candidates.
```sql
CREATE TABLE applications (
id SERIAL PRIMARY KEY,
job_id INT NOT NULL REFERENCES jobs(id) ON DELETE CASCADE,
user_id INT REFERENCES users(id), -- Nullable for guest applications
-- Applicant Info
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
phone VARCHAR(30),
line_id VARCHAR(100),
whatsapp VARCHAR(30),
-- Application Content
message TEXT,
resume_url VARCHAR(500),
documents JSONB,
-- Status
status VARCHAR(20) DEFAULT 'pending', -- 'pending'|'reviewed'|'shortlisted'|'rejected'|'hired'
notes TEXT, -- Recruiter notes
-- Timestamps
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
---
## 🌍 Geographic Tables
### `regions`
States, provinces, or prefectures.
```sql
CREATE TABLE regions (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
country_code VARCHAR(2) NOT NULL, -- 'BR'|'US'|'JP'
code VARCHAR(10) NOT NULL -- 'SP'|'CA'|'13'
);
```
**Seeded Regions:**
- 🇧🇷 Brazil: São Paulo (SP), Rio de Janeiro (RJ), Minas Gerais (MG)
- 🇺🇸 USA: California (CA), New York (NY), Texas (TX)
- 🇯🇵 Japan: Tokyo (13), Osaka (27)
---
### `cities`
Cities within regions.
```sql
CREATE TABLE cities (
id SERIAL PRIMARY KEY,
region_id INT NOT NULL REFERENCES regions(id),
name VARCHAR(100) NOT NULL
);
```
---
## 💰 Payment Tables
### `job_payments` (UUID)
Payment records for job postings.
```sql
CREATE TABLE job_payments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
job_id INT NOT NULL REFERENCES jobs(id) ON DELETE CASCADE,
user_id INT REFERENCES users(id) ON DELETE SET NULL,
-- Stripe
stripe_session_id VARCHAR(255),
stripe_payment_intent VARCHAR(255),
stripe_customer_id VARCHAR(255),
-- Amount
amount DECIMAL(12,2) NOT NULL,
currency VARCHAR(3) DEFAULT 'USD',
-- Status
status VARCHAR(20) DEFAULT 'pending', -- 'pending'|'completed'|'failed'|'refunded'|'expired'
-- Billing
billing_type VARCHAR(20), -- 'company'|'individual'
billing_name VARCHAR(255),
billing_email VARCHAR(255),
-- Job Details
duration_days INT DEFAULT 30,
is_featured BOOLEAN DEFAULT false,
-- Timestamps
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
paid_at TIMESTAMP,
expires_at TIMESTAMP
);
```
---
### `job_posting_prices`
Pricing configuration for job postings.
```sql
CREATE TABLE job_posting_prices (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
price DECIMAL(12,2) NOT NULL,
currency VARCHAR(3) DEFAULT 'USD',
duration_days INT DEFAULT 30,
is_featured BOOLEAN DEFAULT false,
stripe_price_id VARCHAR(255),
active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
---
## 🔔 Notification Tables
### `notifications` (UUID)
User notifications.
```sql
CREATE TABLE notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
type VARCHAR(50),
title VARCHAR(255),
message TEXT,
read BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
---
## 🎫 Support Tables
### `tickets` (UUID)
Support tickets.
```sql
CREATE TABLE tickets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id INT NOT NULL,
subject VARCHAR(255) NOT NULL,
status VARCHAR(20) DEFAULT 'open', -- 'open'|'in_progress'|'resolved'|'closed'
priority VARCHAR(10) DEFAULT 'medium', -- 'low'|'medium'|'high'|'urgent'
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### `ticket_messages` (UUID)
Messages within tickets.
```sql
CREATE TABLE ticket_messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
ticket_id UUID NOT NULL REFERENCES tickets(id) ON DELETE CASCADE,
user_id INT NOT NULL,
message TEXT NOT NULL,
is_staff BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
---
## 📝 Audit Tables
### `login_audits`
Login attempt tracking.
```sql
CREATE TABLE login_audits (
id SERIAL PRIMARY KEY,
user_id INT,
identifier VARCHAR(100),
success BOOLEAN,
ip_address VARCHAR(45),
user_agent TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### `activity_logs`
General activity logging.
```sql
CREATE TABLE activity_logs (
id SERIAL PRIMARY KEY,
user_id INT,
entity_type VARCHAR(50),
entity_id INT,
action VARCHAR(50),
details JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
---
## 🔗 Junction Tables
### `user_companies`
### User Companies (`user_companies`)
Maps users to companies (N:M relationship). Maps users to companies (N:M relationship).
| Column | Type | Description | ```sql
|--------|------|-------------| CREATE TABLE user_companies (
| id | INTEGER | Primary key | id SERIAL PRIMARY KEY,
| user_id | INTEGER | FK → users.id | user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
| company_id | INTEGER | FK → companies.id | company_id INT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
| role | VARCHAR | `companyAdmin`, `recruiter` | role VARCHAR(30) DEFAULT 'recruiter', -- 'companyAdmin'|'recruiter'
| permissions | JSONB | Custom permissions | permissions JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, company_id)
);
```
### Favorite Jobs (`favorite_jobs`) ### `favorite_jobs`
| Column | Type | Description |
|--------|------|-------------| Saved jobs by users.
| id | INTEGER | Primary key |
| user_id | INTEGER | FK → users.id | ```sql
| job_id | INTEGER | FK → jobs.id | CREATE TABLE favorite_jobs (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
job_id INT NOT NULL REFERENCES jobs(id) ON DELETE CASCADE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, job_id)
);
```
--- ---
## Audit Tables ## 🔄 Migrations History
### Login Audits (`login_audits`) | # | File | Description |
| Column | Type | Description | |---|------|-------------|
|--------|------|-------------| | 001 | `001_create_users_table.sql` | Core users table |
| id | INTEGER | Primary key | | 002 | `002_create_companies_table.sql` | Companies/employers |
| user_id | VARCHAR | User identifier | | 003 | `003_create_user_companies_table.sql` | User ↔ Company mapping |
| identifier | VARCHAR | Login identifier used | | 004 | `004_create_prefectures_cities_tables.sql` | Geographic data |
| ip_address | VARCHAR | Client IP | | 005 | `005_create_jobs_table.sql` | Job postings |
| user_agent | VARCHAR | Browser/client info | | 006 | `006_create_applications_table.sql` | Job applications |
| created_at | TIMESTAMP | Login time | | 007 | `007_create_favorite_jobs_table.sql` | Saved jobs |
| 008 | `008_create_password_resets_table.sql` | Password reset tokens |
| 010 | `010_seed_super_admin.sql` | Default superadmin |
| 011 | `011_add_is_featured_to_jobs.sql` | Featured jobs flag |
| 012 | `012_add_work_mode.sql` | Work mode column |
| 013 | `013_create_backoffice_tables.sql` | Audit tables |
| 014 | `014_update_job_status_constraint.sql` | Status enum update |
| 015 | `015_add_candidate_profile_fields.sql` | Candidate profile |
| 016 | `016_create_notifications_table.sql` | Notifications |
| 017 | `017_create_tickets_table.sql` | Support tickets |
| 018 | `018_add_currency_to_jobs.sql` | Currency support |
| 019 | `019_create_job_payments_table.sql` | Payment tracking |
| 020 | `020_unify_schema.sql` | Schema unification |
| 999 | `999_fix_gohorse_schema.sql` | Schema fixes |
### Password Resets (`password_resets`) ---
| Column | Type | Description |
|--------|------|-------------| ## ⚠️ ID Strategy Notes
| id | INTEGER | Primary key |
| user_id | INTEGER | FK → users.id | The database uses a **hybrid ID strategy**:
| token | VARCHAR | Reset token |
| expires_at | TIMESTAMP | Token expiry | | Strategy | Tables | Rationale |
| used | BOOLEAN | Token used status | |----------|--------|-----------|
| **SERIAL (INT)** | users, companies, jobs, applications, regions, cities | Legacy tables, simpler, faster |
| **UUID v4** | notifications, tickets, job_payments | Newer tables, distributed-friendly |
> **Note:** The system does NOT use UUID v7 (time-ordered UUIDs). It uses PostgreSQL's `gen_random_uuid()` which generates UUID v4.
---
## 🔒 Security Notes
1. **Password Hashing:** BCrypt with optional `PASSWORD_PEPPER` environment variable
2. **Soft Deletes:** Not implemented (uses `CASCADE` for referential integrity)
3. **Row-Level Security:** Not implemented (uses application-level checks)
4. **Audit Trail:** `login_audits` and `activity_logs` for compliance
---
## 📚 Related Documentation
- [Backend README](../backend/README.md) - API documentation
- [Seeder README](../seeder-api/README.md) - Database seeding
- [Backoffice README](../backoffice/README.md) - Admin panel

155
docs/ROADMAP.md Normal file
View file

@ -0,0 +1,155 @@
# 🗺️ GoHorse Jobs - Roadmap
Roadmap de desenvolvimento do projeto GoHorse Jobs.
> **Última Atualização:** 2024-12-24
> **Branch Atual:** `dev`
---
## 📊 Status Geral
| Área | Progresso | Status |
|------|-----------|--------|
| **Backend API** | 85% | 🟢 Funcional |
| **Frontend** | 75% | 🟡 Em desenvolvimento |
| **Backoffice** | 60% | 🟡 Em desenvolvimento |
| **Seeder** | 95% | 🟢 Completo |
| **Documentação** | 70% | 🟡 Em progresso |
---
## ✅ Concluído
### Backend
- [x] Estrutura Clean Architecture
- [x] Autenticação JWT com HttpOnly cookies
- [x] CRUD de usuários, empresas, vagas
- [x] Sistema de candidaturas
- [x] Notificações
- [x] Password reset
- [x] XSS sanitization middleware
- [x] Swagger documentation
- [x] Multi-tenancy básico
- [x] PASSWORD_PEPPER para hash seguro
- [x] 🆕 Schema unificado (eliminado core_*)
### Frontend
- [x] Login/Logout com cookies
- [x] Dashboard candidato
- [x] Dashboard empresa
- [x] Listagem de vagas
- [x] Detalhes da vaga
- [x] Candidatura a vaga
- [x] Eye icon toggle de senha
- [x] Responsividade básica
- [x] Sonner para notificações
### Seeder
- [x] 31 empresas (30 tech + System)
- [x] 13 empresas fictícias (ACME, Stark, etc)
- [x] 1129+ vagas
- [x] Users e candidatos
- [x] Regiões (BR, US, JP)
- [x] Cidades
- [x] Notificações
- [x] 🆕 Schema unificado
### DevOps
- [x] Docker setup backend
- [x] Migrations automáticas
- [x] start.sh script unificado
- [x] Seed reset option
---
## 🔄 Em Progresso
### Backend
- [ ] Rate limiting
- [ ] Upload de arquivos (currículos)
- [ ] Busca full-text com pg_trgm
- [ ] Webhooks para integrações
- [ ] API de pagamentos (Stripe)
### Frontend
- [ ] Dashboard admin completo
- [ ] Gestão de candidaturas
- [ ] Filtros avançados de vagas
- [ ] Favoritos (bookmark jobs)
- [ ] Perfil do candidato editável
- [ ] Upload de currículo
- [ ] PWA / Offline support
### Backoffice
- [ ] Gestão de tenants
- [ ] Gestão de usuários
- [ ] Relatórios
- [ ] Auditoria
- [ ] Moderação de vagas
---
## 📋 Backlog
### Alta Prioridade
- [ ] Email transacional (welcome, reset, application)
- [ ] Integração Stripe completa
- [ ] Busca avançada com filtros
- [ ] Internacionalização (i18n)
- [ ] Testes E2E frontend
### Média Prioridade
- [ ] OAuth (Google, LinkedIn)
- [ ] Notificações push (web)
- [ ] Chat em tempo real
- [ ] Analytics dashboard
- [ ] Export CSV/Excel
### Baixa Prioridade
- [ ] App mobile (React Native)
- [ ] Integração ATS
- [ ] AI matching (job ↔ candidate)
- [ ] Video interviews
---
## 🐛 Bugs Conhecidos
| ID | Descrição | Prioridade | Status |
|----|-----------|------------|--------|
| #001 | job_payments FK precisa de migration 019 atualizada | Média | 🟡 Pendente |
| #002 | Swagger docs desatualizado em alguns endpoints | Baixa | 🟡 Pendente |
---
## 📁 Estrutura de Documentação
```
docs/
├── DATABASE.md # Schema completo
├── ROADMAP.md # Este arquivo
├── TASKS.md # Tarefas pendentes detalhadas
└── ARCHITECTURE.md # (futuro) Arquitetura detalhada
backend/
└── README.md # Documentação da API
backoffice/
└── README.md # Documentação do backoffice
seeder-api/
└── README.md # Documentação do seeder
frontend/
└── README.md # Documentação do frontend
```
---
## 🔗 Links Úteis
- **API Docs:** http://localhost:8521/docs/index.html
- **Frontend:** http://localhost:3000
- **Database Schema:** [docs/DATABASE.md](DATABASE.md)
- **Seeder Info:** [seeder-api/README.md](../seeder-api/README.md)

97
docs/TASKS.md Normal file
View file

@ -0,0 +1,97 @@
# 📋 GoHorse Jobs - Tarefas
Lista detalhada de tarefas para evitar retrabalho.
> **Última Atualização:** 2024-12-24
---
## 🔥 Sprint Atual (Dezembro 2024)
### Backend
- [ ] Corrigir migration 019 (job_payments FK)
- [ ] Atualizar Swagger docs
- [ ] Adicionar testes para novos endpoints
- [ ] Implementar rate limiting
### Frontend
- [ ] Página de perfil editável
- [ ] Upload de currículo
- [ ] Filtros avançados na listagem de vagas
- [ ] Página de favoritos
### Documentação
- [x] DATABASE.md - Schema completo
- [x] ROADMAP.md - Este arquivo
- [x] TASKS.md - Tarefas
- [ ] ARCHITECTURE.md - Arquitetura detalhada
- [ ] API.md - Endpoints detalhados
---
## ✅ Recentemente Concluído
### 2024-12-24
- [x] **Schema Unification** - Eliminado tabelas core_* redundantes
- Removido `core_companies`, `core_users`, `core_user_roles`
- Unificado em `companies`, `users`, `user_roles`
- Atualizado 11 arquivos (migrations, repositories, seeders)
- [x] **start.sh Updates**
- Opção 4: Run migrations (Node.js)
- Opção 6: Reset + Migrate + Seed completo
- [x] **Migration Runner**
- Criado `seeder-api/src/migrate.js`
- Suporte a erros de tabelas existentes
- [x] **Documentação**
- DATABASE.md reescrito completo
- ROADMAP.md criado
- TASKS.md criado
### 2024-12-23
- [x] JWT Auth Guard no backoffice (Bearer + Cookie)
- [x] PASSWORD_PEPPER integration
- [x] Frontend auth improvements
- [x] seeder-api README atualizado
---
## 🚧 Não Fazer (Evitar Retrabalho)
> ⚠️ **IMPORTANTE:** Estas tarefas NÃO devem ser feitas pois já foram resolvidas ou descartadas.
| Tarefa | Motivo |
|--------|--------|
| Criar core_companies | REMOVIDO - Usar `companies` |
| Criar core_users | REMOVIDO - Usar `users` |
| Usar UUID para users/jobs | MANTIDO SERIAL - Decisão arquitetural |
| psql para migrations | REMOVIDO - Usar `npm run migrate` |
---
## 📝 Notas de Implementação
### IDs do Banco
- **SERIAL (INT):** users, companies, jobs, applications, regions, cities
- **UUID v4:** notifications, tickets, job_payments
- **NÃO usar UUID v7** - Não suportado pelo gen_random_uuid()
### Autenticação
- Backend: JWT em HttpOnly cookie OU Authorization header
- Frontend: Usa cookies automaticamente
- Backoffice: Suporta ambos (Bearer e Cookie)
### Senhas
- BCrypt com 10 rounds
- PASSWORD_PEPPER obrigatório em produção
- Hash: `bcrypt.hash(password + PEPPER, 10)`
---
## 🔗 Referências
- [DATABASE.md](DATABASE.md) - Schema do banco
- [ROADMAP.md](ROADMAP.md) - Roadmap geral
- [seeder-api/README.md](../seeder-api/README.md) - Como popular dados