diff --git a/Deploy-V.1.0.4.md b/Deploy-V.1.0.4.md
new file mode 100644
index 0000000..f2fd73d
--- /dev/null
+++ b/Deploy-V.1.0.4.md
@@ -0,0 +1,319 @@
+# 🚀 Deploy V.1.0.4 — Nomes de Sistema e Cliente Congelados
+
+> Versão **1.0.4** — inclui tudo da 1.0.3 e formaliza a **regra de nomes congelados**:
+> o nome do sistema (`Score Client`) e o nome do executável do cliente Windows
+> (`ScoreOdonto Dental Client Setup X.Y.Z.exe`) são **fixos e imutáveis** —
+> apenas o número de versão pode mudar.
+
+---
+
+## 📋 Índice
+
+1. [Arquitetura Multi-VPS](#1-arquitetura-multi-vps)
+2. [Pipeline GitOps (Servidor — Modelo A)](#2-pipeline-gitops-modelo-a)
+3. [O Listener do Webhook](#3-o-listener-do-webhook)
+4. [Versionamento — Servidor](#4-versionamento--servidor)
+5. [Cliente Windows — Build, Publicação e Auto-Update](#5-cliente-windows--build-publicacao-e-auto-update)
+6. [🔒 Nomes Congelados — Regra Obrigatória](#6-nomes-congelados--regra-obrigatória)
+7. [Erros comuns e soluções](#7-erros-comuns-e-soluções)
+8. [Troubleshooting](#8-troubleshooting)
+9. [Changelog](#9-changelog)
+
+---
+
+## 1. Arquitetura Multi-VPS
+
+| Servidor | IP (VPN) | Função |
+|---|---|---|
+| **VPS 1 — App** | `10.99.0.1` | Produção (Docker rootless) + serve `/updates/` do cliente |
+| **VPS 3 — Data/Git** | `10.99.0.3` | Gitea + PostgreSQL |
+| **VPS 4 — Builder** | `10.99.0.4` | Build do servidor **e** do cliente Windows (cross-compile) |
+| **Wasabi** | S3-compatível | Storage de imagens (não no disco) |
+
+---
+
+## 2. Pipeline GitOps (Modelo A)
+
+```
+git push origin main (rx.scoreodonto.com)
+ ↓
+Gitea dispara webhook → VPS4:9003/webhook
+ ↓
+listener-rx.js → deploy-prod.sh
+ ↓
+VPS4: build React (Vite) → docker compose build app → docker save → app.tar.gz
+ ↓
+VPS4: rsync app.tar.gz + docker-compose.yml + version.txt → VPS1
+ ↓
+VPS1: docker load + docker compose up -d --no-deps app
+ ↓
+✅ Deploy concluído (~30-40 s)
+```
+
+> ⚠️ O build do React roda com `NODE_ENV=development npm install --include=dev` porque
+> o `vite` é devDependency e o listener roda com `NODE_ENV=production` (que pula devDeps).
+
+---
+
+## 3. O Listener do Webhook
+
+**Arquivo:** `/home/deploy/stack/webhook-listener/listener-rx.js` (porta 9003)
+
+- Valida token (`x-gitea-token` ou `?token=...`)
+- **Trava de concorrência** (`isBuilding`) + **anti-loop** (ignora `chore(deploy): bump version`)
+- Dispara `deploy-prod.sh` e reporta status ao Gitea (pending → success/failure)
+
+> 📌 **O cliente Windows NÃO tem webhook.** O `deploy-client.sh` é **manual** (ver seção 5).
+> Essa é a causa nº 1 de defasagem de versão do cliente.
+
+---
+
+## 4. Versionamento — Servidor
+
+**Fonte de verdade:** `dental-server/version.txt` (lido em runtime, injetado no sidebar).
+`package.json` **nunca** é tocado no bump (preserva cache do Docker). Detalhes na 1.0.2.
+
+```bash
+# Versão servida (dentro do container é a fonte de verdade):
+ssh deploy@10.99.0.1 "docker exec rx_scoreodonto_app cat /app/version.txt"
+curl -s https://rx.scoreodonto.com/ | grep -o 'v[0-9]\.[0-9]\.[0-9]'
+```
+
+---
+
+## 5. Cliente Windows — Build, Publicação e Auto-Update
+
+Projeto: **`rx.scoreodonto.com-client`** (Electron + electron-updater).
+
+### 5.1. Fonte de verdade
+
+Tudo parte do `package.json` do cliente:
+
+```bash
+grep '"version"' /home/deploy/stack/rx.scoreodonto.com-client/package.json
+# "version": "1.2.7"
+```
+
+O `electron-builder` lê esse número e gera **3 artefatos** por versão:
+`ScoreOdonto Dental Client Setup X.Y.Z.exe`, `...exe.blockmap` e `latest.yml`.
+
+### 5.2. As DUAS pastas (e por que confundem)
+
+| Pasta | Onde | O que é |
+|---|---|---|
+| `rx.scoreodonto.com-client/dist/` | **VPS4** | **Saída do build.** Tem todos os `.exe` já gerados. |
+| `rx.scoreodonto.com/dental-server/updates/` | **VPS1** | **O que é servido** em `https://rx.scoreodonto.com/updates/`. É o que as clínicas enxergam. |
+
+> 🔑 **Buildar (gerar no `dist/`) ≠ publicar (copiar para `updates/` na VPS1).**
+> O cliente só "existe" para as clínicas quando o `latest.yml` da **VPS1** aponta para a nova versão.
+
+### 5.3. Ciclo completo — `deploy-client.sh`
+
+```bash
+cd /home/deploy/stack/rx.scoreodonto.com-client
+bash deploy-client.sh
+```
+
+O script faz, em ordem:
+```
+1. npm install
+2. npx electron-builder --win --x64 --publish never → gera dist/*.exe + dist/latest.yml (VPS4)
+3. valida que dist/ tem .exe e latest.yml
+4. rsync dist/*.exe dist/*.yml dist/*.blockmap → VPS1:/.../dental-server/updates/ ← PUBLICAÇÃO
+```
+
+**Só termina o trabalho quando o passo 4 roda.** Se você buildar manualmente
+(`npm run dist`) e parar aí, o `dist/` na VPS4 fica novo, mas a VPS1 continua na versão antiga.
+
+### 5.4. Fluxo de auto-update nas clínicas
+
+```
+App do cliente inicia
+ ↓
+electron-updater: GET https://rx.scoreodonto.com/updates/latest.yml
+ ↓
+versão do yml > versão instalada? → baixa o .exe e instala ao reiniciar
+ → senão, nada acontece
+```
+
+### 5.5. Verificação rápida (3 pontos têm que bater)
+
+```bash
+# 1. Fonte (código):
+grep '"version"' /home/deploy/stack/rx.scoreodonto.com-client/package.json
+
+# 2. Publicado na VPS1 (o que conta):
+ssh deploy@10.99.0.1 "head -1 /home/deploy/stack/rx.scoreodonto.com/dental-server/updates/latest.yml"
+
+# 3. O que o auto-updater realmente baixa (HTTP público):
+curl -s https://rx.scoreodonto.com/updates/latest.yml | head -1
+```
+Se os três não baterem → rode `deploy-client.sh` até o fim.
+
+---
+
+## 6. 🔒 Nomes Congelados — Regra Obrigatória
+
+> ⛔ **Esta seção define regras imutáveis do projeto. Agentes de IA e desenvolvedores
+> NÃO devem alterar os nomes abaixo sem aprovação explícita do responsável pelo projeto.**
+
+### 6.1. Nome do sistema (painel web)
+
+| Local | Valor fixo |
+|---|---|
+| `dental-client/index.html` → `
` | `Score Client — Gerenciador de Imagens` |
+| `src/components/Sidebar.jsx` → cabeçalho | `Score Client` |
+| `src/pages/LoginPage.jsx` → `` | `Score Client` |
+| `src/pages/DownloadPage.jsx` → `` | `Score Client — Cliente Windows` |
+
+**O nome `Score Client` é fixo.** Nunca substituir por variações como `RF Dental`, `RFDental`,
+`ScoreOdonto`, `RX Dental` ou qualquer outro. Se houver refatoração de UI, manter exatamente
+`Score Client`.
+
+### 6.2. Nome do executável do cliente Windows
+
+O `electron-builder` gera o instalador com o nome definido em `package.json` → campo `productName`:
+
+```json
+{
+ "productName": "ScoreOdonto Dental Client"
+}
+```
+
+Isso resulta em arquivos com o padrão:
+
+```
+ScoreOdonto Dental Client Setup X.Y.Z.exe
+ScoreOdonto Dental Client Setup X.Y.Z.exe.blockmap
+latest.yml → path: ScoreOdonto Dental Client Setup X.Y.Z.exe
+```
+
+**Apenas `X.Y.Z` (o número de versão) pode mudar.** O prefixo `ScoreOdonto Dental Client Setup `
+é imutável. Alterar o `productName` no `package.json` quebra:
+- O `latest.yml` gerado (nome do `path` muda → auto-updater não encontra o arquivo)
+- A URL de download no painel web (que lê `path:` do `latest.yml` dinamicamente)
+- O histórico de instalações nas clínicas (Windows trata como produto diferente)
+
+### 6.3. URL de download — como funciona (e por que não usar nome hardcoded)
+
+O `DownloadPage.jsx` lê o nome real do arquivo a partir do `latest.yml` **em tempo de execução**:
+
+```javascript
+fetch('/updates/latest.yml')
+ .then(r => r.text())
+ .then(t => {
+ const vMatch = t.match(/version:\s*([\d.]+)/);
+ if (vMatch) setVersion(vMatch[1]); // ex: "1.2.6"
+ const pMatch = t.match(/^path:\s*(.+)$/m);
+ if (pMatch) setExeFilename(pMatch[1].trim()); // ex: "ScoreOdonto Dental Client Setup 1.2.6.exe"
+ });
+
+// URL final construída:
+const downloadUrl = `/updates/${encodeURIComponent(exeFilename)}`;
+```
+
+> ✅ Isso garante que o botão de download sempre aponta para o arquivo correto da versão em produção,
+> sem hardcode de nome — mas **depende de que o `productName` no `package.json` seja mantido exato**.
+
+### 6.4. Checklist antes de qualquer refatoração de UI ou cliente
+
+- [ ] O título da aba do browser ainda é `Score Client — Gerenciador de Imagens`?
+- [ ] O cabeçalho da sidebar ainda exibe `Score Client`?
+- [ ] O `` da tela de login ainda é `Score Client`?
+- [ ] O `productName` no `package.json` do cliente ainda é `ScoreOdonto Dental Client`?
+- [ ] O `latest.yml` em produção tem `path: ScoreOdonto Dental Client Setup X.Y.Z.exe`?
+
+Se qualquer item acima for `NÃO` → reverter antes de continuar.
+
+---
+
+## 7. Erros comuns e soluções
+
+### ❌ Erro A — Cliente em uma versão, servidor servindo outra (mais antiga)
+**Sintoma:** `package.json` = `1.2.7`, mas `updates/latest.yml` na VPS1 = `1.2.6`.
+As clínicas não recebem o update e novas instalações baixam a versão velha.
+
+**Causa:** a versão foi buildada no `dist/` da VPS4 mas **o `rsync → VPS1` (passo 4 do
+`deploy-client.sh`) não rodou**. Buildar não publica.
+
+**Diagnóstico:**
+```bash
+# Build existe no dist/ (VPS4)?
+ls -1 /home/deploy/stack/rx.scoreodonto.com-client/dist/*.exe | sort -V | tail -1
+cat /home/deploy/stack/rx.scoreodonto.com-client/dist/latest.yml | head -1 # ex: 1.2.7
+
+# Mas a VPS1 está atrás?
+ssh deploy@10.99.0.1 "head -1 /home/deploy/.../dental-server/updates/latest.yml" # ex: 1.2.6
+```
+Versões diferentes = build não publicado.
+
+**Solução (rápida, sem rebuild — artefato já existe e é válido):**
+```bash
+cd /home/deploy/stack/rx.scoreodonto.com-client
+rsync -avz dist/*.exe dist/*.yml dist/*.blockmap \
+ deploy@10.99.0.1:/home/deploy/stack/rx.scoreodonto.com/dental-server/updates/
+```
+**Solução (canônica):** `bash deploy-client.sh` (rebuilda e publica).
+
+---
+
+### ❌ Erro B — Botão de download diz "arquivo não disponível"
+**Sintoma:** ao clicar em "Baixar Instalador" na página `/download`, o browser retorna 404.
+
+**Causa mais comum:** o `path:` no `latest.yml` não bate com o nome real do arquivo em `updates/`.
+Isso acontece se o `productName` foi alterado no `package.json` do cliente, gerando um `.exe`
+com nome diferente do que o `latest.yml` antigo listava.
+
+**Diagnóstico:**
+```bash
+# Nome que o painel web vai pedir:
+ssh deploy@10.99.0.1 "grep '^path:' /home/deploy/stack/rx.scoreodonto.com/dental-server/updates/latest.yml"
+# ex: path: ScoreOdonto Dental Client Setup 1.2.6.exe
+
+# Arquivos que existem de fato:
+ssh deploy@10.99.0.1 "ls /home/deploy/stack/rx.scoreodonto.com/dental-server/updates/*.exe"
+```
+Se os nomes não baterem → o `productName` foi alterado ou o `rsync` não foi executado.
+
+**Solução:** restaurar o `productName` para `ScoreOdonto Dental Client` e rodar `deploy-client.sh`.
+
+---
+
+### ❌ Erro C — `vite: not found` no deploy do servidor
+**Causa:** listener roda com `NODE_ENV=production` → `npm install` pula devDependencies (vite).
+**Solução:** no `deploy-prod.sh`, `NODE_ENV=development npm install --include=dev` antes do `vite build`.
+
+### ❌ Erro D — Imagens do RX não aparecem (placeholder cinza, sem erro no DevTools)
+**Causa:** endpoint de thumbnail retornava JSON `{url}` enquanto o `
` apontava direto para ele.
+**Solução:** o endpoint serve **bytes** (`image/jpeg`); gera a thumb on-the-fly e faz backfill no Wasabi.
+
+### ❌ Erro E — Wasabi 403 após trocar credenciais
+**Causa:** salvar credenciais no banco **não recarregava** o cliente S3 em memória.
+**Solução:** `storage-config` chama `storage.loadConfigFromDb()` após salvar.
+
+---
+
+## 8. Troubleshooting
+
+| Problema | Diagnóstico | Solução |
+|---|---|---|
+| **Cliente desatualizado nas clínicas** | `package.json` ≠ `updates/latest.yml` na VPS1? | Rodar `deploy-client.sh` **até o passo 4** (ou rsync do `dist/`) |
+| **Botão download → 404** | `path:` no `latest.yml` ≠ arquivo real em `updates/`? | Verificar `productName`; restaurar para `ScoreOdonto Dental Client` e rebuildar |
+| Build do cliente falha | Wine/electron-builder na VPS4 | Ver log; `npx electron-builder --win --x64 --publish never` |
+| Clínica não atualiza mesmo com yml novo | versão instalada ≥ yml? | Auto-update só sobe versão; conferir semver |
+| Deploy do servidor `vite: not found` | `NODE_ENV=production` no install | `--include=dev` no `deploy-prod.sh` |
+| Imagens em branco | thumb retornando JSON? | Endpoint deve servir **bytes** image/jpeg |
+| Wasabi 403 | credenciais recarregadas? | `loadConfigFromDb()` após salvar config |
+| Deploy do servidor lento (3+ min) | Modelo B? | Modelo A (build na VPS4) |
+
+---
+
+## 9. Changelog
+
+| Versão | Data | O que mudou |
+|---|---|---|
+| **1.0.4** | 2026-05-31 | **Nomes congelados:** formaliza que `Score Client` (sistema) e `ScoreOdonto Dental Client Setup` (executável) são imutáveis. Documenta o Erro B (404 no download por nome errado), checklist de refatoração e como o `DownloadPage.jsx` resolve o nome dinamicamente via `latest.yml`. |
+| 1.0.3 | 2026-05-31 | Ciclo completo do Cliente Windows (build `dist/` na VPS4 ≠ publicação `updates/` na VPS1). Documenta a armadilha "buildado mas não publicado", verificação em 3 pontos, e o `vite: not found`. |
+| 1.0.2 | 2026-05-30 | RX: switch para Modelo A (build VPS4), erros comuns, Wasabi. Deploy ~30-40s. |
+| 1.0.1 | 2026-05-30 | Consolidação inicial: deploy + versionamento + segurança. |
+| 1.0.0 | 2026-05-30 | Versão inicial. |
diff --git a/Home.md b/Home.md
index 0942a92..c240432 100644
--- a/Home.md
+++ b/Home.md
@@ -4,12 +4,13 @@ Documentação da automação de deploy GitOps (Gitea + Multi-VPS) e versionamen
## Versão atual
-- **[Deploy V.1.0.3](Deploy-V.1.0.3)** ← versão mais recente — ciclo completo do **Cliente Windows**
- (build na VPS4 vs publicação na VPS1), armadilha "buildado mas não publicado", verificação em 3 pontos,
- além de tudo do servidor (Modelo A, Wasabi, versionamento).
+- **[Deploy V.1.0.4](Deploy-V.1.0.4)** ← versão mais recente — **nomes congelados**: `Score Client`
+ (sistema) e `ScoreOdonto Dental Client Setup` (executável) são imutáveis; apenas o número de versão
+ pode mudar. Inclui checklist de refatoração, Erro B (404 no download) e tudo da 1.0.3.
## Arquivo de versões anteriores
+- [Deploy V.1.0.3](Deploy-V.1.0.3) — ciclo completo do Cliente Windows (build na VPS4 vs publicação na VPS1).
- [Deploy V.1.0.2](Deploy-V.1.0.2) — Modelo A otimizado para Wasabi (deploy ~30-40s).
- [Deploy V.1.0.1](Deploy-V.1.0.1) — consolidação: deploy + versionamento + segurança.
- [Deploy V.1.0.0](Deploy-V.1.0.0) — versão inicial (apenas deploy, sem versionamento).