5049ce9b8b
- Pasta única scoreodonto.com/doc/ com 9 docs que prestam: VERDADE-HOJE (estado, principal), DEPLOY-PRODUCAO (runbook), BANCO-DEV-ESTRATEGIA, REGISTRY, AUDITORIA-FUNCIONAL, BACKLOG-FINANCEIRO-V1, CRM_Ortodontia, RX_ARQUITETURA, RX_BACKLOG. - Removidos os docs de infra sobrepostos/desatualizados (estado consolidado em VERDADE-HOJE; histórico fica no git): arquitetura.md, deploy.md, CHECKLIST-DEPLOY-PRODUCAO.md, PENDENCIAS.md, PENDENCIAS_E_DEPLOY.md. - Pasta documentação/ eliminada. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.5 KiB
6.5 KiB
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: bancodental_images_deve/ou prefixo/bucket Wasabi por ambiente (RX_ENV). - 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). ProxyGET /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=1como 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-imagelegado após confirmar que todo.exeem campo é ≥ Direct Upload (1.3.x). Elimina um caminho de upload + base64 pela VPS. - T3.5 (P2) — Throttle/progresso no resync.
trigger-syncreescaneia 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_tokenem 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 envialast_sync, profundidade da fila e últimos erros → página mostra saúde real. - T4.5 (P2) —
lookupPatientInfotolerante a versão do banco do sensor RF. - T4.6 (P3) — Pipeline de auto-update: automatizar envio de
Setup x.y.z.exe+latest.ymlproupdates/do prod ao rebuildar.
5. Segurança / hardening
- T5.1 (P1) —
api_tokenglobal criptografado em repouso (hoje texto puro emsettings.rx_config_global) + rotação + idealmente token de escopo reduzido (não-god). - T5.2 (P1) — Auditar escopo GLOBAL do
tenantGuard— FEITO (dev). 🔴 Achado crítico: a família/api/sync/*(sync GLOBAL legado) usavatenantGuard→ burlável sem clinicaId;DELETE /api/sync/truncate-allfaziaTRUNCATE pacientes,agendamentos,financeiro,leads,guiasde 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-credentialsGET+POST (credenciais OAuth GLOBAIS da plataforma) também eratenantGuard→ qualquer logado sobrescrevia → →superadminGuard(403 p/ não-super; front só chama p/ superadmin). Auditoria completa: todos os demaistenantGuard(clinica-sync, dashboard, agendamentos, avaliacoes, financeiro, guias, leads/:id/converter, DELETE :id, rx/devices) exigemreq.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.txttem oJWT_SECRETREAL (confirmado == o do servidor) commitado → qualquer um com acesso ao repo forja JWT de admin do RX. -INSTRUCOES-SERVIDOR-VPS.txttem oDB_PASSWORD/REDIS_PASSWORDreais 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)..secretsjá 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.jspó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-credentialsdeixavam qualquer logado truncar o banco / trocar OAuth global → agorasuperadminGuard(403 p/ não-super). Mudanças no scoreodonto (dev), não commitadas. - 2026-06-12 — T3.6 auditada:
check-image-existsjá 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.