diff --git a/ass-email/README.md b/ass-email/README.md
deleted file mode 100644
index 9b5d454..0000000
--- a/ass-email/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Ass Email - GoHorse Jobs
-
-This directory handles the email templating and dispatchers, specifically configured for notification processing and mail tasks.
-
-## 🚨 AI Rules Warning 🚨
-Before making ANY changes to infrastructure deployment manifests or Kubernetes files, please refer to the project-wide AI Rules located at `.agent/rules.md`.
-**Do NOT touch `k3s` or `k8s` files.** Do not alter raw RSA/base64 authentication keys.
diff --git a/ass-email/assinatura-exemplo.html b/ass-email/assinatura-exemplo.html
deleted file mode 100644
index 35ce533..0000000
--- a/ass-email/assinatura-exemplo.html
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
-
-
- Assinatura de Email - Exemplo
-
-
-
-
-
Exemplo Preenchido
-
-
-
-
-
-
-
- |
-
-
-
-
- |
- João Silva
- |
-
-
- |
- Desenvolvedor Full Stack
- |
-
-
-
-
-
-
- |
- 📞
- |
-
- +55 (11) 99999-9999
- |
-
-
- |
-
-
-
-
-
- |
- 📍
- |
-
- Av. Paulista, 1000 - São Paulo, SP
- |
-
-
- |
-
-
- |
-
- |
-
-
- |
-
- |
-
-
- |
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ass-email/assinatura-template.html b/ass-email/assinatura-template.html
deleted file mode 100644
index 5462ce1..0000000
--- a/ass-email/assinatura-template.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
- Assinatura de Email - Moobz
-
-
-
-
-
Prévia da Assinatura de Email
-
-
-
-
-
-
-
- |
-
-
-
-
- |
- {{NOME_SOBRENOME}}
- |
-
-
- |
- {{CARGO}}
- |
-
-
-
-
-
-
-
-
- |
-
- {{TELEFONE}}
- |
-
-
- |
-
-
-
-
-
-
-
- |
-
- {{ENDERECO}}
- |
-
-
- |
-
-
- |
-
- |
-
-
- |
-
- |
-
-
- |
-
-
-
-
-
-
-
- Como usar:
- 1. Substitua os campos entre {{CHAVES}} pelos seus dados:
- • {{NOME_SOBRENOME}} → Seu nome completo
- • {{CARGO}} → Seu cargo
- • {{TELEFONE}} → Seu telefone
- • {{ENDERECO}} → Endereço da empresa
- • {{EMAIL}} → Seu email
- • {{INSTAGRAM}} → Usuário do Instagram (sem @)
- 2. Copie o HTML e cole nas configurações de assinatura do seu email.
-
-
-
-
diff --git a/ass-email/assinaturademailmoobz.png b/ass-email/assinaturademailmoobz.png
deleted file mode 100644
index 39661fb..0000000
Binary files a/ass-email/assinaturademailmoobz.png and /dev/null differ
diff --git a/AGENT.md b/docs/context/AGENT.md
similarity index 100%
rename from AGENT.md
rename to docs/context/AGENT.md
diff --git a/DOMAIN.md b/docs/context/DOMAIN.md
similarity index 100%
rename from DOMAIN.md
rename to docs/context/DOMAIN.md
diff --git a/job-scraper-multisite/.dockerignore b/job-scraper-multisite/.dockerignore
deleted file mode 100644
index 090e9b3..0000000
--- a/job-scraper-multisite/.dockerignore
+++ /dev/null
@@ -1,13 +0,0 @@
-# Python scraper .dockerignore
-__pycache__/
-*.pyc
-*.pyo
-.venv/
-venv/
-.env
-.git/
-.gitignore
-README.md
-*.md
-output/*.csv
-.DS_Store
diff --git a/job-scraper-multisite/.env.example b/job-scraper-multisite/.env.example
deleted file mode 100644
index 1478338..0000000
--- a/job-scraper-multisite/.env.example
+++ /dev/null
@@ -1,20 +0,0 @@
-# =============================================================================
-# GoHorse Jobs Scraper - Environment Variables Example
-# =============================================================================
-# Copy this file to .env and update the values
-
-# Output Configuration
-OUTPUT_DIR=./output
-OUTPUT_FORMAT=csv
-
-# API Configuration (to send scraped data to backend)
-BACKEND_API_URL=http://localhost:8521/api/v1
-API_TOKEN=your-api-token-here
-
-# Scraping Configuration
-SCRAPE_DELAY_SECONDS=2
-MAX_PAGES_PER_SITE=10
-USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
-
-# Logging
-LOG_LEVEL=INFO
diff --git a/job-scraper-multisite/.gitignore b/job-scraper-multisite/.gitignore
deleted file mode 100644
index 1384c0a..0000000
--- a/job-scraper-multisite/.gitignore
+++ /dev/null
@@ -1,30 +0,0 @@
-# Python
-__pycache__/
-*.py[cod]
-*$py.class
-*.so
-.Python
-.venv/
-venv/
-ENV/
-
-# Output (keep .gitkeep)
-output/*.csv
-
-# Environment
-.env
-.env.*
-!.env.example
-
-# IDE
-.idea/
-.vscode/
-
-# OS
-.DS_Store
-Thumbs.db
-
-# Distribution
-dist/
-build/
-*.egg-info/
diff --git a/job-scraper-multisite/Dockerfile b/job-scraper-multisite/Dockerfile
deleted file mode 100644
index 31989a7..0000000
--- a/job-scraper-multisite/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# =============================================================================
-# GoHorse Jobs Scraper - Python Dockerfile
-# =============================================================================
-
-FROM mirror.gcr.io/library/python:3.12-slim
-
-WORKDIR /app
-
-# Install dependencies
-COPY requirements.txt ./
-RUN pip install --no-cache-dir -r requirements.txt
-
-# Copy source
-COPY . .
-
-# Security: Run as non-root
-RUN useradd -m -u 1001 scraper && \
- chown -R scraper:scraper /app
-
-USER scraper
-
-# Create output directory
-RUN mkdir -p /app/output
-
-CMD ["python", "main_scraper.py"]
diff --git a/job-scraper-multisite/README.md b/job-scraper-multisite/README.md
deleted file mode 100644
index b76dda1..0000000
--- a/job-scraper-multisite/README.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# 🐴 JobScraper MultiSite
-
-Raspador de vagas de emprego multi-plataforma para sites de tecnologia brasileiros.
-
-## 📁 Estrutura do Projeto
-
-```
-JobScraper_MultiSite/
-├── main_scraper.py # Arquivo principal
-├── scrapers/ # Módulos de raspagem por site
-│ ├── __init__.py
-│ ├── programathor_scraper.py
-│ └── geekhunter_scraper.py
-├── output/ # Arquivos CSV gerados
-│ └── vagas_consolidadas.csv
-├── requirements.txt
-└── README.md
-```
-
-## 🚀 Instalação
-
-```bash
-# Criar ambiente virtual (recomendado)
-python -m venv venv
-source venv/bin/activate # Linux/Mac
-# ou: venv\Scripts\activate # Windows
-
-# Instalar dependências
-pip install -r requirements.txt
-
-# Ou instalar manualmente:
-pip install requests beautifulsoup4 pandas
-```
-
-## ▶️ Execução
-
-```bash
-# Executar raspagem de todos os sites
-python main_scraper.py
-
-# Testar um scraper individual
-python -m scrapers.programathor_scraper
-```
-
-## 📊 Output
-
-Os resultados são salvos na pasta `output/`:
-- `vagas_consolidadas.csv` - Versão mais recente
-- `vagas_consolidadas_YYYYMMDD_HHMMSS.csv` - Versões com timestamp
-
-### Campos extraídos:
-| Campo | Descrição |
-|-------------|------------------------------|
-| titulo | Título da vaga |
-| empresa | Nome da empresa |
-| localizacao | Localização/Modalidade |
-| link | URL da vaga |
-| fonte | Site de origem |
-
-## ➕ Adicionando Novos Sites
-
-1. Crie um novo arquivo em `scrapers/` (ex: `novosite_scraper.py`)
-2. Implemente a função `scrape_novosite()` seguindo o padrão existente
-3. Adicione ao dicionário `SITES` em `main_scraper.py`:
-
-```python
-from scrapers.novosite_scraper import scrape_novosite
-
-SITES = {
- 'programathor': scrape_programathor,
- 'geekhunter': scrape_geekhunter,
- 'novosite': scrape_novosite, # Novo!
-}
-```
-
-## ⚠️ Boas Práticas Anti-Bloqueio
-
-- ✅ Sempre use `time.sleep()` entre requisições (mínimo 2s)
-- ✅ Use headers que simulem um navegador real
-- ✅ Não faça muitas requisições em sequência rápida
-- ✅ Respeite o `robots.txt` de cada site
-- ✅ Considere usar proxies para grandes volumes
-
-## 📝 Licença
-
-Uso educacional. Respeite os Termos de Serviço de cada site.
diff --git a/job-scraper-multisite/main_scraper.py b/job-scraper-multisite/main_scraper.py
deleted file mode 100644
index 9136ec9..0000000
--- a/job-scraper-multisite/main_scraper.py
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/env python3
-"""
-🐴 JobScraper MultiSite - Raspador de Vagas Multi-Plataforma
-=============================================================
-Consolida vagas de emprego de múltiplos sites de tecnologia.
-"""
-
-import pandas as pd
-from datetime import datetime
-import os
-
-# Imports dos scrapers
-from scrapers.programathor_scraper import scrape_programathor
-from scrapers.geekhunter_scraper import scrape_geekhunter
-
-# Configuração: Sites a serem raspados
-SITES = {
- 'programathor': scrape_programathor,
- 'geekhunter': scrape_geekhunter,
-}
-
-# Pasta de output
-OUTPUT_DIR = 'output'
-
-
-def ensure_output_dir():
- """Cria a pasta de output se não existir."""
- if not os.path.exists(OUTPUT_DIR):
- os.makedirs(OUTPUT_DIR)
- print(f"📁 Pasta '{OUTPUT_DIR}' criada.")
-
-
-def run_scrapers(sites_to_run: list = None) -> pd.DataFrame:
- """
- Executa os scrapers configurados e consolida os resultados.
-
- Args:
- sites_to_run: Lista de sites para raspar. Se None, raspa todos.
-
- Returns:
- DataFrame consolidado com todas as vagas.
- """
- if sites_to_run is None:
- sites_to_run = list(SITES.keys())
-
- all_vagas = []
-
- print("=" * 60)
- print("🐴 JobScraper MultiSite - Iniciando raspagem...")
- print("=" * 60)
-
- for site_name in sites_to_run:
- if site_name not in SITES:
- print(f"⚠️ Site '{site_name}' não configurado. Pulando...")
- continue
-
- print(f"\n📡 Processando: {site_name.upper()}")
- print("-" * 40)
-
- scraper_func = SITES[site_name]
- df = scraper_func()
-
- if not df.empty:
- all_vagas.append(df)
-
- if all_vagas:
- consolidated_df = pd.concat(all_vagas, ignore_index=True)
- # Remover duplicatas baseado no link
- consolidated_df.drop_duplicates(subset=['link'], inplace=True)
- return consolidated_df
-
- return pd.DataFrame()
-
-
-def save_results(df: pd.DataFrame, filename: str = None) -> str:
- """
- Salva o DataFrame consolidado em CSV.
-
- Args:
- df: DataFrame com as vagas.
- filename: Nome do arquivo (opcional).
-
- Returns:
- Caminho do arquivo salvo.
- """
- ensure_output_dir()
-
- if filename is None:
- timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
- filename = f'vagas_consolidadas_{timestamp}.csv'
-
- filepath = os.path.join(OUTPUT_DIR, filename)
- df.to_csv(filepath, index=False, encoding='utf-8-sig')
-
- return filepath
-
-
-def main():
- """Função principal."""
- # Executar scrapers
- df = run_scrapers()
-
- print("\n" + "=" * 60)
-
- if df.empty:
- print("❌ Nenhuma vaga encontrada.")
- return
-
- # Estatísticas
- print(f"📊 Total de vagas coletadas: {len(df)}")
- print(f"📊 Fontes: {df['fonte'].value_counts().to_dict()}")
-
- # Salvar resultados
- filepath = save_results(df)
- print(f"\n💾 Vagas salvas em: {filepath}")
-
- # Também salvar versão "latest"
- latest_path = save_results(df, 'vagas_consolidadas.csv')
- print(f"💾 Versão atual: {latest_path}")
-
- print("=" * 60)
- print("✅ Raspagem concluída com sucesso!")
-
- # Preview
- print("\n📋 Preview das vagas:")
- print(df[['titulo', 'empresa', 'fonte']].head(10).to_string(index=False))
-
-
-if __name__ == "__main__":
- main()
diff --git a/job-scraper-multisite/output/.gitkeep b/job-scraper-multisite/output/.gitkeep
deleted file mode 100644
index b8cc9fd..0000000
--- a/job-scraper-multisite/output/.gitkeep
+++ /dev/null
@@ -1 +0,0 @@
-# Keep this folder in git
diff --git a/job-scraper-multisite/requirements.txt b/job-scraper-multisite/requirements.txt
deleted file mode 100644
index d36f2b3..0000000
--- a/job-scraper-multisite/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-requests>=2.28.0
-beautifulsoup4>=4.11.0
-pandas>=1.5.0
-lxml>=4.9.0
diff --git a/job-scraper-multisite/scrapers/__init__.py b/job-scraper-multisite/scrapers/__init__.py
deleted file mode 100644
index ed9cf4e..0000000
--- a/job-scraper-multisite/scrapers/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# Scrapers package
-# Each site has its own scraper module
diff --git a/job-scraper-multisite/scrapers/geekhunter_scraper.py b/job-scraper-multisite/scrapers/geekhunter_scraper.py
deleted file mode 100644
index c599f46..0000000
--- a/job-scraper-multisite/scrapers/geekhunter_scraper.py
+++ /dev/null
@@ -1,89 +0,0 @@
-"""
-Scraper para GeekHunter - https://www.geekhunter.com.br/vagas
-"""
-
-import requests
-from bs4 import BeautifulSoup
-import pandas as pd
-import time
-
-# Headers para simular navegador e evitar bloqueios
-HEADERS = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
- 'Accept-Language': 'pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7',
-}
-
-def scrape_geekhunter(delay: float = 2.0) -> pd.DataFrame:
- """
- Raspa vagas do site GeekHunter.
-
- Args:
- delay: Tempo de espera antes da requisição (anti-bloqueio)
-
- Returns:
- DataFrame com colunas: titulo, empresa, localizacao, link
- """
- url = "https://www.geekhunter.com.br/vagas"
- vagas = []
-
- try:
- # Delay anti-bloqueio
- time.sleep(delay)
-
- print(f"🔍 Raspando vagas de: {url}")
- response = requests.get(url, headers=HEADERS, timeout=30)
- response.raise_for_status()
-
- soup = BeautifulSoup(response.text, 'html.parser')
-
- # Encontrar cards de vagas (ajustar seletores conforme estrutura do site)
- job_cards = soup.select('.job-card') or soup.select('[class*="job"]') or soup.select('article')
-
- for card in job_cards:
- try:
- # Extrair título
- titulo_elem = card.select_one('h2') or card.select_one('h3') or card.select_one('.title')
- titulo = titulo_elem.get_text(strip=True) if titulo_elem else "N/A"
-
- # Extrair empresa
- empresa_elem = card.select_one('.company') or card.select_one('[class*="company"]')
- empresa = empresa_elem.get_text(strip=True) if empresa_elem else "N/A"
-
- # Extrair localização
- loc_elem = card.select_one('.location') or card.select_one('[class*="location"]')
- localizacao = loc_elem.get_text(strip=True) if loc_elem else "Remoto"
-
- # Extrair link
- link_elem = card.select_one('a[href*="/vagas/"]') or card.select_one('a')
- if link_elem:
- href = link_elem.get('href', '')
- link = f"https://www.geekhunter.com.br{href}" if href.startswith('/') else href
- else:
- link = url
-
- vagas.append({
- 'titulo': titulo,
- 'empresa': empresa,
- 'localizacao': localizacao,
- 'link': link,
- 'fonte': 'GeekHunter'
- })
- except Exception as e:
- print(f"⚠️ Erro ao processar card: {e}")
- continue
-
- print(f"✅ {len(vagas)} vagas encontradas no GeekHunter")
-
- except requests.exceptions.RequestException as e:
- print(f"❌ Erro na requisição ao GeekHunter: {e}")
- except Exception as e:
- print(f"❌ Erro inesperado no GeekHunter: {e}")
-
- return pd.DataFrame(vagas)
-
-
-if __name__ == "__main__":
- # Teste individual do scraper
- df = scrape_geekhunter()
- print(df.head())
diff --git a/job-scraper-multisite/scrapers/programathor_scraper.py b/job-scraper-multisite/scrapers/programathor_scraper.py
deleted file mode 100644
index dc1bf88..0000000
--- a/job-scraper-multisite/scrapers/programathor_scraper.py
+++ /dev/null
@@ -1,89 +0,0 @@
-"""
-Scraper para ProgramaThor - https://programathor.com.br/jobs
-"""
-
-import requests
-from bs4 import BeautifulSoup
-import pandas as pd
-import time
-
-# Headers para simular navegador e evitar bloqueios
-HEADERS = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
- 'Accept-Language': 'pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7',
-}
-
-def scrape_programathor(delay: float = 2.0) -> pd.DataFrame:
- """
- Raspa vagas do site ProgramaThor.
-
- Args:
- delay: Tempo de espera antes da requisição (anti-bloqueio)
-
- Returns:
- DataFrame com colunas: titulo, empresa, localizacao, link
- """
- url = "https://programathor.com.br/jobs"
- vagas = []
-
- try:
- # Delay anti-bloqueio
- time.sleep(delay)
-
- print(f"🔍 Raspando vagas de: {url}")
- response = requests.get(url, headers=HEADERS, timeout=30)
- response.raise_for_status()
-
- soup = BeautifulSoup(response.text, 'html.parser')
-
- # Encontrar cards de vagas (ajustar seletores conforme estrutura do site)
- job_cards = soup.select('.cell-list')
-
- for card in job_cards:
- try:
- # Extrair título
- titulo_elem = card.select_one('h3') or card.select_one('.title')
- titulo = titulo_elem.get_text(strip=True) if titulo_elem else "N/A"
-
- # Extrair empresa
- empresa_elem = card.select_one('.company-name') or card.select_one('h4')
- empresa = empresa_elem.get_text(strip=True) if empresa_elem else "N/A"
-
- # Extrair localização
- loc_elem = card.select_one('.location') or card.select_one('.info')
- localizacao = loc_elem.get_text(strip=True) if loc_elem else "Remoto"
-
- # Extrair link
- link_elem = card.select_one('a[href*="/jobs/"]')
- if link_elem:
- href = link_elem.get('href', '')
- link = f"https://programathor.com.br{href}" if href.startswith('/') else href
- else:
- link = url
-
- vagas.append({
- 'titulo': titulo,
- 'empresa': empresa,
- 'localizacao': localizacao,
- 'link': link,
- 'fonte': 'ProgramaThor'
- })
- except Exception as e:
- print(f"⚠️ Erro ao processar card: {e}")
- continue
-
- print(f"✅ {len(vagas)} vagas encontradas no ProgramaThor")
-
- except requests.exceptions.RequestException as e:
- print(f"❌ Erro na requisição ao ProgramaThor: {e}")
- except Exception as e:
- print(f"❌ Erro inesperado no ProgramaThor: {e}")
-
- return pd.DataFrame(vagas)
-
-
-if __name__ == "__main__":
- # Teste individual do scraper
- df = scrape_programathor()
- print(df.head())