37cc818f4c
- 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>
94 lines
6.5 KiB
Markdown
94 lines
6.5 KiB
Markdown
# RX — Backlog de robustez, segurança e limpeza
|
||
|
||
> Tarefas derivadas da revisão de 2026-06-12 (multi-tenant + client.exe + storage).
|
||
> Prioridade: **P1** (faria primeiro) · **P2** · **P3**. Marcar `[x]` ao concluir.
|
||
> Regra do projeto: nada vai pra prod sem autorização; dev.rx e prod.rx **compartilham
|
||
> DB+Wasabi** (ver T3.1 — separar é o que mais reduz risco).
|
||
|
||
---
|
||
|
||
## 3. Robustez do RX / resync
|
||
|
||
- [ ] **T3.1 (P1) — Separar DEV de PROD (DB + Wasabi).** Hoje compartilham o mesmo
|
||
Postgres (`dental_images`) e o mesmo bucket → testes mexem em dado real. Opções:
|
||
banco `dental_images_dev` e/ou prefixo/bucket Wasabi por ambiente (`RX_ENV`).
|
||
- [x] **T3.2 (P1) — Healthcheck de reconciliação Wasabi↔banco** por `clinica_id`/`tenant_id`.
|
||
FEITO (dev): `GET /api/admin/rx-health` (RX) — contagens por (tenant,clínica) + cron +
|
||
`?clinica_id=&checkLimit=N` (HEAD-check de ausentes). Proxy `GET /api/rx/health`
|
||
(scoreodonto, superadmin). Validado: Consultt 2723 imgs/513 pac, 0 ausentes em 15. Commit 016305e.
|
||
- [ ] **T3.3 (P2) — Índice único parcial** `images(original_filename) WHERE enabled=1`
|
||
como trava de duplicata no banco. ⚠️ Criar CONCURRENTLY e fora do boot (se houver
|
||
duplicata, a criação no boot derrubaria o servidor).
|
||
- [ ] **T3.4 (P2) — Remover `send-image` legado** após confirmar que todo `.exe` em campo
|
||
é ≥ Direct Upload (1.3.x). Elimina um caminho de upload + base64 pela VPS.
|
||
- [ ] **T3.5 (P2) — Throttle/progresso no resync.** `trigger-sync` reescaneia todos os PNGs;
|
||
em clínica grande é pesado → lote + reporte de progresso.
|
||
- [ ] **T3.6 (P3) — `check-image-exists`**: garantir que checa linha no banco **E** objeto no
|
||
Wasabi (senão objeto sumido nunca é reenviado).
|
||
|
||
## 4. Client.exe
|
||
|
||
- [ ] **T4.1 (P1) — Code signing do instalador NSIS** (evita SmartScreen nas clínicas).
|
||
- [ ] **T4.2 (P1) — `machine_token` em repouso**: proteger no config local (DPAPI/cripto).
|
||
- [ ] **T4.3 (P2) — Retry/backoff + fila persistente** nos PUT do Wasabi e na `uploadQueue`
|
||
(sobreviver a restart / internet ruim).
|
||
- [ ] **T4.4 (P2) — Telemetria pro `/clients`**: client envia `last_sync`, profundidade da
|
||
fila e últimos erros → página mostra saúde real.
|
||
- [ ] **T4.5 (P2) — `lookupPatientInfo` tolerante a versão** do banco do sensor RF.
|
||
- [ ] **T4.6 (P3) — Pipeline de auto-update**: automatizar envio de `Setup x.y.z.exe` +
|
||
`latest.yml` pro `updates/` do prod ao rebuildar.
|
||
|
||
## 5. Segurança / hardening
|
||
|
||
- [ ] **T5.1 (P1) — `api_token` global criptografado em repouso** (hoje texto puro em
|
||
`settings.rx_config_global`) + rotação + idealmente token de escopo reduzido (não-god).
|
||
- [x] **T5.2 (P1) — Auditar escopo GLOBAL do `tenantGuard`** — FEITO (dev). 🔴 Achado crítico:
|
||
a família `/api/sync/*` (sync GLOBAL legado) usava `tenantGuard` → **burlável sem clinicaId**;
|
||
`DELETE /api/sync/truncate-all` fazia `TRUNCATE pacientes,agendamentos,financeiro,leads,guias`
|
||
de **todas as clínicas** → qualquer usuário logado (até funcionário) apagava o banco inteiro.
|
||
**Corrigido**: os 13 endpoints `/api/sync/*` → `superadminGuard`. Provado: não-superadmin
|
||
agora recebe **403** (antes truncava). 2º achado: **`/api/settings/google-credentials`** GET+POST
|
||
(credenciais OAuth GLOBAIS da plataforma) também era `tenantGuard` → qualquer logado sobrescrevia →
|
||
**→ `superadminGuard`** (403 p/ não-super; front só chama p/ superadmin). **Auditoria completa**:
|
||
todos os demais `tenantGuard` (clinica-sync, dashboard, agendamentos, avaliacoes, financeiro,
|
||
guias, leads/:id/converter, DELETE :id, rx/devices) exigem `req.clinicaId` + `WHERE clinica_id` → seguros.
|
||
- [ ] **T5.3 (P1) — Auth do `remote-crud-patient`** (socket escreve no banco local do client):
|
||
validar papel/escopo forte no servidor.
|
||
- [ ] **T5.4 (P2) — Defesa em profundidade no RX server**: validar tenant nos endpoints admin
|
||
(não confiar só no proxy do scoreodonto).
|
||
- [ ] **T5.5 (P2) — Revisar os 9 dias de WIP** (`auth.js`, `database.js`, `storage.js`, páginas)
|
||
antes do prod.
|
||
- [!] **T5.6 (P3→P0) — Auditar histórico do git por segredos** — FEITO. 🔴🔴🔴 ACHADOS CRÍTICOS:
|
||
- `dental-server/bkp/docs/ENV-CONFIG.txt` tem o **`JWT_SECRET` REAL** (confirmado == o do
|
||
servidor) commitado → **qualquer um com acesso ao repo forja JWT de admin do RX**.
|
||
- `INSTRUCOES-SERVIDOR-VPS.txt` tem o **`DB_PASSWORD`/`REDIS_PASSWORD` reais** em texto puro.
|
||
AÇÃO OBRIGATÓRIA (decisão do usuário, não automatizei):
|
||
1. **Rotacionar JWT_SECRET** (invalida tokens, força re-login) — fecha a forja.
|
||
2. **Rotacionar senha do Postgres/Redis** (10.99.0.3).
|
||
3. Remover os segredos dos arquivos versionados + **scrub do histórico** (git filter-repo/BFG).
|
||
`.secrets` já está no .gitignore (feito antes); isso NÃO resolve os já commitados → rotação é mandatória.
|
||
|
||
## 6. Limpeza / tech-debt
|
||
|
||
- [ ] **T6.1 (P1) — Consolidar os 4 caminhos de upload** (`image-upload-direct`, `send-image`,
|
||
`/api/images/upload`, `/upload-file`) → manter 1–2, remover o resto.
|
||
- [ ] **T6.2 (P2) — Simplificar `storage.js` pós-resync** (remover fallback legado quando todos
|
||
os objetos estiverem na key nova).
|
||
- [ ] **T6.3 (P2) — Remover diretórios mortos** (`bkp/`, `public_legacy/`, `old-root-files/`).
|
||
- [ ] **T6.4 (P3) — Upgrade Node 20 → 22** (AWS SDK exigirá ≥22 em 2027).
|
||
- [ ] **T6.5 (P3) — Log levels** (info/debug/error) no servidor RX.
|
||
- [ ] **T6.6 (P3) — Passada final de comentários/padronização** no fluxo RX.
|
||
|
||
---
|
||
|
||
### Log
|
||
- **2026-06-12** — T3.2 concluída (healthcheck de reconciliação, read-only).
|
||
- **2026-06-12** — T5.2 concluída. 🔴 Fechado RCE-like: `/api/sync/truncate-all` (e família) +
|
||
`/api/settings/google-credentials` deixavam qualquer logado truncar o banco / trocar OAuth global →
|
||
agora `superadminGuard` (403 p/ não-super). Mudanças no **scoreodonto (dev), não commitadas**.
|
||
- **2026-06-12** — T3.6 auditada: `check-image-exists` já está correto (checa banco+Wasabi, apaga órfão). Sem fix.
|
||
- **2026-06-12** — T5.6 🔴🔴🔴: JWT_SECRET REAL + senha de DB/Redis commitados (ENV-CONFIG.txt,
|
||
EXEMPLO-ENV.txt, INSTRUCOES-SERVIDOR-VPS.txt, test-db2.js). **Passo 3 FEITO** (redigidos do working
|
||
tree, commits 4616f20+2b679a5). **PENDENTE/MANDATÓRIO (usuário): rotacionar JWT_SECRET + senha
|
||
Postgres/Redis + scrub do histórico** — até lá, a exposição persiste no histórico do Gitea.
|