- Create docs/AGENTS.md for AI assistants context - Create docs/WORKFLOWS.md consolidating deployment workflows - Remove redundant docs/root/ folder - Remove .agent/ folder (consolidated into docs/) - Update dates in all documentation files - Simplify README.md documentation section
336 lines
14 KiB
Markdown
Executable file
336 lines
14 KiB
Markdown
Executable file
# Backend - GoHorse Jobs API
|
|
|
|
[](https://golang.org/)
|
|
[](https://postgresql.org/)
|
|
|
|
> **Last Updated:** 2026-02-16
|
|
|
|
API REST desenvolvida em Go seguindo princípios de **Clean Architecture** e **DDD**.
|
|
|
|
---
|
|
|
|
## 🏗️ Arquitetura
|
|
|
|
```
|
|
backend/
|
|
├── cmd/
|
|
│ ├── api/ # Entrypoint principal
|
|
│ └── manual_migrate/ # Migration runner
|
|
│
|
|
├── internal/
|
|
│ ├── api/ # Clean Architecture Layer
|
|
│ │ ├── handlers/ # HTTP Handlers (Admin, Auth, Settings, Storage, Tickets)
|
|
│ │ └── middleware/ # Auth, CORS, Rate Limiting, Sanitize
|
|
│ │
|
|
│ ├── core/ # Domain Layer (DDD)
|
|
│ │ ├── domain/entity/ # Entidades (User, Company, Email)
|
|
│ │ ├── ports/ # Interfaces (Repositories)
|
|
│ │ └── usecases/ # Casos de uso (Auth, Register)
|
|
│ │
|
|
│ ├── infrastructure/ # Infrastructure Layer
|
|
│ │ ├── auth/ # JWT Service implementation
|
|
│ │ └── persistence/ # Repository implementations (Postgres)
|
|
│ │
|
|
│ ├── services/ # Business logic services (Email, Notification, Tickets)
|
|
│ │
|
|
│ ├── dto/ # Data Transfer Objects
|
|
│ ├── models/ # GORM models (Legacy/Transition)
|
|
│ ├── router/ # Route configuration
|
|
│ └── utils/ # Helpers (JWT, Sanitizer)
|
|
│
|
|
├── migrations/ # SQL Migrations (30+)
|
|
├── tests/ # E2E and Integration tests
|
|
└── docs/ # Swagger documentation
|
|
```
|
|
|
|
### 📊 Diagrama de Fluxo (C4 Simplificado)
|
|
|
|
```mermaid
|
|
graph TD
|
|
Client[📱 Clients Frontend/App] -->|JSON/HTTP| Router[🚦 Router Mux]
|
|
|
|
subgraph CoreBackend [Core Backend]
|
|
Router --> Middleware[🛡️ Middleware Auth/CORS]
|
|
Middleware --> Handlers[🎮 HTTP Handlers]
|
|
Handlers --> UseCases[🧠 Services & UseCases]
|
|
UseCases --> Repos[💾 Repositories]
|
|
UseCases --> Adapters[🔌 External Adapters]
|
|
end
|
|
|
|
Repos --> DB[(🐘 PostgreSQL)]
|
|
|
|
Adapters --> Firebase[🔥 Firebase FCM]
|
|
Adapters --> LavinMQ[📨 LavinMQ]
|
|
Adapters --> Storage[☁️ S3/R2 Storage]
|
|
Adapters --> Stripe[💳 Stripe]
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Deployment & CI/CD (Forgejo)
|
|
|
|
O deployment é automatizado via **Forgejo Actions**.
|
|
|
|
### Workflow: `Deploy Backend (Dev)`
|
|
Arquivo: `.forgejo/workflows/deploy.yaml`
|
|
|
|
Este workflow é disparado automaticamente ao realizar um push para o branch `dev` com alterações na pasta `backend/`.
|
|
|
|
**Etapas do CI/CD:**
|
|
1. **Trigger:** Push no branch `dev` (apenas alterações em `backend/**`).
|
|
2. **Runner:** Executa no ambiente `docker` (verifique as labels do seu runner).
|
|
3. **SSH Action:** Conecta no servidor de desenvolvimento (Apolo) via SSH.
|
|
4. **Atualização de Código:**
|
|
* Navega até `/mnt/data/gohorsejobs` (ou caminho configurado).
|
|
* Faz `git fetch` e `git checkout dev`.
|
|
* `git pull origin dev`.
|
|
5. **Build & Restart (Podman):**
|
|
* Constrói a imagem: `podman build -t localhost/gohorsejobs-backend-dev ./backend`
|
|
* Reinicia o serviço: `sudo systemctl restart gohorsejobs-backend-dev`
|
|
* Limpeza: `podman image prune -f`
|
|
|
|
**Secrets Necessários (Forgejo):**
|
|
* `HOST`: IP do servidor.
|
|
* `USERNAME`: Usuário SSH.
|
|
* `SSH_KEY`: Chave privada SSH.
|
|
* `PORT`: Porta SSH (ex: 22).
|
|
|
|
---
|
|
|
|
## 🔧 Services
|
|
|
|
| Service | Arquivo | Descrição |
|
|
|---------|---------|-----------|
|
|
| **AdminService** | `admin_service.go` | CRUD de empresas, usuários, candidatos, tags, email templates |
|
|
| **JobService** | `job_service.go` | CRUD de vagas com filtros avançados |
|
|
| **ApplicationService** | `application_service.go` | Gestão de candidaturas |
|
|
| **TicketService** | `ticket_service.go` | **(Novo)** Sistema de tickets de suporte |
|
|
| **ChatService** | `chat_service.go` | Mensagens e conversas (Appwrite) |
|
|
| **NotificationService** | `notification_service.go` | Notificações push |
|
|
| **EmailService** | `email_service.go` | Produtor de emails via LavinMQ |
|
|
| **FCMService** | `fcm_service.go` | Firebase Cloud Messaging |
|
|
| **StorageService** | `storage_service.go` | Pre-signed URLs (S3/R2) |
|
|
| **CredentialsService** | `credentials_service.go` | **(Novo)** Gestão de credenciais criptografadas |
|
|
| **CloudflareService** | `cloudflare_service.go` | Cache purge via API |
|
|
| **SettingsService** | `settings_service.go` | System settings |
|
|
| **AppwriteService** | `appwrite_service.go` | Integração Appwrite Realtime |
|
|
| **AuditService** | `audit_service.go` | Logs de auditoria |
|
|
|
|
---
|
|
|
|
## 🔒 Segurança
|
|
|
|
### Middlewares Implementados
|
|
|
|
| Middleware | Arquivo | Descrição |
|
|
|------------|---------|-----------|
|
|
| **Auth** | `middleware/auth.go` | Validação JWT + RBAC |
|
|
| **CORS** | `middleware/cors.go` | Whitelist de origens via `CORS_ORIGINS` |
|
|
| **Rate Limiting** | `middleware/rate_limit.go` | 100 req/min por IP |
|
|
| **Security Headers** | `middleware/security_headers.go` | OWASP headers (XSS, CSP, etc.) |
|
|
| **Sanitize** | `middleware/sanitize.go` | XSS sanitization em JSON bodies |
|
|
|
|
### Autenticação
|
|
|
|
- **JWT** com expiração configurável
|
|
- **Password Pepper** via `PASSWORD_PEPPER` env var
|
|
- **HttpOnly Cookies** para refresh tokens
|
|
- **RSA Encryption** para credenciais sensíveis
|
|
|
|
---
|
|
|
|
## 📡 Endpoints (API Reference)
|
|
|
|
### 🔐 Auth & Identity
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `POST` | `/api/v1/auth/login` | Autenticação (Retorna JWT + User) | Public |
|
|
| `POST` | `/api/v1/auth/logout` | Logout (Limpa Cookie HttpOnly) | Public |
|
|
| `POST` | `/api/v1/auth/register` | Registro de Candidato | Public |
|
|
| `POST` | `/api/v1/auth/register/company` | Registro de Empresa (Cria Admin) | Public |
|
|
| `POST` | `/api/v1/tokens` | Salvar token FCM para Push | Auth |
|
|
|
|
### 👤 Users & Profiles
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/users/me` | Dados do usuário logado | Auth |
|
|
| `PATCH` | `/api/v1/users/me/profile` | Atualizar meu perfil | Auth |
|
|
| `GET` | `/api/v1/users` | Listar usuários (Admin: da empresa. Superadmin: todos) | Admin/Super |
|
|
| `POST` | `/api/v1/users` | Criar usuário (Admin: user normal. Superadmin: pode criar outros Supers) | Admin/Super |
|
|
| `GET` | `/api/v1/users/roles` | Listar roles disponíveis no sistema | Admin/Super |
|
|
| `PATCH` | `/api/v1/users/{id}` | Atualizar usuário | Admin/Super |
|
|
| `DELETE` | `/api/v1/users/{id}` | Remover usuário | Admin/Super |
|
|
|
|
### 🏢 Companies (Tenants)
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/companies` | Listar empresas (Public: simples. Admin: detalhado) | Public/Admin |
|
|
| `POST` | `/api/v1/companies` | Criar nova empresa (via auto-cadastro ou Admin) | Public |
|
|
| `GET` | `/api/v1/companies/{id}` | Detalhes da empresa | Public |
|
|
| `PATCH` | `/api/v1/companies/{id}` | Editar dados da empresa | Admin/Super |
|
|
| `PATCH` | `/api/v1/companies/{id}/status` | Alterar status (Ativo/Inativo) | Admin/Super |
|
|
| `DELETE` | `/api/v1/companies/{id}` | Remover empresa (Soft delete) | Admin/Super |
|
|
|
|
### 💼 Jobs (Vagas)
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/jobs` | Listar vagas (filtros: local, keywords) | Public |
|
|
| `GET` | `/api/v1/jobs/{id}` | Detalhes da vaga | Public |
|
|
| `POST` | `/api/v1/jobs` | Criar nova vaga | Recruiter |
|
|
| `PUT` | `/api/v1/jobs/{id}` | Editar vaga | Recruiter |
|
|
| `DELETE` | `/api/v1/jobs/{id}` | Remover vaga | Recruiter |
|
|
| `POST` | `/api/v1/jobs/{id}/duplicate` | Duplicar uma vaga existente | Admin/Recruiter |
|
|
| `GET` | `/api/v1/jobs/moderation` | Listar vagas para moderação | Admin/Super |
|
|
| `PATCH` | `/api/v1/jobs/{id}/status` | Aprovar/Rejeitar vaga | Admin/Super |
|
|
|
|
### 📝 Applications (Candidaturas)
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `POST` | `/api/v1/applications` | Candidatar-se a uma vaga | Candidate |
|
|
| `GET` | `/api/v1/applications` | Minhas candidaturas (ou recebidas, se Recruiter) | Auth |
|
|
| `GET` | `/api/v1/applications/{id}` | Detalhes da candidatura | Auth |
|
|
| `PUT` | `/api/v1/applications/{id}/status` | Atualizar fase/status | Recruiter |
|
|
| `DELETE` | `/api/v1/applications/{id}` | Desistir/Remover | Auth |
|
|
| `GET` | `/api/v1/candidates` | Listar base de candidatos (Global) | Admin/Super |
|
|
|
|
### 🎫 Support (Tickets)
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/support/tickets` | Meus tickets de suporte | Auth |
|
|
| `GET` | `/api/v1/support/tickets/all` | Todos os tickets (Visão Admin) | SuperAdmin |
|
|
| `POST` | `/api/v1/support/tickets` | Abrir novo ticket | Auth |
|
|
| `GET` | `/api/v1/support/tickets/{id}` | Ver conversa do ticket | Auth |
|
|
| `POST` | `/api/v1/support/tickets/{id}/messages` | Enviar mensagem no ticket | Auth |
|
|
| `PATCH` | `/api/v1/support/tickets/{id}/close` | Fechar ticket | Auth |
|
|
| `DELETE` | `/api/v1/support/tickets/{id}` | Remover ticket | Admin/Super |
|
|
|
|
### 💬 Chat & Messaging
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/conversations` | Listar conversas ativas | Auth |
|
|
| `GET` | `/api/v1/conversations/{id}/messages` | Ver histórico de mensagens | Auth |
|
|
| `POST` | `/api/v1/conversations/{id}/messages` | Enviar mensagem direta | Auth |
|
|
|
|
### 🔔 Notifications
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/notifications` | Listar notificações | Auth |
|
|
| `PATCH` | `/api/v1/notifications/{id}/read` | Marcar como lida | Auth |
|
|
| `PATCH` | `/api/v1/notifications/read-all` | Marcar todas como lidas | Auth |
|
|
|
|
### 🌍 Locations
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/locations/countries` | Listar países | Public |
|
|
| `GET` | `/api/v1/locations/countries/{id}/states` | Listar estados de um país | Public |
|
|
| `GET` | `/api/v1/locations/states/{id}/cities` | Listar cidades de um estado | Public |
|
|
| `GET` | `/api/v1/locations/search` | Busca textual (Cidade/Estado) | Public |
|
|
|
|
### 🏷️ Tags & Metadata
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/tags` | Listar tags (skills, benefícios) | Public |
|
|
| `POST` | `/api/v1/tags` | Criar nova tag | Admin/Super |
|
|
| `PATCH` | `/api/v1/tags/{id}` | Editar tag | Admin/Super |
|
|
|
|
### ⚙️ System & Settings
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/system/settings/{key}` | Ler configuração de sistema | Auth |
|
|
| `POST` | `/api/v1/system/settings/{key}` | Salvar configuração | SuperAdmin |
|
|
| `GET` | `/api/v1/system/credentials` | Ver credenciais (mascaradas) | SuperAdmin |
|
|
| `POST` | `/api/v1/system/credentials` | Salvar/Rotacionar credencial | SuperAdmin |
|
|
| `GET` | `/api/v1/storage/upload-url` | Gerar URL pré-assinada (S3/R2) | Auth |
|
|
| `POST` | `/api/v1/system/cloudflare/purge` | Limpar cache CDN | SuperAdmin |
|
|
| `GET` | `/api/v1/audit/logins` | Ver logs de acesso | SuperAdmin |
|
|
|
|
### 📧 Email Management
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `GET` | `/api/v1/admin/email-templates` | Listar templates | SuperAdmin |
|
|
| `POST` | `/api/v1/admin/email-templates` | Criar template | SuperAdmin |
|
|
| `GET` | `/api/v1/admin/email-settings` | Configurações SMTP/Provider | SuperAdmin |
|
|
| `PUT` | `/api/v1/admin/email-settings` | Atualizar configs de email | SuperAdmin |
|
|
|
|
### 💳 Payments
|
|
| Método | Endpoint | Descrição | Roles |
|
|
|--------|----------|-----------|-------|
|
|
| `POST` | `/api/v1/payments/create-checkout` | Criar sessão de checkout | Auth |
|
|
| `GET` | `/api/v1/payments/status/{id}` | Verificar status pagto | Auth |
|
|
| `POST` | `/api/v1/payments/webhook` | Webhook (Stripe/Gateway) | Public |
|
|
|
|
---
|
|
|
|
## 🗄️ Migrations
|
|
|
|
O projeto usa um sistema de migrations manuais via `cmd/manual_migrate`.
|
|
|
|
### Executar Migrations
|
|
```bash
|
|
go run ./cmd/manual_migrate
|
|
```
|
|
|
|
---
|
|
|
|
## 💻 Desenvolvimento Local
|
|
|
|
### Pré-requisitos
|
|
- **Go 1.22+**
|
|
- **Podman** (ou Docker, mas o projeto é otimizado para Podman/Quadlet)
|
|
- **PostgreSQL** (Rodando local ou via container)
|
|
|
|
### Executar com Go (Método Padrão)
|
|
```bash
|
|
# 1. Configurar Ambiente
|
|
cp .env.example .env
|
|
# Edite o .env com suas credentials (DB, JWT_SECRET, etc)
|
|
|
|
# 2. Executar Migrations
|
|
go run ./cmd/manual_migrate
|
|
|
|
# 3. Iniciar API Server
|
|
go run ./cmd/api
|
|
```
|
|
|
|
### Executar com Podman (Container)
|
|
```bash
|
|
# Construir a imagem
|
|
podman build -t gohorse-backend ./backend
|
|
|
|
# Rodar o container
|
|
# Nota: --network host é útil em dev para acessar o DB local facilmente
|
|
podman run --name api -p 8080:8080 --env-file ./backend/.env gohorse-backend
|
|
```
|
|
|
|
> **Nota:** A infraestrutura de produção utiliza **Quadlet (Systemd + Podman)**. Para dev, recomenda-se rodar o binário Go nativo ou usar `podman run` individualmente.
|
|
|
|
### Testes
|
|
```bash
|
|
# Todos os testes
|
|
go test ./...
|
|
|
|
# Com cobertura
|
|
go test -cover ./...
|
|
```
|
|
|
|
---
|
|
|
|
## ❓ Troubleshooting (CI/CD & Runner)
|
|
|
|
### O Workflow não inicia (`Waiting for runner...`)
|
|
* **Causa:** Nenhuma maquina registrada com o label correto.
|
|
* **Solução:**
|
|
1. Verifique, no arquivo `.forgejo/workflows/deploy.yaml`, o campo `runs-on`.
|
|
2. Se estiver como `docker`, seu `act_runner` deve ter suporte a este label (ex: `labels: "docker:docker://node:16-bullseye,ubuntu-latest:docker://node:16-bullseye"` no `config.yaml`).
|
|
3. Se o runner for genérico, use `ubuntu-latest`.
|
|
|
|
### Falha de SSH (`ssh: handshake failed`)
|
|
* **Solução:**
|
|
1. Verifique se a chave pública (`id_rsa.pub`) correspondente à `SSH_KEY` do secret está no arquivo `~/.ssh/authorized_keys` da máquina de destino.
|
|
2. Confira se o IP (`HOST`) está acessível da rede onde o runner está.
|
|
|
|
### Falha de Build no Podman
|
|
* **Causa:** Falta de permissão ou serviço parado.
|
|
* **Solução:**
|
|
1. Rode `podman logs -f <conteiner>` na máquina de destino.
|
|
2. Verifique se o usuário tem permissão de usar podman (rootless ou sudo).
|