docs: centraliza e reescreve a documentação em documentação/

- 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 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Builder
2026-06-16 06:45:51 +02:00
parent 0824810c4d
commit 37cc818f4c
11 changed files with 435 additions and 0 deletions
+158
View File
@@ -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: <descrição> (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 ~1030s 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 <commit-anterior> # ou: git reset --hard <commit-anterior>
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:<senha>@10.99.0.3:5432/scoreodonto" --clean <arquivo>.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 <commit-bom> → build → up -d
```
+46
View File
@@ -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 46).
### 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 <commit-bom>` + `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 36 vão eliminar.
+131
View File
@@ -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:<senha>@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-<hash>.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).
+100
View File
@@ -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`, `:<commit-curto>`.
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-<hash>.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 36 estiverem prontas, este documento deixa de ter marcações 🔜 e passa a descrever o fluxo corrente.