docs: documentação única da stack — deploy/infra/projetos + regras (LEIA-PRIMEIRO)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Deploy Agent
2026-06-17 17:31:50 +02:00
commit c0ca88c028
14 changed files with 582 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
# LEIA PRIMEIRO
> Documentação **única e oficial** da stack (Clube67 / ScoreOdonto e demais projetos).
> Repositório (fonte da verdade): **`git.clube67.com/ruicesar/Documentos-Unicos`**.
> **Leia este arquivo antes de qualquer outra coisa.**
---
## Regras obrigatórias
1. **Idioma: PORTUGUÊS.** Tudo — explicações, documentos, comentários, commits, conversas — em português. Sem exceção.
2. **Fonte única.** Este repositório é a documentação oficial e vigente. Qualquer `.md` fora daqui que divergir **não vale**.
3. **Uma situação = um arquivo.** Organização em **pastas por tipo**; dentro, **um `.md` por situação**. **Nunca** misturar situações num mesmo arquivo. Situação nova = arquivo novo (ou pasta nova de tipo).
4. **Atualizar = REESCREVER o arquivo da situação** (nunca "v2" ao lado). O arquivo descreve o **estado ATUAL real**, nunca o desejado.
5. **Versão antiga → `desuso/`.** Antes de reescrever, copie a versão anterior para `desuso/` com data no nome e aviso **EM DESUSO** no topo.
6. **Cada projeto só tem um `LEIA.md`** na raiz, que **aponta** para este repositório — **nunca** guarda documentação própria espalhada.
7. **`desuso/` é só CONSULTA.** Em dúvida, **consulte o `desuso/`** para entender o histórico / tirar dúvida ou como base para **corrigir/melhorar**. Mas ele **nunca** é instrução vigente: **toda instrução nova ou atualizada vai na doc oficial** (fora do `desuso/`).
8. **Sempre testar em `https://dev.<projeto>`** antes de qualquer coisa.
9. **Sempre pedir aprovação** do administrador antes de ir para **produção** ou implementar **novas melhorias/implementações**.
10. **Antes de anotar, checar duplicação.** Verifique se o tema **já existe** aqui — não duplicar. **Prefira sempre doc UNIVERSAL** (serve a todos os projetos). Se um projeto **for diferente**: **cite o que o torna diferente** e crie a doc específica dele em `projetos/<projeto>/` — para a **doc universal ficar sempre alinhada** (não poluída com exceções).
---
## Organização deste repositório
| Pasta | Conteúdo |
|---|---|
| `deploy/` | Deploy (universal): `modelo`, `subir-release`, `rollback`, `versionamento`. |
| `infra/` | Infraestrutura (universal): `maquinas-e-rede`, `ambiente-dev`. |
| `projetos/<projeto>/` | **Só o que DIFERE** do universal, por projeto (cita o delta + referencia o universal). |
| `desuso/` | Histórico/obsoletos (datado, "EM DESUSO"). Só consulta. |
> Tipo de assunto novo (ex.: segurança, banco, monitoramento)? Crie uma **pasta nova** aqui com os `.md` das situações.
+20
View File
@@ -0,0 +1,20 @@
# Deploy — Modelo (Build Once → Promote → Deploy)
> Situação: **como o deploy funciona, em conceito.** Estado real verificado em 17/jun/2026.
**Push** na `main` builda **uma vez** e publica a imagem por **commit**; a **tag `vX.Y.Z`** **re-tagueia** essa mesma imagem (sem rebuild) e deploya. **Produção nunca builda — só executa imagens prontas.**
```
PUSH main (commit C) TAG vX.Y.Z (no commit C)
│ │
▼ ▼
CI: build (1x) CI: promote (SEM build)
publica :C + :latest re-tag :C → :vX.Y.Z (MESMO digest) + deploy
▼ ▼
registry (Gitea) produção: pull :vX.Y.Z + up --no-build
```
Garantia central: **a imagem em produção é byte-idêntica à que foi buildada e testada**. A tag é só um rótulo de release sobre um artefato imutável.
- **Por que importa:** acaba a recompilação na promoção (que podia gerar imagem diferente da testada) e a colisão de tags. Implementação de referência: scoreodonto.com (`v1.0.18`).
- Situações relacionadas: `subir-release.md`, `rollback.md`, `versionamento.md`; infra em `../infra/`.
+16
View File
@@ -0,0 +1,16 @@
# Deploy — Rollback (reverter)
> Situação: **a versão nova quebrou, quero voltar.**
Por imagem, **sem rebuild** — na VPS1:
```bash
/home/deploy/stack/<projeto>/deploy-prod.sh <tag-ou-commit-anterior> # pull + up --no-build
```
- A referência confiável é o **commit** (`:<sha>`) ou a **tag de release** (`:vX.Y.Z`) — no modelo Build Once, `:vX.Y.Z` é alias imutável do commit.
- As migrações de banco são **aditivas** (só adicionam tabelas/colunas) → **voltar o código é seguro**, o schema extra fica inerte.
- Restaurar o **dump do banco** só em caso extremo:
```bash
pg_restore -d "postgresql://<user>:<senha>@10.99.0.3:5432/<banco>" --clean <arquivo>.dump
```
- Recuperação em **minutos** (só troca a imagem). Backups ficam em `/home/deploy/backups/`.
+31
View File
@@ -0,0 +1,31 @@
# Deploy — Subir um release
> Situação: **quero colocar uma versão nova em produção.**
⚠️ **Regra de ouro:** confirme **DEV ou PRODUÇÃO** antes de agir. `dev.<projeto>` = VPS4 (descartável). `<projeto>` sem `dev.` = VPS1 (real). **Nunca** `git push --force` na `main`. Push e tag exigem **autorização explícita do administrador**.
```bash
# 1) VPS4 — validar em DEV
node --check backend/server.js
docker compose build scoreodonto-backend scoreodonto-frontend
docker compose up -d --force-recreate scoreodonto-backend scoreodonto-frontend # conferir em dev.<projeto>
# 2) commit + push → o CI builda 1x e publica :<commit> + :latest (NÃO deploya)
git add -A && git commit -m "feat: <descrição>"
git push origin main
# 3) tag = "aprovado para produção" → o CI re-tagueia :<commit>→:vX.Y.Z (SEM rebuild) e deploya
git tag -a vX.Y.Z -m "release vX.Y.Z" && git push origin vX.Y.Z
# 4) verificar (sem SSH)
curl -s https://<projeto>/api/version # → vX.Y.Z · <commit> · PROD
curl -s https://<projeto>/api/health # → status ok
```
**Backup do banco de produção antes de releases sensíveis** (não há shell na VPS3; usar container):
```bash
docker run --rm -e PGPASSWORD=<senha> -v /home/deploy/backups:/b postgres:18 \
pg_dump -h 10.99.0.3 -U <user> -d <banco> -Fc -f /b/<banco>_$(date +%Y%m%d_%H%M).dump
```
> Pré-requisito do passo 3: o commit já tem que estar publicado no registry (passo 2). Se não estiver, o CI **falha de propósito** ("faça push antes da tag") — nunca builda na tag.
+19
View File
@@ -0,0 +1,19 @@
# Deploy — Versionamento e saúde
> Situação: **como a versão é definida e onde ela aparece; como checar saúde.**
## Versão
- A versão é **definida pela tag git** (`vX.Y.Z`) — **não** se escreve versão à mão em arquivo (não existe mais `constants.ts`/`update-version.js`).
- `commit`/`build` são carimbados no **build** da imagem (imutáveis); `version`/`environment` são **injetados no deploy em runtime** (a partir da tag).
- Em **DEV** a versão aparece como `dev` (não há release); o número só existe em produção.
## Onde a versão aparece (tudo em runtime, lendo `/api/version`)
- **`vX.Y.Z` fixo no canto inferior direito** de toda página.
- Tela de **Configurações → "Sobre o sistema"**.
- O frontend **não embute** versão — consome `GET /api/version`. Fonte única = backend.
## Endpoints
- **`GET /api/version`** → `{ name, version, commit, build, environment }`.
- **`GET /api/health`** → `{ status, version, commit, environment, uptime_s, checks }`.
- **banco** é crítico: se cair → `status: down` + **HTTP 503**.
- **cache** é opcional: se cair → `status: degraded` (HTTP 200); `disabled` se desligado.
+7
View File
@@ -0,0 +1,7 @@
# Desuso (obsoletos)
Versões **antigas** dos documentos, guardadas só como histórico.
- **NÃO usar como referência** — o documento vigente está em `../` (a pasta `documentos-unicos/`).
- Cada arquivo aqui foi substituído por uma versão reescrita, conforme a **regra 4** do `../LEIA-PRIMEIRO.md`.
- Convenção do nome: `<NOME>_<AAAA-MM-DD>.md`, com aviso de **EM DESUSO** no topo.
@@ -0,0 +1,91 @@
> ⚠️ EM DESUSO desde 2026-06-17 — consolidado em /home/deploy/stack/documentos-unicos/ (ver LEIA-PRIMEIRO.md). Mantido só como histórico; NÃO usar como referência.
---
# GUIA DE DEPLOY - SCOREODONTO CRM (VPS)
Este guia detalha o processo de implantação do ScoreOdonto CRM em um servidor VPS (Ubuntu/Debian recomendado).
## 1. Pré-requisitos
* Node.js (v18+) e NPM.
* MySQL Server.
* Nginx (como Proxy Reverso).
* PM2 (Gerenciador de Processos).
## 2. Configuração do Banco de Dados
No servidor MySQL da VPS, crie o banco e as tabelas:
```sql
CREATE DATABASE sis_odonto CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```
Importe seus dados usando o `SyncView` ou o script de atualização após o deploy.
## 3. Preparação do Ambiente
Clone o repositório na VPS e instale as dependências:
```bash
cd /var/www/scoreodonto
npm install
```
Crie o arquivo `.env` na pasta raiz (`scoreodonto/`):
```env
PORT=3002
DB_HOST=localhost
DB_USER=seu_usuario
DB_PASSWORD=sua_senha
DB_NAME=sis_odonto
```
## 4. Build do Frontend
Gere os arquivos estáticos para produção:
```bash
npm run build
```
Isso criará a pasta `dist` (ou `build`).
## 5. Gerenciamento com PM2
Inicie o servidor backend:
```bash
pm2 start server.js --name "scoreodonto-api"
pm2 save
```
## 6. Configuração do Nginx
Edite o arquivo de configuração do site no Nginx (`/etc/nginx/sites-available/scoreodonto`):
```nginx
server {
listen 80;
server_name seu-dominio.com;
# Frontend
location / {
root /var/www/scoreodonto/dist;
index index.html;
try_files $uri $uri/ /index.html;
}
# Backend API
location /api {
proxy_pass http://localhost:3002;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
Ative o site e reinicie o Nginx:
```bash
sudo ln -s /etc/nginx/sites-available/scoreodonto /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
```
## 7. Ajustes de Produção
* **API URL**: O frontend agora usa o `API_URL` relativo ou configurado via environment. Como o Nginx está redirecionando `/api` para o backend, o sistema funcionará corretamente de forma transparente.
* **Notificações**: Estão unificadas no topo de cada página para fácil acesso.
* **Segurança**: Certifique-se de configurar um certificado SSL (Certbot/Let's Encrypt).
---
*Gerado automaticamente pelo Antigravity.*
@@ -0,0 +1,99 @@
> ⚠️ EM DESUSO desde 2026-06-17 — consolidado em /home/deploy/stack/documentos-unicos/ (ver LEIA-PRIMEIRO.md). Mantido só como histórico; NÃO usar como referência.
---
# 🚀 Fluxo de Deploy Multi-VPS (VPS 1, VPS 3 e VPS 4)
Este guia descreve detalhadamente o fluxo GitOps e despacho de arquivos compilados entre os servidores do ecossistema NewWhats.
---
## 🗺️ Mapa de Papéis dos Servidores
```
[ VPS 4: Builder ] ───(git push)───► [ VPS 3: Git/DB ]
│ ▲
│ │
(rsync compiles) (DB Connections)
│ │
▼ │
[ VPS 1: Produção ] ───────────────────────────┘
```
| Servidor | IP VPN | Função Principal | Fluxo de Código |
|---|---|---|---|
| **VPS 1 (App Server)** | `10.99.0.1` | Execução em Produção | Recebe os arquivos compilados da VPS 4 |
| **VPS 3 (Data Server)** | `10.99.0.3` | Banco PostgreSQL & Gitea | Centraliza o Git e o banco de dados |
| **VPS 4 (Build Server)**| `10.99.0.4` | Desenvolvimento & Compilação | Compila a plataforma e despacha via Rsync |
---
## 🔄 Fluxo de Deploy Passo a Passo
O ciclo de deploy adota o modelo **Builder-to-Host** para garantir que servidores de execução de produção (VPS 1) não consumam recursos excessivos de CPU com compilações pesadas de Webpack/Next.js e TypeScript.
```mermaid
sequenceDiagram
participant Dev as Desenvolvedor (VPS 4)
participant Gitea as Gitea (VPS 3)
participant Builder as Build Process (VPS 4)
participant Prod as Produção Docker (VPS 1)
Dev->>Gitea: git push origin main
Dev->>Builder: Executa deploy-prod-builder.sh
Builder->>Gitea: git fetch & reset --hard
Builder->>Builder: Incrementa versão (update-version.js)
Builder->>Builder: Compila Backend, Plugins & Frontend
Builder->>Prod: rsync /dist e /node_modules
Builder->>Prod: ssh restart containers
Builder->>Gitea: git push (version bump)
```
---
## 🖥️ Detalhamento por Máquina
### 1️⃣ VPS 4 — O Motor de Compilação (Build / Builder)
Todas as modificações de código e atualizações são criadas e validadas nesta máquina.
1. O desenvolvedor realiza as alterações no código local.
2. Faz o commit e envia para a VPS 3:
```bash
git add .
git commit -m "feat: minha nova funcionalidade"
git push origin main
```
3. Executa o script centralizador de deploy:
```bash
bash /home/deploy/stack/clube67/deploy-prod-builder.sh
```
* *O script limpa e reseta a pasta local para bater com a origin/main.*
* *Roda `update-version.js` para incrementar o build (ex: `v1.0.9 (build #9)`).*
* *Compila o backend, gera tipos Prisma, compila plugins e roda `next build`.*
4. **Sincronizar o incremento de versão no Gitea (Obrigatório):**
Após o deploy com sucesso, os arquivos de versão estarão alterados localmente. É vital comitá-los para não apagar o contador de deploys no Gitea na próxima execução:
```bash
git add deploys.json version.json frontend/public/deploys.json frontend/public/version.json
git commit -m "chore(deploy): bump version"
git push origin main
```
### 2️⃣ VPS 3 — O Orquestrador e Repositório (Git & Banco de Dados)
A VPS 3 é o coração dos dados do ecossistema. Ela roda o banco PostgreSQL diretamente no host e serve o Gitea.
* **Recebimento de Alterações (Push):** Quando a VPS 4 faz `git push`, a VPS 3 valida a autenticação de chaves SSH ou JWT e atualiza o branch `main`.
* **Disponibilização (Pull):** Durante o deploy automático, a VPS 4 executa `git fetch` e `git reset` apontando de volta para a VPS 3 para garantir consistência.
### 3️⃣ VPS 1 — O Servidor de Produção (App Server)
A VPS 1 roda os containers Docker `newwhats-backend-prod` e `newwhats-frontend-prod`.
* **Sem Compilação Local:** Ela nunca roda `npm run build` ou instala dependências de desenvolvimento.
* **Recebimento de Binários:** O script da VPS 4 envia apenas as pastas `/dist`, `/node_modules`, `package.json` e os arquivos do frontend prontos (`.next/`, `/public/`) via **rsync** de alta velocidade.
* **Reinício de Containers:** Após os arquivos serem transferidos para a pasta local da VPS 1, a VPS 4 faz um comando SSH seguro que dispara:
```bash
docker compose restart newwhats-backend-prod newwhats-frontend-prod
```
---
## 🚦 Boas Práticas e Resolução de Conflitos
* **Nunca altere código diretamente na VPS 1:** Qualquer edição em produção será apagada no próximo deploy, pois o `rsync --delete` substitui todos os arquivos pelos compilados na VPS 4.
* **Commite antes de Buildar:** Lembre-se sempre de subir suas alterações para o Gitea (`git push`) antes de rodar o deploy-prod-builder.sh, pois o script reseta a árvore de diretórios local para bater com o Git remoto.
@@ -0,0 +1,45 @@
> ⚠️ EM DESUSO desde 2026-06-17 — consolidado em /home/deploy/stack/documentos-unicos/ (ver LEIA-PRIMEIRO.md). Mantido só como histórico; NÃO usar como referência.
---
# 🔢 Contador de Versões e Painel de Deploy
O NewWhats conta com um sistema de versionamento automatizado e monitoramento integrado diretamente no painel administrativo (Admin settings).
---
## 1. Funcionamento do Versionamento Automático (`v1.+1`)
A cada ciclo de build executado na **VPS 4 (Build Server)**, o script `deploy-prod-builder.sh` incrementa automaticamente as versões e constrói o histórico de deploys:
1. Executa o script auxiliar `update-version.js` na raiz do projeto.
2. Esse script lê o histórico em `deploys.json`.
3. Incrementa o contador de builds (Ex: `#7` -> `#8`).
4. Incrementa a versão semântica de forma menor, ex: `v1.0.7` -> `v1.0.8`.
5. Registra metadados cruciais do commit atual do Git:
* Código de Hash do Commit.
* Mensagem do último commit.
* Autor do Deploy.
* Carimbo de data/hora exato do deploy.
6. Grava arquivos finais:
* `version.json` e `deploys.json` (usados pelo Backend).
* `frontend/public/version.json` e `frontend/public/deploys.json` (consumidos pelo Frontend).
---
## 2. A Interface do Usuário (Painel de Deploys)
Integrado perfeitamente nas Configurações do Administrador, adicionamos uma aba dedicada a **Versões**, que exibe com design moderno e premium (gradientes vibrantes e micro-animações):
* **Versão Ativa**: Exibe a versão ativa atual (ex: `v1.0.8`) com o respectivo número de build (`build #8`).
* **Último Commit**: Mostra o hash abreviado e a mensagem do último commit que disparou o deploy atual.
* **Histórico de Deploys**: Uma tabela organizada exibindo o histórico cronológico de todos os deploys efetuados, seus status, data/hora e mensagem explicativa.
* **Disparo Manual Webhook**: Um botão "Verificar atualizações" que consome o endpoint `/deploys/trigger` do backend, disparando de forma assíncrona o webhook de deploy automático na VPS 4 com pooling de progresso dinâmico na tela.
---
## 3. Segurança e Sincronização GitOps
Para garantir total consistência e impedir perda de dados:
* O script de build executa `git fetch` e `git reset --hard origin/main` antes de compilar.
* **Regra Fundamental**: Qualquer alteração para entrar em produção deve ser primeiramente comitada localmente e empurrada para o repositório Gitea (`git push origin main`). O script de deploy puxará as alterações atualizadas do servidor Git de forma automatizada e segura!
@@ -0,0 +1,54 @@
> ⚠️ EM DESUSO desde 2026-06-17 — consolidado em /home/deploy/stack/documentos-unicos/ (ver LEIA-PRIMEIRO.md). Mantido só como histórico; NÃO usar como referência.
---
# 🚀 Deploy do ScoreOdonto Dental Client (Windows)
Este documento detalha o processo de compilação e distribuição de novas atualizações do programa desktop (Windows) que fica nas máquinas das clínicas, diretamente pelo nosso servidor Linux (VPS 4).
## 🛠 Como funciona a Arquitetura
O nosso cliente é construído usando **Electron**.
A compilação cruzada (Cross-compile) acontece de forma automatizada: nossa máquina Linux (VPS 4) empacota o código-fonte em um instalador Windows `.exe`.
Após a compilação, o script joga os binários automaticamente para a pasta de produção na **VPS 1**, e o sistema de Auto-Update avisa as clínicas.
---
## 📦 Passo a Passo para Lançar uma Nova Versão
Sempre que você fizer alterações no código do cliente (ex: `index.js`, `client-monitor.js`, etc) e quiser mandar para os clientes, siga esta receita:
### Passo 1: Atualizar a Versão
Abra o arquivo `package.json` localizado na pasta do cliente (`rx.scoreodonto.com-client/`).
Altere o número da versão na linha `"version"`.
*Dica: Sempre suba a versão para que o Auto-Update do Windows reconheça a novidade (Ex: de `"1.2.7"` para `"1.2.8"`).*
### Passo 2: Executar o Script de Deploy
Pelo terminal, dentro da pasta do cliente na **VPS 4**, execute o script mágico:
```bash
cd /home/deploy/stack/rx.scoreodonto.com-client
./deploy-client.sh
```
### Passo 3: Acompanhar o Terminal
O script fará o seguinte trabalho sozinho:
1. Rodar um `npm install` garantindo os pacotes.
2. Iniciar o `electron-builder` criando a versão `.exe` para o Windows (`--win --x64`).
3. Validar se os artefatos (`.exe`, `latest.yml`, `.blockmap`) foram criados na pasta `/dist`.
4. Conectar na **VPS 1** e transferir (via `rsync`) os arquivos para a pasta pública: `/home/deploy/stack/rx.scoreodonto.com/dental-server/updates`.
Você verá a mensagem: `✅ Build e distribuição do client concluídos com sucesso!`
### Passo 4: Auto-Update nas Clínicas
A partir do momento em que a VPS 1 receber o arquivo `latest.yml` e o novo `.exe`, o sistema já está no ar.
Nas clínicas:
- Na próxima vez que o programa cliente for iniciado (ou após o intervalo padrão do `electron-updater`), ele baixará o `.exe` silenciosamente.
- Ele pedirá ao usuário para reiniciar e aplicar o update.
- Nenhuma intervenção manual é necessária!
---
## ⚠️ Solução de Problemas
- **Erro de conexão ao enviar para a VPS 1:** Verifique se as chaves SSH do usuário `deploy` na VPS 4 têm permissão irrestrita na VPS 1 (`10.99.0.1`).
- **O instalador falha no Windows:** Se você instalou pacotes nativos (C++) pesados, a compilação cruzada no Linux pode quebrar. Evite bibliotecas nativas pesadas no lado do cliente.
- **O Auto-Update não detecta a versão:** Confirme se a URL em `"publish"` dentro do `package.json` (`https://rx.scoreodonto.com/updates/`) está acessível pelo navegador e mostra a pasta de arquivos.
@@ -0,0 +1,121 @@
> ⚠️ EM DESUSO desde 2026-06-17 — consolidado em /home/deploy/stack/documentos-unicos/ (ver LEIA-PRIMEIRO.md). Mantido só como histórico; NÃO usar como referência.
---
# Deploy & Versionamento — Runbook ScoreOdonto
> Auditado contra o sistema em **17/jun/2026**. Cada item carrega seu **status real**.
>
> **Legenda:** ✅ EM PRODUÇÃO · 🧪 EM DEV (não promovido) · 🎯 ALVO (não implementado).
>
> **Produção AGORA:** `v1.0.16 · commit 471c2c2 · 2026-06-17` (`curl https://scoreodonto.com/api/version`).
> Modelo **Build Once → Promote → Deploy** completo — Passo 5 validado em v1.0.16. Tudo abaixo ✅.
---
## 1. O modelo ✅
> **Push** na `main` builda **uma vez** e publica por **commit**; a **tag `vX.Y.Z`** **re-tagueia** esse mesmo artefato (sem rebuild) e deploya. **Produção nunca builda — só executa imagens.**
```
PUSH main (commit C) TAG vX.Y.Z (no commit C)
│ │
▼ ▼
CI: build (1x) CI: promote (SEM build) ✅
publica :C + :latest re-tag :C → :vX.Y.Z (MESMO digest) + deploy
▼ ▼
registry VPS1: pull :vX.Y.Z + up --no-build
APP_VERSION=tag injetada em runtime
```
Prova (v1.0.16): `:v1.0.16` tem **digest idêntico** a `:471c2c2` — a tag é só um rótulo sobre a imagem já testada.
---
## 2. Estado por componente (verificado)
| Componente | Status | Detalhe |
|---|---|---|
| Infra VPS1/3/4 + Docker rootless | ✅ | Mapa na §3 |
| Registry (`git.clube67.com/ruicesar/...`) | ✅ | Ver `REGISTRY.md` |
| CI: job `build` publica por **commit** em push (sem `APP_VERSION`) | ✅ | `.gitea/workflows/build.yml` (runner `vps4-builder`) |
| Job `promote` por tag: re-tag `:<commit>→:vX.Y.Z` (sem rebuild) + deploy | ✅ | validado em v1.0.16 (`:v1.0.16` == `:471c2c2`) |
| Validação de integridade no promote (commit existe? digest igual? front+back mesmo commit) | ✅ | falha se o commit não foi pushado |
| Produção não builda (`image:` + `pull` + `up --no-build`) | ✅ | `docker-compose.prod.yml` |
| Banco DEV isolado em `pgdev`; prod no Postgres da VPS3 | ✅ | Ver `BANCO-DEV-ESTRATEGIA.md` |
| Versão em runtime (`/api/version`) → Configurações + telas públicas | ✅ | `useAppVersion()`; sem `APP_VERSION` manual |
| `APP_VERSION`/`APP_ENV` injetados no deploy em runtime | ✅ | `compose.prod` `environment` |
| Versão **nasce da tag git** (`constants.ts`/`update-version.js` removidos) | ✅ | Passo 5 |
---
## 3. Mapa de máquinas ✅
| Onde | Host | Papel | Docker |
|---|---|---|---|
| VPS1 | `10.99.0.1` | **Produção** (Traefik + apps) | rootless |
| VPS3 | `10.99.0.3` | Postgres (prod) + Gitea + registry | — |
| VPS4 | `10.99.0.4` | **Dev + Builder** (código; runner CI; `pgdev`) | rootless |
- Repo: `ssh://git@10.99.0.3/ruicesar/scoreodonto.com.git`. Project Compose: `scoreodontocom`.
---
## 4. De onde vem a versão (`/api/version`)
```json
{ "name": "ScoreOdonto API", "version": "v1.0.16", "commit": "471c2c2",
"build": "2026-06-17 10:35 UTC", "environment": "PROD" }
```
- **commit / build** = carimbados no **build** (imutáveis — identidade do artefato).
- **version / environment** = **injetados no deploy em runtime** (a partir da tag). A mesma imagem é promovida sob qualquer tag, sem rebuild.
- **Frontend** lê tudo de `/api/version` (`useAppVersion()`); não embute versão. Fonte única = backend.
---
## 5. Runbook — subir um release ✅
> ⚠️ **Regra de ouro:** confirme **DEV ou PRODUÇÃO**. `dev.scoreodonto.com` = VPS4 (banco `pgdev`). `scoreodonto.com` = VPS1 (real). **Nunca** `git push --force` na `main`. Push/tag exigem autorização explícita.
```bash
# 1) VPS4: validar em DEV
cd /home/deploy/stack/scoreodonto.com
node --check backend/server.js
docker compose build scoreodonto-backend scoreodonto-frontend
docker compose up -d --force-recreate scoreodonto-backend scoreodonto-frontend # https://dev.scoreodonto.com
# 2) commit + push → CI builda 1x e publica :<commit> + :latest (NÃO deploya)
git add -A && git commit -m "feat: <descrição>"
git push origin main
# 3) tag = "aprovado p/ produção" → job PROMOTE re-tagueia :<commit>→:vX.Y.Z (SEM rebuild) + deploya
# (o número da versão é livre — não precisa casar com nenhum arquivo)
git tag -a vX.Y.Z -m "release vX.Y.Z" && git push origin vX.Y.Z
# 4) verificar (sem SSH)
curl -s https://scoreodonto.com/api/version # → vX.Y.Z · <commit> · PROD
```
**Backup do banco de PRODUÇÃO antes de releases sensíveis** (via container, pois não há shell na VPS3):
```bash
docker run --rm -e PGPASSWORD=<senha> -v /home/deploy/backups:/b postgres:18 \
pg_dump -h 10.99.0.3 -U scoreodonto_user -d scoreodonto -Fc -f /b/scoreodonto_$(date +%Y%m%d_%H%M).dump
```
---
## 6. Rollback ✅
Por imagem, **sem rebuild** — na VPS1:
```bash
/home/deploy/stack/scoreodonto.com/deploy-prod.sh <tag-ou-commit-anterior> # pull + up --no-build
```
⚠️ A referência confiável é o **commit** (`:<sha>`). Tags `:vX.Y.Z` antigas (pré-Passo 5) podem ter sido republicadas com código diferente — a partir do Passo 5, `:vX.Y.Z` é sempre um alias imutável do commit. Migrações são aditivas (voltar o código é seguro). Dump em `/home/deploy/backups/` só em extremo.
---
## 7. Follow-ups (não bloqueiam) 🎯
- `GET /api/health` (monitoramento/diagnóstico).
- **Política de retenção** do registry (uma imagem `:<commit>` por push acumula).
- Reconciliar o repo na VPS1 (working tree sujo, não afeta o deploy por imagem).
Racional do modelo em `deploy.md`; histórico em `project-cicd-tag-promove-nao-rebuilda` (memória).
+13
View File
@@ -0,0 +1,13 @@
# Infra — Ambiente de desenvolvimento
> Situação: **como funciona o `dev.<projeto>` e por que dá para testar sem medo.**
- **`dev.<projeto>`** (ex.: `dev.scoreodonto.com`) roda na **VPS4**, servido por uma **imagem buildada** (nginx sobre `vite build`) — **NÃO é hot-reload (HMR)**. Editar o código **exige rebuild + recreate** do container para refletir.
- (Os processos `vite --port 5173/5180` que rodam na VPS4 são de **outros apps**, ex.: o client do RX — não do scoreodonto.)
- **Banco DEV isolado:** o backend de dev usa o container **`pgdev`** (PostGIS na VPS4), banco `<projeto>_dev`**não toca o banco de produção** (VPS3). Pasta: `/home/deploy/stack/pg-dev/`.
- `pg-dev-refresh.sh <projeto>` → repuxa dados da produção (somente leitura) para o `_ref` e recria o `_dev`.
- `pg-dev-reset.sh <projeto>` → volta o `_dev` ao estado limpo em segundos.
- **Por que importa:** testar em dev (criar lixo, rodar migração arriscada) tem **zero impacto** na produção. A produção nunca é alterada por dev.
- Em dev a versão exibida é **`dev`** (ver `../deploy/versionamento.md`).
⚠️ **Atenção:** `vite build` **não bloqueia por erro de tipo** (TypeScript) — um erro de tipo pode passar no build e só estourar em runtime. Sempre exercite a tela que mudou antes de promover.
+16
View File
@@ -0,0 +1,16 @@
# Infra — Máquinas e rede
> Situação: **quem é cada servidor e como se conectam.**
Rede privada **WireGuard** `10.99.0.0/24`.
| VPS | IP | Papel | Docker |
|---|---|---|---|
| VPS1 | 10.99.0.1 | **Produção** (Traefik/TLS + apps) | rootless |
| VPS3 | 10.99.0.3 | **Dados & Controle**: PostgreSQL, Gitea, Registry, Dragonfly, NATS, Temporal | — |
| VPS4 | 10.99.0.4 | **Dev + Builder** (código, runner do CI, banco `pgdev`) | rootless |
- **Código (fonte da verdade):** Gitea na VPS3.
- **Registry de imagens:** Container Registry embutido do Gitea — `git.clube67.com`, namespace `ruicesar/`. Não há `registry:2` separado.
- **Roteamento:** Traefik (VPS1) termina TLS e roteia por host: `<projeto>` → containers de produção locais; `dev.<projeto>``10.99.0.4:<porta>` (VPS4) via WireGuard.
- **Produção é rootless:** comandos `docker` na VPS1 usam `DOCKER_HOST=unix:///run/user/1000/docker.sock`.
+8
View File
@@ -0,0 +1,8 @@
# projetos/ — deltas específicos por projeto
Aqui fica **apenas o que torna um projeto DIFERENTE** da documentação universal (`../deploy/`, `../infra/`).
- Antes de criar algo aqui: confirme que **não** cabe na doc universal. Se couber, vai na universal.
- Um arquivo por situação que diverge, em `projetos/<projeto>/<situação>.md`.
- Cada arquivo deve: **(1) citar o que difere** do universal e **(2) referenciar** o documento universal correspondente.
- Objetivo: manter a doc universal **sempre alinhada** (sem exceções dentro dela).