diff --git a/database-novo/tmp/import-doc-assinatura-eletronica.sql b/database-novo/tmp/import-doc-assinatura-eletronica.sql new file mode 100644 index 0000000..be89201 --- /dev/null +++ b/database-novo/tmp/import-doc-assinatura-eletronica.sql @@ -0,0 +1,166 @@ +-- Importacao da doc Assinatura eletronica de documentos (Fase 3 #7) +-- Gerado a partir de development/saas-docs/05-assinatura-eletronica-melissa.json +BEGIN; + +DO $IMPORT$ +DECLARE + v_doc_id uuid; +BEGIN + INSERT INTO public.saas_docs ( + titulo, conteudo, categoria, exibir_no_faq, tipo_acesso, + pagina_path, ordem, ativo, medias + ) VALUES ( + 'Assinatura eletrônica de documentos', + $HTML$

Assinatura eletrônica de documentos

+ +

O sistema permite enviar documentos clínicos (TCLE, contratos, autorizações, laudos) pro paciente assinar sem que ele precise ter login. O fluxo registra a assinatura com hash do conteúdo, IP, user-agent e timestamp — gerando um audit trail compliance LGPD/CFP.

+ +

1. Visão geral do fluxo

+
    +
  1. Terapeuta abre o documento no prontuário e clica em Assinar
  2. +
  3. Adiciona os signatários (nome + email) e ativa "Gerar link público para assinatura"
  4. +
  5. Sistema cria signature requests + um link público temporário com token
  6. +
  7. Terapeuta copia a URL e envia pro paciente (WhatsApp, email, SMS — manual por enquanto)
  8. +
  9. Paciente abre o link em qualquer navegador, lê o documento, marca o checkbox de aceite LGPD e clica Assinar
  10. +
  11. Sistema computa SHA-256 do PDF baixado, registra assinatura via RPC server-side (IP/UA capturados pelo banco)
  12. +
  13. Terapeuta vê o status atualizado no documento (pendente → assinado)
  14. +
+ +

2. Lado terapeuta — criar solicitação

+

No preview de um documento (na aba Documentos do prontuário), clique no botão Assinar na sidebar de ações. O DocumentSignatureDialog abre com:

+ + +

3. Lado paciente — link público (sem login)

+

Ao abrir o link /shared/document/:token, o paciente vê:

+ + +

Ao clicar Assinar:

+
    +
  1. Sistema baixa o PDF e computa SHA-256 client-side (proof of integrity — se o doc foi alterado depois, hash não bate)
  2. +
  3. Chama a RPC sign_document_by_token passando o hash
  4. +
  5. RPC captura IP via inet_client_addr() e user-agent via current_setting('request.headers') — server-side, à prova de spoof client-side
  6. +
  7. Registra em document_signatures: timestamp, hash, IP, UA, status='assinado'
  8. +
  9. Mostra tela de confirmação "Documento assinado com sucesso"
  10. +
+ +

4. Audit trail registrado

+

Cada assinatura grava:

+ + +
+ 🛡️ Por que server-side? Capturar IP/UA no banco via inet_client_addr() é anti-spoof: o cliente não consegue forjar valores arbitrários. Garante que o audit trail reflete a sessão HTTP real, não um POST manipulado. +
+ +

5. Recusar a assinatura

+

O paciente pode recusar em vez de assinar — útil se ele não concorda com o conteúdo. Click em Recusar abre um confirm; ao confirmar, o sistema registra a recusa (com timestamp + IP/UA da mesma forma) e marca a request como status='recusado'. O terapeuta vê isso na lista de signature requests e pode entrar em contato pra ajustar o documento.

+ +

6. Portal do paciente — lista de pendências

+

Pacientes logados no portal (/portal/documentos) veem uma lista de TODOS os documentos solicitados pra eles, com KPIs no topo:

+ +

Filtro por status (todos / pendentes / assinados) + lista. Click em Assinar agora num item pendente leva pro /shared/document/:token (mesma página pública, mas com auth já garantida via portal).

+ +

7. Expiração e múltiplos usos

+ + +

8. Múltiplos signatários

+

Documentos como termo de autorização de menor podem precisar de 2+ assinaturas (responsável legal + paciente menor, ou os dois pais). O dialog aceita N signatários; cada um recebe sua própria entry em document_signatures. O link público é o mesmo — quando o paciente abre, escolhe qual signatário ele é no select e assina apenas a sua entry.

+ +

9. Validade legal

+

A assinatura eletrônica registrada pelo sistema atende:

+ +

⚠️ Pra documentos que exigem ICP-Brasil (notarial, procuração com poderes especiais), use uma plataforma externa de assinatura qualificada — esse fluxo não substitui.

+ +

⚠️ Notas pro desenvolvedor

+$HTML$, + 'Documentos', + true, + 'usuario', + '/melissa/paciente', + 5, + true, + '[{"tipo": "imagem", "url": ""}]'::jsonb + ) + RETURNING id INTO v_doc_id; + + INSERT INTO public.saas_faq_itens (doc_id, pergunta, resposta, ordem, ativo) VALUES + (v_doc_id, 'Como peço pra um paciente assinar um documento (TCLE, contrato, autorização)?', + $FAQ$Na aba Documentos do prontuário, clique no doc → no preview, clique em Assinar (sidebar de ações). O dialog abre. Adicione o paciente como signatário (nome + email), mantenha "Gerar link público para assinatura" marcado, escolha validade (7 dias é o default) e clique em Solicitar. O sistema cria a request e mostra uma URL pra copiar. Envie pro paciente via WhatsApp, email, SMS — como preferir.$FAQ$, 0, true), + + (v_doc_id, 'Como o paciente assina sem ter login no sistema?', + $FAQ$Ele abre o link público (/shared/document/:token) em qualquer navegador. Vê o PDF inline, lê o aviso LGPD/CFP, marca o checkbox "Li o documento e concordo", e clica Assinar. O sistema computa hash SHA-256 do PDF, chama a RPC server-side que captura IP/User-Agent e registra a assinatura. Nada de cadastro, nada de senha.$FAQ$, 1, true), + + (v_doc_id, 'Que informação fica registrada quando ele assina?', + $FAQ$Tudo que precisa pra audit compliance: nome e email do signatário (do cadastro), timestamp server-side (não do relógio do cliente), hash SHA-256 do PDF no momento da assinatura (qualquer alteração posterior invalida a integridade), IP e User-Agent capturados pelo banco via inet_client_addr() e current_setting('request.headers') — anti-spoof. Tudo fica em public.document_signatures.$FAQ$, 2, true), + + (v_doc_id, 'O terapeuta também precisa assinar o documento?', + $FAQ$Depende do tipo. Pra atestados, laudos e declarações, geralmente sim — você gera o PDF a partir do template (que já contém seu nome + registro profissional + assinatura digitalizada se você incluiu no rodapé). Pra contratos e termos com paciente como contraparte, você adiciona você mesmo como segundo signatário no dialog antes de enviar. Cada um abre o link e assina sua entry separadamente.$FAQ$, 3, true), + + (v_doc_id, 'O link tem validade? E se expirar?', + $FAQ$Tem. Você escolhe 24h, 3 dias, 7 dias ou 30 dias na hora de criar (default 7d). Depois disso o link retorna erro 410 Gone. Se o paciente não assinou a tempo, gere um novo link: no preview do doc, clique em Compartilhar ou abra o dialog de assinatura novamente — vai criar outro token. Limite de usos do link: ~5 (margem pra reload/multi-device), depois também expira.$FAQ$, 4, true), + + (v_doc_id, 'E se o paciente recusar a assinatura?', + $FAQ$Tem botão Recusar ao lado do Assinar. Clique pede confirmação; ao confirmar, a request fica com status='recusado' com timestamp e IP/UA registrados igual à assinatura. Você vê o status na lista de pendências do doc e na aba do prontuário. Geralmente: ajuste o conteúdo do documento e envie nova solicitação.$FAQ$, 5, true), + + (v_doc_id, 'O paciente pode assinar depois pelo Portal sem precisar do link?', + $FAQ$Sim, se ele tem conta de portal. Em /portal/documentos aparece a lista de tudo que está pendente pra ele assinar, com KPIs (total, pendentes, assinados, recusados) e botão Assinar agora que leva pra mesma página de assinatura. Útil pra pacientes que perderam o link no WhatsApp — eles loga e acha tudo num lugar só.$FAQ$, 6, true), + + (v_doc_id, 'Como compartilho o link com o paciente — tem envio automático?', + $FAQ$Hoje o envio é manual: o dialog gera a URL, você copia e cola onde quiser (WhatsApp, email, SMS, AirDrop, QR code, link em conversa direta). Envio automático (notificação por WA/email quando signature é criada) está no roadmap, depende do Módulo 6 (notifications factory channel) que ainda não foi implementado.$FAQ$, 7, true), + + (v_doc_id, 'A assinatura tem validade legal mesmo sem certificado ICP-Brasil?', + $FAQ$Pra documentos clínicos comuns (TCLE, contrato de prestação, autorizações, declarações entre terapeuta-paciente), sim. A assinatura simples com timestamp + hash + IP + UA atende LGPD (Art. 7º I — consentimento explícito) e o Código de Ética do CFP. Pra documentos que exigem certificado ICP-Brasil (notarial, procuração com poderes especiais), use uma plataforma externa de assinatura qualificada — esse fluxo não substitui.$FAQ$, 8, true), + + (v_doc_id, 'O paciente consegue editar o documento antes de assinar?', + $FAQ$Não. O paciente só visualiza — o PDF é renderizado em iframe e a integridade é garantida pelo hash SHA-256 computado no momento da assinatura. Se o conteúdo precisar mudar, é você que ajusta o documento (editar via template ou regenerar) e envia nova solicitação. A assinatura antiga (se houve) fica registrada com o hash do conteúdo antigo — o doc atual tem hash diferente, mostrando que mudou.$FAQ$, 9, true), + + (v_doc_id, 'Como cancelo uma solicitação de assinatura?', + $FAQ$Hoje não há um botão "cancelar" direto na UI. O caminho é: ignore (deixa expirar pelo prazo do link) ou peça pro admin marcar como status='expirado' no banco. Em versões futuras teremos botão de cancelar na lista de pendências do doc.$FAQ$, 10, true), + + (v_doc_id, 'Posso pedir mais de uma pessoa pra assinar o mesmo documento?', + $FAQ$Sim. Pra termos com múltiplos signatários (autorização de atendimento de menor com 2 pais, contrato com responsável legal + paciente), adicione cada um como signatário separado no dialog. Cada um vira uma entry em document_signatures. O link público é o mesmo — quando o signatário abre, escolhe quem ele é no select acima dos botões e assina apenas a entry dele. Útil também pra você incluir si mesmo (terapeuta) + paciente num contrato bilateral.$FAQ$, 11, true); + + RAISE NOTICE 'Doc criada: id=%, faq_itens=12', v_doc_id; +END; +$IMPORT$; + +COMMIT; diff --git a/development/saas-docs/05-assinatura-eletronica-melissa.json b/development/saas-docs/05-assinatura-eletronica-melissa.json new file mode 100644 index 0000000..920e51e --- /dev/null +++ b/development/saas-docs/05-assinatura-eletronica-melissa.json @@ -0,0 +1,87 @@ +{ + "titulo": "Assinatura eletrônica de documentos", + "conteudo": "

Assinatura eletrônica de documentos

\n\n

O sistema permite enviar documentos clínicos (TCLE, contratos, autorizações, laudos) pro paciente assinar sem que ele precise ter login. O fluxo registra a assinatura com hash do conteúdo, IP, user-agent e timestamp — gerando um audit trail compliance LGPD/CFP.

\n\n

1. Visão geral do fluxo

\n
    \n
  1. Terapeuta abre o documento no prontuário e clica em Assinar
  2. \n
  3. Adiciona os signatários (nome + email) e ativa \"Gerar link público para assinatura\"
  4. \n
  5. Sistema cria signature requests + um link público temporário com token
  6. \n
  7. Terapeuta copia a URL e envia pro paciente (WhatsApp, email, SMS — manual por enquanto)
  8. \n
  9. Paciente abre o link em qualquer navegador, lê o documento, marca o checkbox de aceite LGPD e clica Assinar
  10. \n
  11. Sistema computa SHA-256 do PDF baixado, registra assinatura via RPC server-side (IP/UA capturados pelo banco)
  12. \n
  13. Terapeuta vê o status atualizado no documento (pendente → assinado)
  14. \n
\n\n

2. Lado terapeuta — criar solicitação

\n

No preview de um documento (na aba Documentos do prontuário), clique no botão Assinar na sidebar de ações. O DocumentSignatureDialog abre com:

\n\n\n

3. Lado paciente — link público (sem login)

\n

Ao abrir o link /shared/document/:token, o paciente vê:

\n\n\n

Ao clicar Assinar:

\n
    \n
  1. Sistema baixa o PDF e computa SHA-256 client-side (proof of integrity — se o doc foi alterado depois, hash não bate)
  2. \n
  3. Chama a RPC sign_document_by_token passando o hash
  4. \n
  5. RPC captura IP via inet_client_addr() e user-agent via current_setting('request.headers') — server-side, à prova de spoof client-side
  6. \n
  7. Registra em document_signatures: timestamp, hash, IP, UA, status='assinado'
  8. \n
  9. Mostra tela de confirmação \"Documento assinado com sucesso\"
  10. \n
\n\n

4. Audit trail registrado

\n

Cada assinatura grava:

\n\n\n
\n 🛡️ Por que server-side? Capturar IP/UA no banco via inet_client_addr() é anti-spoof: o cliente não consegue forjar valores arbitrários. Garante que o audit trail reflete a sessão HTTP real, não um POST manipulado.\n
\n\n

5. Recusar a assinatura

\n

O paciente pode recusar em vez de assinar — útil se ele não concorda com o conteúdo. Click em Recusar abre um confirm; ao confirmar, o sistema registra a recusa (com timestamp + IP/UA da mesma forma) e marca a request como status='recusado'. O terapeuta vê isso na lista de signature requests e pode entrar em contato pra ajustar o documento.

\n\n

6. Portal do paciente — lista de pendências

\n

Pacientes logados no portal (/portal/documentos) veem uma lista de TODOS os documentos solicitados pra eles, com KPIs no topo:

\n\n

Filtro por status (todos / pendentes / assinados) + lista. Click em Assinar agora num item pendente leva pro /shared/document/:token (mesma página pública, mas com auth já garantida via portal).

\n\n

7. Expiração e múltiplos usos

\n\n\n

8. Múltiplos signatários

\n

Documentos como termo de autorização de menor podem precisar de 2+ assinaturas (responsável legal + paciente menor, ou os dois pais). O dialog aceita N signatários; cada um recebe sua própria entry em document_signatures. O link público é o mesmo — quando o paciente abre, escolhe qual signatário ele é no select e assina apenas a sua entry.

\n\n

9. Validade legal

\n

A assinatura eletrônica registrada pelo sistema atende:

\n\n

⚠️ Pra documentos que exigem ICP-Brasil (notarial, procuração com poderes especiais), use uma plataforma externa de assinatura qualificada — esse fluxo não substitui.

\n\n

⚠️ Notas pro desenvolvedor

\n", + "categoria": "Documentos", + "exibir_no_faq": true, + "tipo_acesso": "usuario", + "pagina_path": "/melissa/paciente", + "ordem": 5, + "ativo": true, + "medias": [ + { "tipo": "imagem", "url": "" } + ], + "_faq_itens": [ + { + "pergunta": "Como peço pra um paciente assinar um documento (TCLE, contrato, autorização)?", + "resposta": "Na aba Documentos do prontuário, clique no doc → no preview, clique em Assinar (sidebar de ações). O dialog abre. Adicione o paciente como signatário (nome + email), mantenha \"Gerar link público para assinatura\" marcado, escolha validade (7 dias é o default) e clique em Solicitar. O sistema cria a request e mostra uma URL pra copiar. Envie pro paciente via WhatsApp, email, SMS — como preferir.", + "ordem": 0, + "ativo": true + }, + { + "pergunta": "Como o paciente assina sem ter login no sistema?", + "resposta": "Ele abre o link público (/shared/document/:token) em qualquer navegador. Vê o PDF inline, lê o aviso LGPD/CFP, marca o checkbox \"Li o documento e concordo\", e clica Assinar. O sistema computa hash SHA-256 do PDF, chama a RPC server-side que captura IP/User-Agent e registra a assinatura. Nada de cadastro, nada de senha.", + "ordem": 1, + "ativo": true + }, + { + "pergunta": "Que informação fica registrada quando ele assina?", + "resposta": "Tudo que precisa pra audit compliance: nome e email do signatário (do cadastro), timestamp server-side (não do relógio do cliente), hash SHA-256 do PDF no momento da assinatura (qualquer alteração posterior invalida a integridade), IP e User-Agent capturados pelo banco via inet_client_addr() e current_setting('request.headers') — anti-spoof. Tudo fica em public.document_signatures.", + "ordem": 2, + "ativo": true + }, + { + "pergunta": "O terapeuta também precisa assinar o documento?", + "resposta": "Depende do tipo. Pra atestados, laudos e declarações, geralmente sim — você gera o PDF a partir do template (que já contém seu nome + registro profissional + assinatura digitalizada se você incluiu no rodapé). Pra contratos e termos com paciente como contraparte, você adiciona você mesmo como segundo signatário no dialog antes de enviar. Cada um abre o link e assina sua entry separadamente.", + "ordem": 3, + "ativo": true + }, + { + "pergunta": "O link tem validade? E se expirar?", + "resposta": "Tem. Você escolhe 24h, 3 dias, 7 dias ou 30 dias na hora de criar (default 7d). Depois disso o link retorna erro 410 Gone. Se o paciente não assinou a tempo, gere um novo link: no preview do doc, clique em Compartilhar ou abra o dialog de assinatura novamente — vai criar outro token. Limite de usos do link: ~5 (margem pra reload/multi-device), depois também expira.", + "ordem": 4, + "ativo": true + }, + { + "pergunta": "E se o paciente recusar a assinatura?", + "resposta": "Tem botão Recusar ao lado do Assinar. Clique pede confirmação; ao confirmar, a request fica com status='recusado' com timestamp e IP/UA registrados igual à assinatura. Você vê o status na lista de pendências do doc e na aba do prontuário. Geralmente: ajuste o conteúdo do documento e envie nova solicitação.", + "ordem": 5, + "ativo": true + }, + { + "pergunta": "O paciente pode assinar depois pelo Portal sem precisar do link?", + "resposta": "Sim, se ele tem conta de portal. Em /portal/documentos aparece a lista de tudo que está pendente pra ele assinar, com KPIs (total, pendentes, assinados, recusados) e botão Assinar agora que leva pra mesma página de assinatura. Útil pra pacientes que perderam o link no WhatsApp — eles loga e acha tudo num lugar só.", + "ordem": 6, + "ativo": true + }, + { + "pergunta": "Como compartilho o link com o paciente — tem envio automático?", + "resposta": "Hoje o envio é manual: o dialog gera a URL, você copia e cola onde quiser (WhatsApp, email, SMS, AirDrop, QR code, link em conversa direta). Envio automático (notificação por WA/email quando signature é criada) está no roadmap, depende do Módulo 6 (notifications factory channel) que ainda não foi implementado.", + "ordem": 7, + "ativo": true + }, + { + "pergunta": "A assinatura tem validade legal mesmo sem certificado ICP-Brasil?", + "resposta": "Pra documentos clínicos comuns (TCLE, contrato de prestação, autorizações, declarações entre terapeuta-paciente), sim. A assinatura simples com timestamp + hash + IP + UA atende LGPD (Art. 7º I — consentimento explícito) e o Código de Ética do CFP. Pra documentos que exigem certificado ICP-Brasil (notarial, procuração com poderes especiais), use uma plataforma externa de assinatura qualificada — esse fluxo não substitui.", + "ordem": 8, + "ativo": true + }, + { + "pergunta": "O paciente consegue editar o documento antes de assinar?", + "resposta": "Não. O paciente só visualiza — o PDF é renderizado em iframe e a integridade é garantida pelo hash SHA-256 computado no momento da assinatura. Se o conteúdo precisar mudar, é você que ajusta o documento (editar via template ou regenerar) e envia nova solicitação. A assinatura antiga (se houve) fica registrada com o hash do conteúdo antigo — o doc atual tem hash diferente, mostrando que mudou.", + "ordem": 9, + "ativo": true + }, + { + "pergunta": "Como cancelo uma solicitação de assinatura?", + "resposta": "Hoje não há um botão \"cancelar\" direto na UI. O caminho é: ignore (deixa expirar pelo prazo do link) ou peça pro admin marcar como status='expirado' no banco. Em versões futuras teremos botão de cancelar na lista de pendências do doc.", + "ordem": 10, + "ativo": true + }, + { + "pergunta": "Posso pedir mais de uma pessoa pra assinar o mesmo documento?", + "resposta": "Sim. Pra termos com múltiplos signatários (autorização de atendimento de menor com 2 pais, contrato com responsável legal + paciente), adicione cada um como signatário separado no dialog. Cada um vira uma entry em document_signatures. O link público é o mesmo — quando o signatário abre, escolhe quem ele é no select acima dos botões e assina apenas a entry dele. Útil também pra você incluir si mesmo (terapeuta) + paciente num contrato bilateral.", + "ordem": 11, + "ativo": true + } + ] +}