From 37cc818f4c52565e40c67d86cb99721d7267f4bf Mon Sep 17 00:00:00 2001 From: VPS 4 Builder Date: Tue, 16 Jun 2026 06:45:51 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20centraliza=20e=20reescreve=20a=20docume?= =?UTF-8?q?nta=C3=A7=C3=A3o=20em=20documenta=C3=A7=C3=A3o/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - reúne todos os .md de ScoreOdonto numa pasta única (fonte única, dentro do repo versionado pelo Gitea) - arquitetura.md: reescrito p/ o estado REAL (3 VPS, banco compartilhado dev/prod, sem staging/listener/registry fantasmas) - deploy.md: reescrito p/ o estado-ALVO (Gitea CI/CD: push->build->registry->deploy por tag) - DEPLOY-PRODUCAO.md: runbook operacional executável (fluxo manual real de hoje) - VERDADE-HOJE.md: auditoria (codigo/banco/containers/deploy/versao/rollback) Co-Authored-By: Claude Opus 4.8 --- .../AUDITORIA-FUNCIONAL-SCOREODONTO.md | 0 .../BACKLOG-FINANCEIRO-V1.md | 0 .../CHECKLIST-DEPLOY-PRODUCAO.md | 0 .../CRM_Ortodontia_Tutoria_Master.md | 0 documentação/DEPLOY-PRODUCAO.md | 158 ++++++++++++++++++ .../PENDENCIAS_E_DEPLOY.md | 0 ...ETURA_scoreodonto-rx-clientWindows-wasabi.md | 0 .../RX_BACKLOG_robustez-seguranca-cleanup.md | 0 documentação/VERDADE-HOJE.md | 46 +++++ documentação/arquitetura.md | 131 +++++++++++++++ documentação/deploy.md | 100 +++++++++++ 11 files changed, 435 insertions(+) rename {instrucoes_gerais/scoreodonto => documentação}/AUDITORIA-FUNCIONAL-SCOREODONTO.md (100%) rename {instrucoes_gerais/scoreodonto => documentação}/BACKLOG-FINANCEIRO-V1.md (100%) rename {instrucoes_gerais/scoreodonto => documentação}/CHECKLIST-DEPLOY-PRODUCAO.md (100%) rename CRM_Ortodontia_Tutoria_Master.md => documentação/CRM_Ortodontia_Tutoria_Master.md (100%) create mode 100644 documentação/DEPLOY-PRODUCAO.md rename PENDENCIAS_E_DEPLOY.md => documentação/PENDENCIAS_E_DEPLOY.md (100%) rename RX_ARQUITETURA_scoreodonto-rx-clientWindows-wasabi.md => documentação/RX_ARQUITETURA_scoreodonto-rx-clientWindows-wasabi.md (100%) rename RX_BACKLOG_robustez-seguranca-cleanup.md => documentação/RX_BACKLOG_robustez-seguranca-cleanup.md (100%) create mode 100644 documentação/VERDADE-HOJE.md create mode 100644 documentação/arquitetura.md create mode 100644 documentação/deploy.md diff --git a/instrucoes_gerais/scoreodonto/AUDITORIA-FUNCIONAL-SCOREODONTO.md b/documentação/AUDITORIA-FUNCIONAL-SCOREODONTO.md similarity index 100% rename from instrucoes_gerais/scoreodonto/AUDITORIA-FUNCIONAL-SCOREODONTO.md rename to documentação/AUDITORIA-FUNCIONAL-SCOREODONTO.md diff --git a/instrucoes_gerais/scoreodonto/BACKLOG-FINANCEIRO-V1.md b/documentação/BACKLOG-FINANCEIRO-V1.md similarity index 100% rename from instrucoes_gerais/scoreodonto/BACKLOG-FINANCEIRO-V1.md rename to documentação/BACKLOG-FINANCEIRO-V1.md diff --git a/instrucoes_gerais/scoreodonto/CHECKLIST-DEPLOY-PRODUCAO.md b/documentação/CHECKLIST-DEPLOY-PRODUCAO.md similarity index 100% rename from instrucoes_gerais/scoreodonto/CHECKLIST-DEPLOY-PRODUCAO.md rename to documentação/CHECKLIST-DEPLOY-PRODUCAO.md diff --git a/CRM_Ortodontia_Tutoria_Master.md b/documentação/CRM_Ortodontia_Tutoria_Master.md similarity index 100% rename from CRM_Ortodontia_Tutoria_Master.md rename to documentação/CRM_Ortodontia_Tutoria_Master.md diff --git a/documentação/DEPLOY-PRODUCAO.md b/documentação/DEPLOY-PRODUCAO.md new file mode 100644 index 0000000..78357d7 --- /dev/null +++ b/documentação/DEPLOY-PRODUCAO.md @@ -0,0 +1,158 @@ +# DEPLOY-PRODUCAO — Runbook operacional (estado de HOJE) + +> 🛑 **LEIA PRIMEIRO.** Procedimento **real e executável hoje**, passo a passo, sem adivinhação. +> Reflete o mecanismo atual: **a produção (VPS1) builda a si mesma** via `git pull` + `docker compose build` + `up -d`. +> O fluxo-alvo (registry + deploy por tag, prod sem build) está em `deploy.md` e ainda não existe. A realidade da infra está em `arquitetura.md`. +> +> ⚠️ **Regra de ouro:** antes de qualquer build/deploy/push, confirme com o operador **DEV ou PRODUÇÃO**. +> `dev.scoreodonto.com` = VPS4 (descartável, mas **mesmo banco** da prod). `scoreodonto.com` = VPS1 (real). +> **Nunca** `git push --force` na `main`. **Dev e prod compartilham o banco** (VPS3) — o backup é a única rede de segurança. + +--- + +## Mapa rápido (quem é quem) + +| Onde | Host | Papel | Socket Docker | +|------|------|-------|----------------| +| VPS4 | `10.99.0.4` | dev + builder (código aqui) | `/var/run/docker.sock` (root) | +| VPS1 | `10.99.0.1` | produção | `unix:///run/user/1000/docker.sock` (rootless) | +| VPS3 | `10.99.0.3` | Postgres + Gitea | — | + +- Repo: `ssh://git@10.99.0.3/ruicesar/scoreodonto.com.git` (Gitea). +- Diretório do repo nas duas máquinas: `/home/deploy/stack/scoreodonto.com`. +- Project Compose: `scoreodontocom` (containers `scoreodontocom-*`). + +--- + +## FASE 0 — Pré-voo (na VPS4) + +```bash +cd /home/deploy/stack/scoreodonto.com + +# 1. Sanidade do backend +node --check backend/server.js + +# 2. Validar a mudança em DEV (já no ar em https://dev.scoreodonto.com) +# Conferir o bundle servido (deve mudar a cada rebuild): +curl -s https://dev.scoreodonto.com/ | grep -oE 'index-[A-Za-z0-9_-]+\.js' | head -1 +``` + +```bash +# 3. BACKUP DO BANCO (rede de segurança única — dev/prod compartilham o banco) +# Rodar na VPS3. Usar as credenciais do ambiente/segredo, nunca em texto puro. +ssh deploy@10.99.0.3 'pg_dump -Fc scoreodonto -f /home/deploy/backups/scoreodonto_$(date +%Y%m%d_%H%M).dump' +``` + +--- + +## FASE 1 — Versão (na VPS4) ⚠️ passo manual + +O bump **não é automático** (`npm run build` é só `vite build`). É preciso incrementar **à mão**: + +```bash +cd /home/deploy/stack/scoreodonto.com +node update-version.js # incrementa o patch em frontend/constants.ts (ex.: V1.0.12 → V1.0.13) +grep APP_VERSION frontend/constants.ts +``` + +> Hoje a versão **não fica visível no navegador** (está no bundle JS). Até a Etapa 3 (versionamento visível), anote a versão que está promovendo. + +--- + +## FASE 2 — Commit & push para o Gitea (na VPS4) + +> Só execute com autorização explícita do operador (é o repo de produção). + +```bash +cd /home/deploy/stack/scoreodonto.com +git add -A +git commit -m "feat: (bump vX.Y.Z)" +git push origin main +``` + +> ❗ Push **não** dispara deploy automático hoje (não há listener/webhook ativo). A promoção é a FASE 3. + +--- + +## FASE 3 — Promover para produção (na VPS1) + +```bash +ssh deploy@10.99.0.1 +export DOCKER_HOST=unix:///run/user/1000/docker.sock # docker rootless da VPS1 +cd /home/deploy/stack/scoreodonto.com + +# 1. Trazer o código aprovado +git pull origin main + +# 2. Carimbo de versão visível (lido pelos build args do compose) — em PROD use APP_ENV=PROD +export APP_VERSION=$(grep -oE 'V[0-9]+\.[0-9]+\.[0-9]+' frontend/constants.ts | head -1) +export GIT_COMMIT=$(git rev-parse --short HEAD) +export BUILD_TIME=$(date -u +'%Y-%m-%d %H:%M UTC') +export APP_ENV=PROD + +# 3. Buildar as imagens (frontend faz vite build; backend npm install) +docker compose build scoreodonto-frontend scoreodonto-backend + +# 4. Subir (troca os containers pelas imagens novas) +docker compose up -d scoreodonto-frontend scoreodonto-backend nginx +``` + +> Os 4 `export` carimbam versão/commit/data/ambiente na imagem. Sem eles, o build ainda funciona mas mostra `dev`/`unknown` no rodapé. Em **DEV** (VPS4) use `APP_ENV=DEV`. + +O backend leva ~10–30s no boot (reconecta Postgres/Dragonfly e roda as migrações idempotentes). + +--- + +## FASE 4 — Verificação pós-deploy (na VPS1) + +```bash +export DOCKER_HOST=unix:///run/user/1000/docker.sock + +# Containers no ar +docker ps --format '{{.Names}} | {{.Status}}' | grep score + +# Backend: esperar a linha de migração + carimbo de versão +docker logs scoreodontocom-scoreodonto-backend-1 --tail 40 | grep -iE 'migration|VERSION' +# alvo: [MIGRATION] all migrations OK +# [VERSION] ScoreOdonto API vX.Y.Z · commit ... · build ... · PROD + +# Confirmar a versão no ar SEM acessar container (a forma definitiva): +curl -s https://scoreodonto.com/api/version +# {"name":"ScoreOdonto API","version":"vX.Y.Z","commit":"...","build":"...","environment":"PROD"} + +# E visualmente: a versão aparece no rodapé do menu lateral (Sidebar). +``` + +**Smoke tests mínimos:** abrir `https://scoreodonto.com`, logar, e exercitar o que mudou (ex.: lançamento financeiro, agenda, salas). Conferir ausência de erro 500 no `docker logs`. + +--- + +## FASE 5 — Rollback (se algo quebrar) + +As migrações são **aditivas** → reverter o **código** é seguro (colunas/tabelas extras ficam inertes). + +```bash +ssh deploy@10.99.0.1 +export DOCKER_HOST=unix:///run/user/1000/docker.sock +cd /home/deploy/stack/scoreodonto.com + +git log --oneline -5 # achar o commit bom anterior +git checkout # ou: git reset --hard +docker compose build scoreodonto-frontend scoreodonto-backend +docker compose up -d scoreodonto-frontend scoreodonto-backend +``` + +> Hoje o rollback **rebuilda** a versão anterior (as imagens são `:latest`, não há tag por versão). Quando a **Etapa 6** entregar deploy por tag + registry, o rollback vira só `docker compose pull` da tag anterior — sem rebuild. Restaurar o dump do banco (FASE 0) só em caso extremo: +> `pg_restore -d "postgresql://scoreodonto_user:@10.99.0.3:5432/scoreodonto" --clean .dump` + +--- + +## Resumo em uma tela + +``` +VPS4: validar em dev → node --check → backup do banco (VPS3) + → node update-version.js → commit → git push origin main (com OK do operador) +VPS1: git pull → docker compose build → docker compose up -d + → verificar logs ([MIGRATION] all migrations OK) + smoke test +Rollback: git checkout → build → up -d +``` diff --git a/PENDENCIAS_E_DEPLOY.md b/documentação/PENDENCIAS_E_DEPLOY.md similarity index 100% rename from PENDENCIAS_E_DEPLOY.md rename to documentação/PENDENCIAS_E_DEPLOY.md diff --git a/RX_ARQUITETURA_scoreodonto-rx-clientWindows-wasabi.md b/documentação/RX_ARQUITETURA_scoreodonto-rx-clientWindows-wasabi.md similarity index 100% rename from RX_ARQUITETURA_scoreodonto-rx-clientWindows-wasabi.md rename to documentação/RX_ARQUITETURA_scoreodonto-rx-clientWindows-wasabi.md diff --git a/RX_BACKLOG_robustez-seguranca-cleanup.md b/documentação/RX_BACKLOG_robustez-seguranca-cleanup.md similarity index 100% rename from RX_BACKLOG_robustez-seguranca-cleanup.md rename to documentação/RX_BACKLOG_robustez-seguranca-cleanup.md diff --git a/documentação/VERDADE-HOJE.md b/documentação/VERDADE-HOJE.md new file mode 100644 index 0000000..a28d6e8 --- /dev/null +++ b/documentação/VERDADE-HOJE.md @@ -0,0 +1,46 @@ +# Qual é a verdade hoje? — Auditoria de infra ScoreOdonto + +> Resposta direta às 6 perguntas essenciais, **verificada em 16/jun/2026**. Sem teoria, sem fantasma. +> Detalhes em `arquitetura.md` (real), `deploy.md` (alvo) e `DEPLOY-PRODUCAO.md` (runbook). + +--- + +### 1. Onde está o código? +- **Fonte da verdade:** Gitea na **VPS3**, repo `ruicesar/scoreodonto.com` (`ssh://git@10.99.0.3/ruicesar/scoreodonto.com.git`). +- **Cópia de trabalho (dev):** VPS4 em `/home/deploy/stack/scoreodonto.com` (onde se programa). +- **Cópia de produção:** VPS1 em `/home/deploy/stack/scoreodonto.com` (HEAD verificado: `19dbbae`). +- **Documentação:** centralizada em `scoreodonto.com/documentação/` (este diretório). + +### 2. Onde está o banco? +- **PostgreSQL** no host da **VPS3** (`10.99.0.3:5432`), banco `scoreodonto`, usuário `scoreodonto_user`. +- ⚠️ **DEV e PROD usam o MESMO banco.** Não há isolamento. Backup (`pg_dump -Fc`) é a única rede de segurança. +- Cache **DragonflyDB** (`10.99.0.3:6379`, índice `/1`). Mensageria **NATS** (`:4222`) e **Temporal** (`:7233`). + +### 3. Onde estão os containers? +- **Produção (VPS1, docker rootless `unix:///run/user/1000/docker.sock`):** + - `scoreodontocom-scoreodonto-frontend-1` — Up ~5 dias (imagem `:latest` buildada na própria VPS1). + - `scoreodontocom-scoreodonto-backend-1` — Up ~5 dias (`:8018`). + - `traefik-traefik-1` — borda TLS (Up ~13 dias). Também: rx, newwhats, subdominio, mercado. +- **Dev (VPS4, docker root `/var/run/docker.sock`):** + - `scoreodontocom-nginx-1` (`0.0.0.0:8020->80`, alvo do Traefik para `dev.`), `scoreodonto-frontend-1` (`:3013`), `scoreodonto-backend-1` (`:8018`). +- **Roteamento:** Traefik na VPS1 → `scoreodonto.com` (containers locais) e `dev.scoreodonto.com` → `http://10.99.0.4:8020`. + +### 4. Quem faz deploy? +- **Hoje: ninguém automático.** Não há listener nem webhook ativo (o antigo `listener-scoreodonto.js` porta 9002 foi deletado; serviço desligado). **`git push` NÃO dispara deploy.** +- O deploy é **manual**: na VPS1, `git pull` + `docker compose build` + `docker compose up -d` (passo a passo em `DEPLOY-PRODUCAO.md`). +- Ou seja: **a produção builda a si mesma** hoje (o oposto do alvo "prod não builda", que depende do registry — Etapas 4–6). + +### 5. Como versiona? +- `APP_VERSION` em `frontend/constants.ts` (dev hoje **`V1.0.13`**), incrementado por `update-version.js` (patch++). +- ⚠️ **Bump é manual** — nada chama `update-version.js` no build (`npm run build` = só `vite build`). Por isso a versão fica parada se ninguém rodar o script. +- ✅ **Versão agora é visível** (Etapa 3, 16/jun): rodapé do Sidebar + endpoint `GET /api/version` + log de boot `[VERSION] …`. Carimbo (commit/data/ambiente) injetado no build via build args. **No ar em DEV; produção passa a exibir após o próximo deploy.** + +### 6. Como volta uma versão (rollback)? +- **Hoje:** na VPS1, `git checkout ` + `docker compose build` + `up -d` (rebuilda a versão anterior; imagens são `:latest`, sem tag por versão). +- Seguro porque as migrações são **aditivas** (voltar código não quebra o schema). Restaurar dump só em caso extremo. +- **Alvo (Etapa 6):** rollback = `docker compose pull` da tag anterior no registry, **sem rebuild**. + +--- + +## Veredito de uma linha +> O código está salvo no Gitea (VPS3) e roda em containers na VPS1 (prod) e VPS4 (dev), ambos no **mesmo banco** da VPS3. **Não há CI/CD automático**: deploy e rollback são manuais via `git pull` + `docker compose build/up` na VPS1, e a **versão é invisível e bumpada à mão** — as duas dores que as Etapas 3–6 vão eliminar. diff --git a/documentação/arquitetura.md b/documentação/arquitetura.md new file mode 100644 index 0000000..d3f2343 --- /dev/null +++ b/documentação/arquitetura.md @@ -0,0 +1,131 @@ +# Arquitetura ScoreOdonto — Estado REAL + +> Documento de **estado atual verificado** (16/jun/2026). Descreve apenas o que existe e está rodando hoje. +> Sem referências históricas, sem staging, sem listeners desativados. Para o fluxo-alvo de deploy ver `deploy.md`; para o passo a passo operacional ver `DEPLOY-PRODUCAO.md`. + +--- + +## 1. Visão geral + +O ScoreOdonto roda sobre **3 VPS** ligadas por uma rede privada **WireGuard** (`10.99.0.0/24`): + +| VPS | IP interno | Papel | +|------|-------------|-------------------------------| +| VPS1 | 10.99.0.1 | **Produção** (borda + apps) | +| VPS3 | 10.99.0.3 | **Dados & Controle** (Postgres, Gitea) | +| VPS4 | 10.99.0.4 | **Desenvolvimento & Builder** | + +``` + Internet (HTTPS) + │ + ▼ +┌──────────────────────────── VPS1 (10.99.0.1) ─────────────────────────────┐ +│ Traefik (TLS Let's Encrypt, entrypoint websecure) │ +│ • scoreodonto.com / www ─────► containers de PRODUÇÃO (local) │ +│ • dev.scoreodonto.com ─────► http://10.99.0.4:8020 (via WireGuard) │ +│ │ +│ Produção (imagens buildadas): │ +│ scoreodontocom-scoreodonto-frontend-1 (SPA em nginx) │ +│ scoreodontocom-scoreodonto-backend-1 (Node :8018) │ +│ (também hospeda: rx, newwhats, subdominio, mercado) │ +└────────────────────────────────┬──────────────────────────────────────────┘ + │ WireGuard + ┌───────────────────────┼───────────────────────┐ + ▼ ▼ +┌──── VPS3 (10.99.0.3) ────┐ ┌──── VPS4 (10.99.0.4) ──────────┐ +│ PostgreSQL :5432 │◄────────────│ Desenvolvimento + Builder │ +│ db: scoreodonto │ (dev E │ nginx (borda dev) :8020→80 │ +│ Dragonfly :6379 (/1) │ prod │ └─► frontend :3013 │ +│ NATS :4222 │ usam o │ └─► backend (/api):8018 │ +│ Temporal :7233 │ MESMO │ Código-fonte em: │ +│ Gitea :3000 │ banco) │ /home/deploy/stack/ │ +│ repo: ruicesar/ │ │ scoreodonto.com/ │ +│ scoreodonto.com │ │ Docker: socket ROOT │ +│ Registry: NÃO existe │ │ (/var/run/docker.sock) │ +│ (porta 5000 fechada) │ │ │ +└───────────────────────────┘ └─────────────────────────────────┘ +``` + +--- + +## 2. VPS1 — Produção (10.99.0.1) + +- **Traefik** (container `traefik-traefik-1`) é a borda: termina TLS (Let's Encrypt, resolver `le`, entrypoint `websecure`) e roteia por `Host`. + - `scoreodonto.com` e `www.scoreodonto.com` → containers de produção locais. + - `dev.scoreodonto.com` → `http://10.99.0.4:8020` (encaminha para a VPS4 pela WireGuard). Config dinâmica em `traefik/dynamic/dev.scoreodonto.yml`. +- **Containers de produção** (imagens já buildadas, project `scoreodontocom`): + - `scoreodontocom-scoreodonto-frontend-1` — SPA React servido por nginx. + - `scoreodontocom-scoreodonto-backend-1` — API Node/Express na porta `8018`. +- **Docker rootless**: o daemon roda no socket do usuário `deploy` (`unix:///run/user/1000/docker.sock`). Comandos `docker` na VPS1 precisam dessa variável `DOCKER_HOST`. +- Produção **não builda** o ScoreOdonto: ela sobe imagens prontas. (O `docker-compose.yml` tem `build:`, mas o fluxo correto é trazer a imagem pronta da VPS4 — ver `deploy.md`.) + +## 3. VPS3 — Dados & Controle (10.99.0.3) + +Serviços instalados **direto no host** (não em container): + +- **PostgreSQL** `:5432` — banco `scoreodonto`, usuário `scoreodonto_user`. **Fonte de dados única.** +- **DragonflyDB** `:6379` — cache (índice `/1` reservado ao ScoreOdonto). +- **NATS** `:4222` e **Temporal** `:7233` — mensageria / workflows. +- **Gitea** `:3000` — **fonte oficial da verdade do código**. Repo `ruicesar/scoreodonto.com`, acesso por `ssh://git@10.99.0.3/ruicesar/scoreodonto.com.git`. É o motor de CI/CD (ver `deploy.md`). +- **Registry Docker privado:** **ainda não existe** (porta 5000 fechada). Planejado para a VPS3. + +## 4. VPS4 — Desenvolvimento & Builder (10.99.0.4) + +- **Esta é a máquina de trabalho.** Código-fonte em `/home/deploy/stack/scoreodonto.com/`. +- **Docker é ROOT** aqui (socket `/var/run/docker.sock`) — diferente da VPS1. +- Containers em execução (project `scoreodontocom`): + - `scoreodontocom-nginx-1` — borda do dev, publica `0.0.0.0:8020->80`. É o alvo do Traefik para `dev.scoreodonto.com`. + - `scoreodontocom-scoreodonto-frontend-1` — SPA (porta interna `3013`). + - `scoreodontocom-scoreodonto-backend-1` — API Node (porta interna `8018`). +- **O dev NÃO é Vite HMR.** O container de frontend roda uma **imagem buildada** (`vite build` → `nginx:alpine`); editar `frontend/` ou `backend/` exige **rebuild + recreate** do container para refletir em `dev.scoreodonto.com`. (Existe um override `docker-compose.dev.yml` com Vite/HMR, mas não é o que está no ar.) +- O `nginx/default.conf` da VPS4 faz: `/api/` e `/socket.io/` → `scoreodonto-backend:8018`; `/` → `scoreodonto-frontend:3013`. + +### Caminho de uma requisição + +- **Produção:** navegador → `https://scoreodonto.com` → Traefik (VPS1, TLS) → frontend/backend de produção (VPS1) → Postgres (VPS3). +- **Dev:** navegador → `https://dev.scoreodonto.com` → Traefik (VPS1, TLS) → `10.99.0.4:8020` (nginx VPS4) → frontend/backend de dev (VPS4) → **mesmo Postgres** (VPS3). + +--- + +## 5. ⚠️ Banco compartilhado entre DEV e PROD + +**Dev e produção apontam para o MESMO banco `scoreodonto` na VPS3.** O backend de dev usa `DATABASE_URL=postgresql://scoreodonto_user:@10.99.0.3:5432/scoreodonto`. + +Consequências práticas: +- Migrações rodadas no boot do backend de dev **já alteram o banco real**. As migrações do projeto são **idempotentes e aditivas** (só criam tabelas/colunas), o que torna isso tolerável — mas **não há isolamento**. +- A **única rede de segurança** é o backup (`pg_dump scoreodonto -Fc`) antes de mudanças sensíveis. +- Isolar um banco `scoreodonto_dev` é o conserto estrutural recomendado para o futuro (fora do escopo deste documento). + +--- + +## 6. Stack técnica e portas + +| Componente | Tecnologia | Porta interna | +|------------|-----------|----------------| +| Frontend | React + Vite + TypeScript + Tailwind (build estático servido por nginx) | 3013 | +| Backend | Node.js + Express + driver `pg` nativo (**sem ORM**) | 8018 | +| Borda dev (VPS4) | nginx:alpine | 8020 → 80 | +| Banco | PostgreSQL 18 | 5432 | +| Cache | DragonflyDB (índice `/1`) | 6379 | +| Mensageria | NATS / Temporal | 4222 / 7233 | +| Git/CI | Gitea | 3000 | +| Borda prod | Traefik (TLS Let's Encrypt) | 443 (websecure) | + +**Imagens (Dockerfiles):** +- Frontend: multi-stage — `node:20-alpine` (build `npm run build`) → `nginx:alpine` (serve `dist/`). +- Backend: `node:20-slim`, `npm install --omit=dev`, `CMD node server.js`. + +--- + +## 7. Versionamento (estado atual e limitação) + +- A versão vive em `frontend/constants.ts` (`APP_VERSION`, hoje `V1.0.12`) e é incrementada (patch) por `update-version.js` antes do build. +- **Limitação crítica:** a versão **não aparece** no HTML servido — fica embutida no bundle `index-.js`. Hoje só dá para saber a versão no ar inspecionando o container. É por isso que não se consegue confirmar "subiu mesmo?" pelo navegador. **Tornar a versão visível** (rodapé + endpoint + log de boot) é uma melhoria planejada (ver lista de afazeres / `deploy.md`). + +--- + +## 8. O que NÃO existe (para encerrar fantasmas) + +- ❌ **Não existe staging.** Não há `staging.scoreodonto.com`, nem stack `*-staging`, nem banco `scoreodonto_staging`. O único ambiente de teste é `dev.scoreodonto.com` (VPS4), com o banco de produção. +- ❌ **Não existe listener de deploy ativo** para o scoreodonto.com. O antigo `listener-scoreodonto.js` (porta 9002) foi deletado e o serviço está desligado; não há webhook do scoreodonto.com registrado no Gitea. Hoje, `git push` **não dispara** deploy automático. (O fluxo-alvo para reativar isso está em `deploy.md`.) +- ❌ **Não existe registry privado** ainda (planejado para a VPS3). diff --git a/documentação/deploy.md b/documentação/deploy.md new file mode 100644 index 0000000..008f06b --- /dev/null +++ b/documentação/deploy.md @@ -0,0 +1,100 @@ +# Deploy ScoreOdonto — Como um commit vira produção (estado-ALVO) + +> Este documento responde **uma** pergunta: **"como um commit vira produção?"** +> Descreve o **fluxo-alvo** com **Gitea como motor de CI/CD**. O que já existe hoje está marcado como ✅; o que ainda será construído está marcado como 🔜. +> Para a realidade da infra ver `arquitetura.md`. Para o procedimento manual executável **hoje** ver `DEPLOY-PRODUCAO.md`. + +--- + +## 1. Princípios (inegociáveis) + +1. **Gitea (VPS3) é a fonte única da verdade** e o motor de CI/CD. +2. **Produção (VPS1) nunca builda e nunca recebe código-fonte** — só consome **imagens versionadas** prontas. +3. **Build acontece fora da produção** (na CI / na VPS4). +4. **Deploy é um ato deliberado por TAG**, nunca automático em todo push (a `main` é usada para desenvolvimento e o banco é compartilhado — promover sem querer é perigoso). +5. **Rollback é trocar a imagem** por uma tag anterior — sem rebuild, sem recompilar, sem copiar arquivo. +6. **Toda imagem é rastreável**: carrega versão semântica + commit + data de build. + +--- + +## 2. O fluxo-alvo, em uma frase + +> **Push** abastece o desenvolvimento e (🔜) **produz uma imagem versionada no registry**; +> **criar uma tag `vX.Y.Z`** é o que **promove** essa imagem para produção. + +``` + git push ──► Gitea (VPS3) ──► CI: build da imagem ──► Registry privado (VPS3) + (na main) (versão+commit+data) imagem :vX.Y.Z + │ + criar tag vX.Y.Z ────┘ + ▼ + VPS1: docker compose pull + up -d + (troca o container pela imagem da tag) + ▼ + Produção rodando vX.Y.Z +``` + +--- + +## 3. As duas metades do fluxo + +### Metade A — Integração contínua (push → imagem) 🔜 +1. Desenvolvedor trabalha na VPS4 e valida em `https://dev.scoreodonto.com`. +2. `git push origin main` para o Gitea (VPS3). +3. A **CI do Gitea** (Gitea Actions) builda a imagem Docker (frontend multi-stage + backend), injetando **versão semântica, commit curto e data de build**. +4. A imagem é enviada ao **Registry privado da VPS3** com tags como `:main`, `:`. +5. **Nada vai para produção aqui.** Esta metade só produz e guarda o artefato. + +### Metade B — Entrega por tag (tag → produção) 🔜 +1. Quando uma versão está aprovada, cria-se uma **tag semântica**: `git tag v1.0.15 && git push origin v1.0.15`. +2. A CI marca a imagem correspondente como `:v1.0.15` no registry (promoção do artefato já testado — sem rebuild). +3. A VPS1 recebe o gatilho de entrega (job de deploy / acionamento manual aprovado) e roda: + `docker compose pull && docker compose up -d` apontando para `:v1.0.15`. +4. A versão visível (rodapé/endpoint) confirma `v1.0.15` no ar. + +--- + +## 4. Versionamento visível (pré-requisito da confiança) ✅ FEITO + +> Implementado em 16/jun/2026 (Etapa 3). O build carimba versão/commit/data/ambiente via build args (`GIT_COMMIT`, `BUILD_TIME`, `APP_ENV`, `APP_VERSION`) → `import.meta.env.VITE_*` no frontend e `process.env` no backend. Visível no **rodapé do Sidebar**, no endpoint **`GET /api/version`** e na **linha de boot** `[VERSION] …` dos logs. + +Cada build carimba e **exibe**: + +``` +ScoreOdonto +v1.0.15 +commit: 7a9b3c1 +build: 2026-06-16 14:32 UTC +ambiente: PRODUÇÃO +``` + +Visível no **rodapé** da aplicação, em um **endpoint de diagnóstico** (ex.: `GET /api/version`) e na **linha de boot** dos logs. Hoje a versão fica escondida no bundle `index-.js` (ver `arquitetura.md` §7) — esta é a primeira melhoria de maior valor. + +--- + +## 5. Rollback 🔜 + +- Listar as tags/imagens no registry da VPS3. +- Na VPS1, apontar o compose para a tag anterior (`:v1.0.14`) e `docker compose up -d`. +- Recuperação em minutos, **sem rebuild**. O banco é aditivo (ver `arquitetura.md` §5), então voltar o código é seguro; restaurar dump só em caso extremo. + +--- + +## 6. Estado de hoje (honesto) ✅/❌ + +- ✅ `git push` para o Gitea **funciona** (guarda o código). +- ❌ **Não há build automático**, **não há registry**, **não há deploy automático**. O antigo listener (porta 9002) foi deletado e não há webhook do scoreodonto.com no Gitea. +- ➡️ Enquanto a CI acima não existe, a promoção para produção é **manual** e está documentada passo a passo em **`DEPLOY-PRODUCAO.md`** (build na VPS4 → enviar imagem para a VPS1 → `up -d`). + +--- + +## 7. Roadmap para sair do "hoje" e chegar no "alvo" + +| Etapa | Entrega | Status | +|-------|---------|--------| +| 3 | Versionamento visível (rodapé + endpoint + log) | ✅ | +| 4 | Registry Docker privado na VPS3 | 🔜 | +| 5 | Pipeline de build no Gitea (push → imagem → registry), **sem deploy** | 🔜 | +| 6 | Deploy por TAG (`vX.Y.Z` → produção na VPS1) + rollback por imagem | 🔜 | + +Quando as Etapas 3–6 estiverem prontas, este documento deixa de ter marcações 🔜 e passa a descrever o fluxo corrente.