Backend - GoHorse Jobs API

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)
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:
- Trigger: Push no branch
dev (apenas alterações em backend/**).
- Runner: Executa no ambiente
docker (verifique as labels do seu runner).
- SSH Action: Conecta no servidor de desenvolvimento (Apolo) via SSH.
- Atualização de Código:
- Navega até
/mnt/data/gohorsejobs (ou caminho configurado).
- Faz
git fetch e git checkout dev.
git pull origin dev.
- 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
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)
# 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)
# 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
# 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:
- Verifique, no arquivo
.forgejo/workflows/deploy.yaml, o campo runs-on.
- 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).
- Se o runner for genérico, use
ubuntu-latest.
Falha de SSH (ssh: handshake failed)
- Solução:
- 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.
- 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:
- Rode
podman logs -f <conteiner> na máquina de destino.
- Verifique se o usuário tem permissão de usar podman (rootless ou sudo).