feat(cadastro): card "Protético" na vitrine de onboarding + desenho do Modo 1
- OnboardingChat: adiciona o card de atalho "Protéticos" (perfil profissional → protetico), ao lado de Dentistas/Biomédicos. O cadastro de protético já funcionava via "Sou profissional", faltava o atalho na vitrine. - doc/MODO1-LINK-SEGURO-PROTESE: desenho do "Provedor sem conta" — link seguro /p/TOKEN (token por OS, revogável; rotas públicas com a mesma blindagem soLab; página pública read+ação; CTA de conversão com herança de histórico). Evolução futura, sem refatoração. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
# Modo 1 — Provedor de Prótese SEM conta (link seguro `/p/TOKEN`)
|
||||
|
||||
> Desenho (24/jun/2026). Evolução registrada como "fora de escopo" em `PROVEDOR-PROTESE-DECISAO.md`.
|
||||
> Princípio (decisão arquitetural): **a clínica opera 100% da OS; o protético não precisa ter conta.**
|
||||
> O link é a porta de entrada do ecossistema — acompanha hoje, vira conta amanhã.
|
||||
|
||||
## Objetivo
|
||||
A clínica cria/gere a OS normalmente. O protético recebe um **link seguro** (WhatsApp/e-mail) e,
|
||||
**sem login**, acompanha e atua na OS dele. Com CTA para criar conta grátis (conversão).
|
||||
|
||||
```
|
||||
Clínica cria OS ──► gera link /p/TOKEN ──► WhatsApp/e-mail ──► Protético abre (sem conta)
|
||||
├─ vê a OS (sem CPF/valores do paciente)
|
||||
├─ confirma recebimento/devolução
|
||||
├─ avança etapa / anexa foto
|
||||
└─ responde ocorrência
|
||||
"Crie sua conta grátis" ──► cadastro (card Protético)
|
||||
```
|
||||
|
||||
## 1. Escopo do token: **por OS** (não por protético)
|
||||
Escopo mínimo = menor superfície de risco. Um token dá acesso a **uma OS**. Vantagens: revogável
|
||||
individualmente, expira por trabalho, não expõe a carteira inteira do protético. (Evolução: um token
|
||||
"carteira" por protético-na-clínica que lista várias OS — fica para depois.)
|
||||
|
||||
## 2. Modelo de dados (revogável e auditável)
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS protese_os_link (
|
||||
token TEXT PRIMARY KEY, -- aleatório longo (≥ 32 bytes base62), NÃO sequencial
|
||||
os_id TEXT NOT NULL,
|
||||
protetico_id TEXT, -- a quem se destina (rastreio)
|
||||
created_by TEXT, -- quem na clínica gerou
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
expires_at TIMESTAMPTZ, -- opcional (ex.: +30 dias); null = sem expirar
|
||||
revoked_at TIMESTAMPTZ, -- revogação manual
|
||||
last_access_at TIMESTAMPTZ,
|
||||
acessos INTEGER DEFAULT 0
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_protese_os_link_os ON protese_os_link (os_id);
|
||||
```
|
||||
> Preferir tabela a JWT puro: permite **revogar** e **auditar acessos**. O token nunca contém dados.
|
||||
|
||||
## 3. Rotas públicas (sem `authGuard`; o token é a credencial)
|
||||
Todas resolvem `os_id` pelo token (valida não-revogado, não-expirado) e aplicam a **mesma blindagem
|
||||
do provedor**: sem `paciente_id`/CPF, sem valores do paciente (reusa a lógica `soLab`).
|
||||
|
||||
| Rota | Ação |
|
||||
|---|---|
|
||||
| `GET /api/p/:token` | OS: nº, clínica, dentista, paciente (nome, conforme permissão), prazo, status, observações, fotos, componentes, ocorrências, custódia. **Sem CPF/valores do paciente.** |
|
||||
| `POST /api/p/:token/custodia` | confirmar recebimento / devolução (clínica↔lab) |
|
||||
| `POST /api/p/:token/status` | avançar a produção (recebido→…→finalizado) |
|
||||
| `POST /api/p/:token/foto` | anexar foto do trabalho (+ ocorrência) |
|
||||
| `POST /api/p/:token/ocorrencias/:id/resposta` | responder ocorrência (contraditório) |
|
||||
|
||||
Cada ação registra no histórico da OS um **actor "Protético (link)"** com o `protetico_id` do token —
|
||||
mantendo a auditoria. Mesmas validações de status/foto já existentes.
|
||||
|
||||
## 4. Geração e envio (lado clínica)
|
||||
Na OS (modal, aba Etapas ou Monitoramento): botão **"Enviar ao protético"** →
|
||||
`POST /api/protese/os/:id/link` gera/recupera o token e devolve a URL
|
||||
`https://scoreodonto.com/p/TOKEN`. Atalhos: **WhatsApp** (`https://wa.me/?text=…`) e **e-mail**
|
||||
(`mailto:`). Botão **"Revogar link"** para invalidar.
|
||||
|
||||
## 5. Frontend público `/p/:token`
|
||||
Rota **fora do app autenticado** (sem Sidebar/login). Página enxuta que reusa as seções do
|
||||
`OSDetailModal` em modo "público/lab" (etapas, fotos, componentes, custódia, ocorrências — sem
|
||||
financeiro/clientes). Topo com a marca + rodapé fixo:
|
||||
|
||||
> *"Gostou de acompanhar por aqui? Crie sua conta grátis e gerencie todos os seus laboratórios."*
|
||||
> → leva ao cadastro **já com o card Protético** (adicionado) e e-mail pré-preenchido.
|
||||
|
||||
## 6. Segurança (checklist)
|
||||
- Token aleatório ≥ 32 bytes, base62, **não sequencial**; comparação em tempo constante.
|
||||
- Escopo de **1 OS**; expiração opcional; **revogável**; rate-limit por token/IP.
|
||||
- **Sem CPF e sem valores do paciente** (mesma blindagem `soLab` da Fase 1).
|
||||
- Ações registram actor no histórico (auditoria); `last_access_at`/`acessos` para detectar abuso.
|
||||
- OS `entregue`/`cancelado` → link vira **somente leitura**.
|
||||
|
||||
## 7. Conversão (o "porquê de negócio")
|
||||
O link é aquisição: o protético experimenta o produto sem fricção e, ao criar conta, **herda o
|
||||
histórico** (as OS daquela clínica já estão ligadas ao `protetico_id` dele). Liga direto ao
|
||||
marketplace/score (Fase 5) — quanto mais clínicas o usam, mais OS e melhor o score do protético.
|
||||
|
||||
## 8. Faseamento sugerido
|
||||
- **1a (núcleo):** tabela + `GET /api/p/:token` (leitura) + página pública read-only + botão "enviar".
|
||||
- **1b (ação):** custódia + status + foto pelo link (escrita), com auditoria.
|
||||
- **1c (conversão):** CTA de cadastro com herança de histórico + revogação/expiração na UI.
|
||||
|
||||
> Nenhuma refatoração: reusa OS/eventos/custódia/ocorrências/blindagem já existentes. Só adiciona a
|
||||
> camada de token público.
|
||||
Reference in New Issue
Block a user