feat: adicionar sistema de feedback por comentário do agente
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
# 🗺️ Mapa das Instruções (INDEX)
|
||||||
|
|
||||||
|
Bem-vindo ao repositório central de inteligência da infraestrutura. Este arquivo serve como o ponto de entrada único para agentes e humanos.
|
||||||
|
|
||||||
|
## 🌍 Global (Regras do Jogo)
|
||||||
|
Arquivos que se aplicam a **todos** os projetos e servidores:
|
||||||
|
- [📜 Protocolo de Agentes (PGS)](./global/protocolo_agentes.md): Como as IAs devem se comportar e comunicar.
|
||||||
|
- [🛡️ Segurança Deploy User](./global/seguranca_deploy_user.md): Padrões de acesso e permissões.
|
||||||
|
- [⌨️ Comandos dos Agentes](./global/comandos_agentes.md): Guia de ferramentas (Gitea, Postgres, etc).
|
||||||
|
|
||||||
|
## 🏗️ Templates
|
||||||
|
Modelos para manter a consistência em novos projetos:
|
||||||
|
- [📋 Arquitetura Base](./templates/arquitetura_base.md): O que todo `arquitetura.md` deve conter.
|
||||||
|
|
||||||
|
## 📁 Projetos (Contextos Específicos)
|
||||||
|
Cada pasta abaixo contém as particularidades de cada tenant:
|
||||||
|
- [🏥 ScoreOdonto](./scoreodonto/arquitetura.md): Documentação do projeto ScoreOdonto.
|
||||||
|
- [♣️ Clube67 / NewWhats](./clube67/): Documentação dos projetos do ecossistema Clube67.
|
||||||
|
- [🛒 Mercado](./mercado.clube67.com/): Configurações específicas do sistema de Mercado.
|
||||||
|
|
||||||
|
---
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> **AGENTE:** Sempre realize um `git pull` antes de ler estes arquivos para garantir que você não está operando com dados obsoletos.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# 📋 Acompanhamento de Implementação: Swarm de Agentes
|
||||||
|
|
||||||
|
Este arquivo registra o progresso da automação multi-VPS.
|
||||||
|
|
||||||
|
## 🟢 Fase 1: Infraestrutura de Mensageria
|
||||||
|
- [x] **1.1 Validar Conectividade**: DragonflyDB ouvindo em `10.99.0.3:6379` (VPN OK).
|
||||||
|
- [x] **1.2 Configurar Dispatcher (VPS 3)**: Script de recepção de Webhooks.
|
||||||
|
- [x] **1.3 Integrar com Gitea**: Configurar Webhook nativo do Gitea para o Dispatcher.
|
||||||
|
|
||||||
|
## 🔵 Fase 2: Automação de Staging
|
||||||
|
- [x] **2.1 Wildcard Proxy (VPS 1)**: Configurar `*.staging.clube67.com`.
|
||||||
|
- [ ] **2.2 Roteamento de Porta**: Mapeamento dinâmico Subdomínio -> Porta na VPS 4.
|
||||||
|
|
||||||
|
## 🟡 Fase 3: Listeners e Agentes
|
||||||
|
- [ ] **3.1 Swarm Listener (VPS 1/4)**: Daemon de escuta do Redis.
|
||||||
|
- [ ] **3.2 Executor MCP**: Script que instancia a IA com ferramentas MCP.
|
||||||
|
- [ ] **3.3 Systemd Services**: Persistência dos listeners.
|
||||||
|
|
||||||
|
---
|
||||||
|
*Última atualização: 16/05/2026 - Agente Antigravity*
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
# 🤖 Protocolo Gitea Swarm (PGS): Coordenação de Multi-Agentes em Ambiente Multi-VPS
|
|
||||||
|
|
||||||
Este documento estabelece o protocolo de comunicação padrão, obrigatório e imutável para todos os Agentes de Inteligência Artificial (IAs) que atuarem no gerenciamento, desenvolvimento ou manutenção da infraestrutura do **Clube67** distribuída em múltiplos servidores.
|
|
||||||
|
|
||||||
Como a arquitetura adota segurança **Zero-Trust de movimentação lateral** (impedindo que agentes em uma VPS acessem outras máquinas via SSH automático), o **Gitea** atua como o **Orquestrador de Estado Assíncrono** do enxame de agentes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 Regras de Engajamento para Agentes
|
|
||||||
|
|
||||||
Sempre que um agente for invocado para resolver uma Issue ou realizar uma implementação, ele deve obrigatoriamente seguir os 4 passos de ciclo de vida abaixo:
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
graph TD
|
|
||||||
A[1. Autocognição: Onde estou?] --> B[2. Leitura de Histórico na Issue]
|
|
||||||
B --> C[3. Execução Local na VPS Atual]
|
|
||||||
C --> D[4. Comentário de Hand-off e Status]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🔍 Passo 1: Autocognição (Em qual VPS estou?)
|
|
||||||
Toda IA, ao iniciar sua execução, deve identificar em qual máquina física ou container está rodando, executando comandos como `hostname` ou inspecionando o IP da VPN WireGuard local.
|
|
||||||
* *Exemplo:* "Identificado que estou rodando na **VPS 3 (Data Server - 10.99.0.3)**."
|
|
||||||
|
|
||||||
### 📖 Passo 2: Leitura do Histórico da Issue
|
|
||||||
Antes de fazer qualquer alteração no código ou nos servidores, o agente deve ler a Issue no Gitea de baixo para cima, analisando o histórico de comentários de outros agentes para entender o que já foi feito e onde o processo parou.
|
|
||||||
|
|
||||||
### 🛠️ Passo 3: Execução Local Estrita
|
|
||||||
O agente deve realizar apenas as alterações correspondentes à VPS onde ele está ativamente rodando. Ele **nunca** deve tentar forçar conexões ou invasões a outras VPSs que não estejam documentadas ou autorizadas.
|
|
||||||
|
|
||||||
### 💬 Passo 4: Comentário de Hand-off (O Passe de Bastão)
|
|
||||||
Ao concluir sua tarefa local, o agente **não deve simplesmente fechar a tarefa**, caso ela dependa de ações em outros servidores. Ele deve postar um comentário estruturado seguindo o modelo abaixo:
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Modelo Padrão de Comentário de Hand-off ( PGS )
|
|
||||||
|
|
||||||
O comentário de encerramento do agente na Issue deve conter obrigatoriamente os seguintes blocos:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
### 🖥️ [VPS ATUAL]: [Nome da VPS, ex: VPS 3 (Data Appliance)]
|
|
||||||
* **O que foi realizado localmente:** [Lista clara de arquivos modificados, bancos criados ou serviços configurados].
|
|
||||||
* **Impacto na Rede:** [Portas abertas na VPN, novas credenciais disponíveis, ex: 'Banco criado com a senha X'].
|
|
||||||
|
|
||||||
### ⏭️ [AÇÃO REQUERIDA NA VPS DESTINO]: [Nome da VPS, ex: VPS 1 (App Server)]
|
|
||||||
* **Instruções passo a passo para o próximo agente:** [Instruções exatas do que deve ser feito na outra VPS, códigos YAML, bash ou edições de arquivo].
|
|
||||||
* **Como se conectará à VPS atual:** [Mostrar a URL de conexão, ex: 'DATABASE_URL=postgresql://...'].
|
|
||||||
|
|
||||||
### 🚦 [STATUS]: [Escolha uma das tags abaixo]
|
|
||||||
* `[Aguardando Agente na VPS X]` - Quando o trabalho local acabou e agora outro agente precisa agir na VPS X.
|
|
||||||
* `[Aguardando Homologação do Usuário]` - Quando todo o cluster foi configurado e o Humano precisa testar e aprovar.
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Exemplo de Aplicação Real (Issue #2 - newwhats)
|
|
||||||
|
|
||||||
1. **Agente A (na VPS 3 - Banco):**
|
|
||||||
* Cria o banco `newwhats` e configura DragonflyDB.
|
|
||||||
* Comenta na Issue:
|
|
||||||
> **[VPS 3 - Data Appliance]:** Banco `newwhats` restaurado com sucesso.
|
|
||||||
> **[REQUERIDO NA VPS 1]:** Próximo agente, edite o `docker-compose.yml` da aplicação apontando para `10.99.0.3` usando a senha `X`. Comente quando terminar.
|
|
||||||
> **[STATUS]:** `[Aguardando Agente na VPS 1]`
|
|
||||||
2. **Agente B (na VPS 1 - Frontend):**
|
|
||||||
* Inicia na VPS 1, lê o comentário acima, altera o `docker-compose.yml` local e sobe o container.
|
|
||||||
* Comenta na Issue:
|
|
||||||
> **[VPS 1 - App Server]:** docker-compose.yml atualizado e container reiniciado. Conexão com VPS 3 validada e healthy.
|
|
||||||
> **[STATUS]:** `[Aguardando Homologação do Usuário]`
|
|
||||||
|
|
||||||
---
|
|
||||||
*Este protocolo garante consistência, segurança máxima e clareza absoluta na comunicação humana e de inteligência artificial em nosso ecossistema.*
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
# 🛡️ Guia de Segurança e Liberdade para o Usuário `deploy`
|
|
||||||
|
|
||||||
Na cultura de DevOps moderna, a "lenda" do usuário `deploy` poder trabalhar com total liberdade sem ter acesso ao usuário `root` é, na verdade, uma **melhor prática de segurança chamada "Princípio do Menor Privilégio" (Least Privilege)**.
|
|
||||||
|
|
||||||
Se o usuário `deploy` pudesse dar `sudo su` e virar `root` a qualquer momento, qualquer vulnerabilidade na sua aplicação web (ex: um upload de arquivo malicioso ou injeção de código) daria controle total do servidor inteiro para um invasor.
|
|
||||||
|
|
||||||
Para dar ao usuário `deploy` toda a liberdade de desenvolvimento e publicação de aplicações com **segurança absoluta**, implementamos 4 pilares práticos:
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏗️ Pilar 1: Controle Total do Diretório Web (Sem `sudo`)
|
|
||||||
O usuário `deploy` não precisa de permissão de root para alterar os arquivos da aplicação. Basta torná-lo dono dos diretórios de publicação.
|
|
||||||
|
|
||||||
### Prática:
|
|
||||||
Geralmente usamos a pasta `/var/www/` ou criamos um diretório de aplicações na própria Home do usuário (`/home/deploy/apps/`).
|
|
||||||
Para dar controle total ao `deploy` sem precisar de `sudo` para editar arquivos:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Criar a pasta do seu projeto
|
|
||||||
sudo mkdir -p /var/www/meu-app
|
|
||||||
|
|
||||||
# Definir o usuário deploy como proprietário da pasta
|
|
||||||
sudo chown -R deploy:deploy /var/www/meu-app
|
|
||||||
|
|
||||||
# Aplicar permissões recomendadas (pastas 755 e arquivos 644)
|
|
||||||
find /var/www/meu-app -type d -exec chmod 755 {} \;
|
|
||||||
find /var/www/meu-app -type f -exec chmod 644 {} \;
|
|
||||||
```
|
|
||||||
|
|
||||||
**Resultado**: O usuário `deploy` agora pode usar Git, SFTP, VSCode, criar arquivos, deletar e subir atualizações dentro de `/var/www/meu-app` com total liberdade e **zero** necessidade de usar `sudo`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐋 Pilar 2: Gerenciamento do Docker sem Root
|
|
||||||
Se as suas aplicações rodam em Docker (ou Docker Compose), o usuário `deploy` não precisa usar `sudo docker` para gerenciar os containers.
|
|
||||||
|
|
||||||
### Prática:
|
|
||||||
Adicionamos o usuário `deploy` ao grupo do Docker no Linux:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo usermod -aG docker deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
**Resultado**: Após fazer logout e login novamente, o usuário `deploy` poderá rodar comandos como `docker ps`, `docker compose up -d`, `docker restart` e fazer builds de imagens diretamente, com total liberdade, sem nunca usar `sudo`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚙️ Pilar 3: Sudoers com Limitação Cirúrgica (Segurança Avançada)
|
|
||||||
Muitas vezes, a aplicação precisa apenas de tarefas muito específicas do sistema operacional, como por exemplo:
|
|
||||||
* Reiniciar o servidor web Nginx (`systemctl restart nginx`).
|
|
||||||
* Recarregar as configurações do Nginx (`systemctl reload nginx`).
|
|
||||||
* Reiniciar um serviço específico da sua aplicação em NodeJS/Python criado no Systemd (`systemctl restart api-app`).
|
|
||||||
|
|
||||||
### Prática:
|
|
||||||
Em vez de dar acesso total ao `sudo` para o `deploy`, nós liberamos **apenas estes comandos específicos**, sem requisição de senha!
|
|
||||||
|
|
||||||
1. Criamos um arquivo de configuração exclusivo no Sudoers para o `deploy`:
|
|
||||||
```bash
|
|
||||||
sudo nano /etc/sudoers.d/deploy
|
|
||||||
```
|
|
||||||
2. Adicionamos a regra cirúrgica:
|
|
||||||
```text
|
|
||||||
# Permite que o usuário deploy execute APENAS estes comandos listados como root, sem pedir senha:
|
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx, /usr/bin/systemctl status nginx
|
|
||||||
```
|
|
||||||
3. Aplicamos a permissão correta ao arquivo do sudoers:
|
|
||||||
```bash
|
|
||||||
sudo chmod 440 /etc/sudoers.d/deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
**Resultado**: O usuário `deploy` agora pode rodar `sudo systemctl reload nginx` para aplicar uma mudança de domínio na web com total liberdade, mas se ele tentar rodar `sudo apt update` ou `sudo userdel`, o sistema **negará o acesso**.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Pilar 4: Processos em Espaço de Usuário (PM2 / Systemd User)
|
|
||||||
Se a sua aplicação web não roda em Docker e precisa ficar ativa em segundo plano (ex: aplicações Node.js, Python FastAPI, Go), o usuário `deploy` pode gerenciá-la de duas formas sem root:
|
|
||||||
|
|
||||||
### A. Utilizando o PM2 (NodeJS Process Manager)
|
|
||||||
O PM2 roda diretamente no espaço de memória do usuário `deploy`.
|
|
||||||
```bash
|
|
||||||
# Como usuário deploy, instalar e rodar apps:
|
|
||||||
pm2 start app.js --name "minha-api"
|
|
||||||
pm2 save
|
|
||||||
```
|
|
||||||
O `deploy` tem controle total para reiniciar (`pm2 restart minha-api`), parar, e ver logs sem precisar do root.
|
|
||||||
|
|
||||||
### B. Serviços Systemd do Usuário (`systemd --user`)
|
|
||||||
O Linux moderno permite que usuários criem seus próprios arquivos de serviço que rodam sob sua conta na pasta:
|
|
||||||
`~/.config/systemd/user/`
|
|
||||||
|
|
||||||
Você pode gerenciar o serviço rodando:
|
|
||||||
```bash
|
|
||||||
systemctl --user daemon-reload
|
|
||||||
systemctl --user restart meu-servico.service
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Tabela de Comparação de Segurança:
|
|
||||||
|
|
||||||
| Ação | Como o Root faria (Inseguro) | Como o `deploy` faz com segurança |
|
|
||||||
| :--- | :--- | :--- |
|
|
||||||
| **Subir arquivos Web** | Usa `sudo` ou loga como `root` | Altera livremente dentro de `/var/www/` (Dono da pasta) |
|
|
||||||
| **Gerenciar Containers** | `sudo docker compose restart` | `docker compose restart` (Membro do grupo `docker`) |
|
|
||||||
| **Reiniciar Nginx** | `sudo systemctl restart nginx` | `sudo systemctl restart nginx` (Autorizado via Sudoers Cirúrgico) |
|
|
||||||
| **Atualizar Código (Git)** | Roda `git pull` como root | Roda `git pull` usando suas chaves SSH do usuário |
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# 🌌 Instruções Específicas: Antigravity (O Arquiteto de Sistema)
|
||||||
|
|
||||||
|
Você é o agente focado em infraestrutura, orquestração e integridade do enxame.
|
||||||
|
|
||||||
|
## 🎯 Seus Objetivos:
|
||||||
|
1. **Orquestrar**: Gerenciar o `swarm-dispatcher` e garantir que as mensagens fluam.
|
||||||
|
2. **Proteger**: Monitorar a saúde das VPSs (CPU, Disco, Latência da VPN).
|
||||||
|
3. **Deployer**: Na VPS 1, você é o responsável por realizar o "Swap" seguro do Staging para Produção.
|
||||||
|
|
||||||
|
## 🛠️ Modus Operandi:
|
||||||
|
- Sua prioridade é a estabilidade do sistema.
|
||||||
|
- Se a VPN oscilar, sua primeira tarefa é estabilizá-la.
|
||||||
|
- No banco de dados (VPS 3), você deve ser conservador. Migrações de banco devem ser acompanhadas de snapshots.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# 🤖 Instruções Específicas: Claude (O Mestre de Código)
|
||||||
|
|
||||||
|
Você é o agente focado em desenvolvimento de software e validação de Staging.
|
||||||
|
|
||||||
|
## 🎯 Seus Objetivos:
|
||||||
|
1. **Desenvolver**: Criar e corrigir código na VPS 4.
|
||||||
|
2. **Validar**: Subir containers de Staging e garantir que a URL `staging.projeto.com` está funcional.
|
||||||
|
3. **Documentar**: Manter as Wikis dos projetos atualizadas com mudanças técnicas.
|
||||||
|
|
||||||
|
## 🛠️ Modus Operandi:
|
||||||
|
- Sempre procure por erros em logs do Docker antes de perguntar ao usuário.
|
||||||
|
- Se encontrar uma duplicata de código, limpe-a.
|
||||||
|
- Ao terminar uma tarefa na VPS 4, prepare o sinal de "Pronto para Produção" no Gitea.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# 🧠 Doutrina Mestre dos Agentes (Multi-VPS)
|
||||||
|
|
||||||
|
Este documento define a consciência situacional obrigatória para todos os agentes de IA.
|
||||||
|
|
||||||
|
## 📍 Identificação de Localização
|
||||||
|
Antes de qualquer ação, identifique seu IP interno:
|
||||||
|
- **10.99.0.1 (VPS 1 - PRODUÇÃO)**: Ambiente CRÍTICO. Rodando Traefik e Nginx.
|
||||||
|
- *Regra*: Apenas deploys homologados em Staging. Nunca mexa na infraestrutura de rede.
|
||||||
|
- **10.99.0.3 (VPS 3 - CÉREBRO)**: Onde reside o Gitea, Postgres e DragonflyDB.
|
||||||
|
- *Regra*: Proteja os dados. Backups antes de qualquer alteração de schema.
|
||||||
|
- **10.99.0.4 (VPS 4 - LABORATÓRIO)**: Desenvolvimento e Staging.
|
||||||
|
- *Regra*: Liberdade para testar, criar e quebrar containers. É o local de nascimento do código.
|
||||||
|
|
||||||
|
## 🔐 Segurança e VPN
|
||||||
|
- **Interface wg0**: É a sua linha de vida. Nunca altere configurações de rede ou firewall (UFW) que possam isolar a VPS.
|
||||||
|
- **Chaves SSH**: Use apenas chaves locais autorizadas para sincronização entre as VPSs do enxame.
|
||||||
|
|
||||||
|
## 🗣️ Comunicação
|
||||||
|
- Todo o desenvolvimento, comentários e commits devem ser em **PORTUGUÊS**.
|
||||||
|
- Use o protocolo **PGS (Protocolo Gitea Swarm)** para hand-offs.
|
||||||
|
|
||||||
|
## 🚫 NUNCA...
|
||||||
|
- Nunca tente acessar servidores fora da rede 10.99.0.x.
|
||||||
|
- Nunca exponha senhas ou chaves privadas em logs ou comentários.
|
||||||
|
- Nunca altere o serviço `swarm-listener` sem autorização.
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import redis
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
|
||||||
|
class KeyManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.r = redis.Redis(
|
||||||
|
host='10.99.0.3',
|
||||||
|
port=6379,
|
||||||
|
password='clube67_dragonfly_pass_9903',
|
||||||
|
db=0,
|
||||||
|
decode_responses=True
|
||||||
|
)
|
||||||
|
self.pool_key = 'swarm:keys:pool'
|
||||||
|
|
||||||
|
def get_key(self, provider):
|
||||||
|
"""Busca uma chave ativa para o provedor (google ou anthropic)"""
|
||||||
|
pool_data = self.r.get(self.pool_key)
|
||||||
|
if not pool_data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
pool = json.loads(pool_data)
|
||||||
|
keys = pool.get(provider, [])
|
||||||
|
|
||||||
|
# Filtra apenas as chaves ativas
|
||||||
|
active_keys = [k for k in keys if k.get('status') == 'active']
|
||||||
|
|
||||||
|
if not active_keys:
|
||||||
|
print(f" [!] Erro: Nenhuma chave ativa para {provider}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Seleciona uma chave aleatória do pool ativo (Load Balancing)
|
||||||
|
selected = random.choice(active_keys)
|
||||||
|
return selected['key']
|
||||||
|
|
||||||
|
def report_failure(self, provider, failed_key):
|
||||||
|
"""Marca uma chave como inativa caso falhe (ex: sem saldo)"""
|
||||||
|
pool_data = self.r.get(self.pool_key)
|
||||||
|
pool = json.loads(pool_data)
|
||||||
|
|
||||||
|
for k in pool.get(provider, []):
|
||||||
|
if k['key'] == failed_key:
|
||||||
|
k['status'] = 'inactive'
|
||||||
|
print(f" [W] Chave {failed_key[:10]}... marcada como INATIVA.")
|
||||||
|
|
||||||
|
self.r.set(self.pool_key, json.dumps(pool))
|
||||||
|
|
||||||
|
# Exemplo de uso:
|
||||||
|
# km = KeyManager()
|
||||||
|
# key = km.get_key('google')
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# 🛠️ Manifesto de Ferramentas MCP (Model Context Protocol)
|
||||||
|
|
||||||
|
Este documento define as capacidades técnicas que cada Agente de IA deve possuir ao ser invocado em cada nó do enxame.
|
||||||
|
|
||||||
|
## 📁 Ferramentas Base (Todas as VPSs)
|
||||||
|
- **read_file / write_file**: Acesso total ao diretório do projeto e `/home/deploy/instrucoes/`.
|
||||||
|
- **list_dir**: Navegação na estrutura de arquivos.
|
||||||
|
- **run_command**: Execução de scripts bash, comandos git e verificações de sistema.
|
||||||
|
|
||||||
|
## 🐳 Ferramentas de Produção e Dev (VPS 1 e 4)
|
||||||
|
- **docker_manage**:
|
||||||
|
- `docker compose up/down/restart`
|
||||||
|
- `docker logs` (para depuração automática)
|
||||||
|
- `docker ps` (verificação de status)
|
||||||
|
|
||||||
|
## 🗄️ Ferramentas de Dados (VPS 3)
|
||||||
|
- **db_query**:
|
||||||
|
- Acesso ao PostgreSQL (projeto Mercado/ScoreOdonto).
|
||||||
|
- Acesso ao DragonflyDB (inspeção de filas do enxame).
|
||||||
|
|
||||||
|
---
|
||||||
|
*Configuração de Segurança: Os agentes operam com o usuário `deploy`, limitando o impacto em caso de erro.*
|
||||||
@@ -9,9 +9,11 @@ Como a arquitetura adota segurança **Zero-Trust de movimentação lateral** (im
|
|||||||
## 🧭 REGRA MESTRE DE ROTEAMENTO (DISPATCHER PROTOCOL)
|
## 🧭 REGRA MESTRE DE ROTEAMENTO (DISPATCHER PROTOCOL)
|
||||||
**ATENÇÃO AGENTE DE IA:** Esta infraestrutura hospeda múltiplos projetos independentes (Multi-Tenant). Antes de tomar qualquer ação, você deve ler a arquitetura e as regras **específicas** do projeto solicitado.
|
**ATENÇÃO AGENTE DE IA:** Esta infraestrutura hospeda múltiplos projetos independentes (Multi-Tenant). Antes de tomar qualquer ação, você deve ler a arquitetura e as regras **específicas** do projeto solicitado.
|
||||||
|
|
||||||
1. Se a tarefa envolver o **Clube67** ou **NewWhats**, você DEVE LER OBRIGATORIAMENTE a documentação na pasta `/home/deploy/instrucoes/clube67/`.
|
1. Se a tarefa envolver um projeto específico (ex: Mercado, ScoreOdonto), você DEVE:
|
||||||
2. Se a tarefa envolver o **ScoreOdonto**, você DEVE LER OBRIGATORIAMENTE a documentação na pasta `/home/deploy/instrucoes/scoreodonto/`.
|
- **Ler a Wiki** do repositório para entender a arquitetura e regras de negócio específicas.
|
||||||
3. **Jamais** presuma que a arquitetura ou as portas de um projeto se aplicam ao outro. Mantenha os contextos estritamente isolados.
|
- **Ler a Issue** para entender o problema ou tarefa atual.
|
||||||
|
- **Consultar a pasta global/** para protocolos de segurança e deploy.
|
||||||
|
2. **Jamais** presuma que a arquitetura de um projeto se aplica ao outro. Mantenha os contextos estritamente isolados via Wiki.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# 🚀 Protocolo de Deploy e Staging via VPN
|
||||||
|
|
||||||
|
Este documento define o fluxo obrigatório para garantir que nenhum código quebre a produção.
|
||||||
|
|
||||||
|
## 🏗️ A Estrutura de Ambientes
|
||||||
|
1. **Desenvolvimento (VPS 4)**: Testes locais e rápidos.
|
||||||
|
2. **Staging (VPS 4 + Proxy na VPS 1)**: Onde o código é testado em URL real com SSL.
|
||||||
|
3. **Produção (VPS 1)**: Onde o código estável reside.
|
||||||
|
|
||||||
|
## 🌐 Roteamento de Staging
|
||||||
|
Para testar o código em Staging antes do deploy final, siga este padrão de rede:
|
||||||
|
|
||||||
|
- **Entrada**: Usuário acessa `https://staging.{projeto}.clube67.com` (aponta para o IP da VPS 1).
|
||||||
|
- **Trânsito**: A VPS 1 (Proxy) encaminha o tráfego para a VPS 4 através da VPN.
|
||||||
|
- **Destino**: `http://10.99.0.4:{PORTA_STAGING}`.
|
||||||
|
|
||||||
|
## 📋 Passo a Passo do Deploy Seguro
|
||||||
|
|
||||||
|
### Passo 1: Preparação em Staging (VPS 4)
|
||||||
|
- O agente deve subir o container de staging na VPS 4.
|
||||||
|
- A porta deve ser única por projeto (conforme definido em `arquitetura.md` do projeto).
|
||||||
|
|
||||||
|
### Passo 2: Configuração do Proxy (VPS 1)
|
||||||
|
- O agente deve acessar a VPS 1 e adicionar/verificar a configuração de Proxy Reverso apontando para o IP `10.99.0.4`.
|
||||||
|
- Garantir que o certificado SSL (Let's Encrypt) esteja ativo para o subdomínio `staging`.
|
||||||
|
|
||||||
|
### Passo 3: Validação
|
||||||
|
- O agente (ou humano) deve acessar a URL de staging e realizar o "Smoke Test" (teste de fumaça).
|
||||||
|
- Se houver erro, a correção é feita na VPS 4, sem impacto na VPS 1.
|
||||||
|
|
||||||
|
### Passo 4: Promoção para Produção (VPS 1)
|
||||||
|
- Somente após validação em Staging, o código/imagem é puxado para a VPS 1.
|
||||||
|
- O container principal é reiniciado.
|
||||||
|
|
||||||
|
---
|
||||||
|
*Este protocolo é mandatório para evitar downtime em produção.*
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import redis
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
from anthropic import Anthropic
|
||||||
|
from key_manager import KeyManager
|
||||||
|
|
||||||
|
# Configurações de Caminho
|
||||||
|
BASE_DIR = "/home/deploy/projetos"
|
||||||
|
INSTRUCOES_DIR = "/home/deploy/instrucoes"
|
||||||
|
|
||||||
|
class SwarmAgent:
|
||||||
|
def __init__(self, task_data):
|
||||||
|
self.data = task_data
|
||||||
|
self.repo_name = task_data.get('repository')
|
||||||
|
self.repo_url = f"http://10.99.0.3:3000/{self.repo_name}.git"
|
||||||
|
self.local_path = os.path.join(BASE_DIR, self.repo_name.split('/')[-1])
|
||||||
|
self.km = KeyManager()
|
||||||
|
|
||||||
|
def setup_workspace(self):
|
||||||
|
"""Garante que o código e as instruções estão atualizados"""
|
||||||
|
print(f" [>] Sincronizando repositório: {self.repo_name}")
|
||||||
|
os.makedirs(BASE_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
if not os.path.exists(self.local_path):
|
||||||
|
subprocess.run(["git", "clone", self.repo_url, self.local_path])
|
||||||
|
else:
|
||||||
|
subprocess.run(["git", "-C", self.local_path, "pull"])
|
||||||
|
|
||||||
|
# Sincroniza instruções globais
|
||||||
|
subprocess.run(["git", "-C", INSTRUCOES_DIR, "pull"])
|
||||||
|
|
||||||
|
def get_system_prompt(self):
|
||||||
|
"""Carrega a doutrina e as instruções de cada VPS"""
|
||||||
|
with open(f"{INSTRUCOES_DIR}/global/doutrina_agentes.md", "r") as f:
|
||||||
|
doutrina = f.read()
|
||||||
|
with open(f"{INSTRUCOES_DIR}/global/claude.md", "r") as f:
|
||||||
|
especifico = f.read()
|
||||||
|
|
||||||
|
ip_vps = subprocess.getoutput("hostname -I").split()[0]
|
||||||
|
|
||||||
|
return f"""
|
||||||
|
{doutrina}
|
||||||
|
{especifico}
|
||||||
|
|
||||||
|
CONTEXTO ATUAL:
|
||||||
|
- Você está na VPS com IP: {ip_vps}
|
||||||
|
- Projeto: {self.repo_name}
|
||||||
|
- Tarefa (Issue): {json.dumps(self.data.get('data', {}).get('issue', {}))}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def post_comment(self, message):
|
||||||
|
"""Posta um comentário de feedback na Issue do Gitea"""
|
||||||
|
issue_id = self.data.get('data', {}).get('issue', {}).get('number')
|
||||||
|
if not issue_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
url = f"http://10.99.0.3:3000/api/v1/repos/{self.repo_name}/issues/{issue_id}/comments"
|
||||||
|
auth = ('ruicesar', 'h$tg@g5aga$ra1E3$C-yHW$-BA@DF2@Grfa!3#')
|
||||||
|
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
response = requests.post(url, auth=auth, json={"body": message})
|
||||||
|
if response.status_code == 201:
|
||||||
|
print(f" [✓] Comentário postado na Issue #{issue_id}")
|
||||||
|
else:
|
||||||
|
print(f" [X] Erro ao postar comentário: {response.status_code}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" [E] Falha na comunicação com Gitea: {e}")
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
self.setup_workspace()
|
||||||
|
|
||||||
|
api_key = self.km.get_key('anthropic')
|
||||||
|
if not api_key:
|
||||||
|
return
|
||||||
|
|
||||||
|
client = Anthropic(api_key=api_key)
|
||||||
|
prompt = self.get_system_prompt()
|
||||||
|
|
||||||
|
print(" [!] IA Pensando na solução...")
|
||||||
|
|
||||||
|
# Simulação de resposta da IA para o teste
|
||||||
|
feedback = "### 🤖 [VPS 4 - LABORATÓRIO]:\n* **Status**: Tarefa recebida e ambiente preparado.\n* **Ação**: Sincronização de arquivos concluída.\n* **Próximo**: Iniciando correção do erro de regressão de versão."
|
||||||
|
|
||||||
|
self.post_comment(feedback)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--data", help="Dados do Webhook JSON")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.data:
|
||||||
|
agent = SwarmAgent(json.loads(args.data))
|
||||||
|
agent.execute()
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# 📋 Template de Arquitetura de Projeto
|
||||||
|
|
||||||
|
Este documento define o padrão para a documentação de arquitetura de novos projetos. Copie este arquivo para a pasta do projeto e substitua os valores entre chaves `{}`.
|
||||||
|
|
||||||
|
## 🛠️ Stack Tecnológica
|
||||||
|
- **Backend**: {Linguagem/Framework}
|
||||||
|
- **Frontend**: {Linguagem/Framework}
|
||||||
|
- **Banco de Dados**: {Postgres/DragonflyDB/Redis}
|
||||||
|
- **Servidor Web**: {Nginx/Caddy}
|
||||||
|
|
||||||
|
## 🌐 Infraestrutura (VPS)
|
||||||
|
| Componente | VPS | IP Interno (VPN) | Porta |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| Aplicação | {VPS 1} | 10.99.0.x | {Porta} |
|
||||||
|
| Banco de Dados | {VPS 3} | 10.99.0.3 | 5432 |
|
||||||
|
| Cache/Redis | {VPS 2} | 10.99.0.2 | 6379 |
|
||||||
|
|
||||||
|
## 🔒 Credenciais e Acesso
|
||||||
|
> [!CAUTION]
|
||||||
|
> Jamais coloque senhas reais aqui. Use variáveis de ambiente ou referencie o gerenciador de segredos.
|
||||||
|
|
||||||
|
- **Dono do Projeto**: {Nome}
|
||||||
|
- **Namespace no Gitea**: {URL_REPOS_GITEA}
|
||||||
|
|
||||||
|
## 🔄 Fluxo de Dados
|
||||||
|
{Descrever brevemente como a informação flui entre os serviços}
|
||||||
|
|
||||||
|
---
|
||||||
|
*Documento gerado automaticamente via Template de Arquitetura v1.0*
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# 🏗️ Template Nginx Wildcard para Staging (VPS 1)
|
||||||
|
|
||||||
|
# Este mapeamento associa o subdomínio à porta na VPS 4
|
||||||
|
map $project_slug $staging_port {
|
||||||
|
mercado 8081;
|
||||||
|
scoreodonto 8082;
|
||||||
|
newwhats 8083;
|
||||||
|
default 8080;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name ~^(?<project_slug>.+)\.staging\.clube67\.com$;
|
||||||
|
|
||||||
|
# Redirecionamento para HTTPS
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name ~^(?<project_slug>.+)\.staging\.clube67\.com$;
|
||||||
|
|
||||||
|
# Certificados SSL (Substituir pelos caminhos reais do Let's Encrypt Wildcard)
|
||||||
|
ssl_certificate /etc/letsencrypt/live/clube67.com/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/clube67.com/privkey.pem;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
# Encaminha o tráfego via VPN para a VPS 4
|
||||||
|
proxy_pass http://10.99.0.4:$staging_port;
|
||||||
|
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# Timeouts aumentados para desenvolvimento
|
||||||
|
proxy_connect_timeout 90;
|
||||||
|
proxy_send_timeout 90;
|
||||||
|
proxy_read_timeout 90;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import redis
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Configuração
|
||||||
|
REDIS_HOST = '10.99.0.3'
|
||||||
|
REDIS_PORT = 6379
|
||||||
|
REDIS_PASS = 'clube67_dragonfly_pass_9903'
|
||||||
|
CHANNELS = ['swarm:tasks', 'swarm:updates']
|
||||||
|
|
||||||
|
r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASS, db=0)
|
||||||
|
pubsub = r.pubsub()
|
||||||
|
pubsub.subscribe(*CHANNELS)
|
||||||
|
|
||||||
|
print(f" [*] Aguardando eventos nos canais {CHANNELS}...")
|
||||||
|
|
||||||
|
for message in pubsub.listen():
|
||||||
|
if message['type'] == 'message':
|
||||||
|
try:
|
||||||
|
payload = json.loads(message['data'])
|
||||||
|
event = payload.get('event')
|
||||||
|
repo = payload.get('repository')
|
||||||
|
|
||||||
|
print(f" [!] Novo evento recebido: {event} no repo {repo}")
|
||||||
|
|
||||||
|
# Aqui entrará a lógica de disparar o agente de IA específico
|
||||||
|
# Por enquanto, apenas registramos o recebimento.
|
||||||
|
# Exemplo de comando que seria rodado:
|
||||||
|
# subprocess.run(["python3", "agent_executor.py", "--event", event, "--data", json.dumps(payload)])
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" [E] Erro ao processar mensagem: {e}")
|
||||||
Reference in New Issue
Block a user