Assinatura Eletrônica
Módulo de assinatura eletrônica: o registro de um pacote de documentos enviado a uma plataforma de assinatura para ser assinado por um conjunto de pessoas, com as regras que dizem quem assina o quê e como comprova a identidade.
O módulo é agnóstico de provedor. O mesmo modelo atende QI Sign, Clicksign, Confia, Unico Sign e DocuSign: o formato de cada plataforma é traduzido na entrada e na saída, e nunca aparece na entidade.
O módulo está implementado no domínio (entidades, regras, persistência, serviços) e o contrato de provedor (ISignatureProvider) está definido, mas os endpoints REST e as implementações concretas de cada provedor ainda não foram escritos. Esta página documenta o modelo de dados — os campos que a entidade tem e para que cada um serve. Quando as rotas forem expostas, esta seção passa a incluí-las.
O que é um envelope
O envelope (Signature) é a unidade do módulo. Ele agrupa quatro coisas:
| Peça | O que é |
|---|---|
| Envelope | O contêiner: prazo, provedor, status. |
| Documentos | Os arquivos, cada um apontando para o registro que ele atesta. Os que serão assinados, os assinados, os dossiês de evidência e as imagens de identificação capturadas. |
| Signatários | As pessoas: nome, documento, contato, canal de notificação, ação, método de autenticação e resultado biométrico. |
| Requisitos | O elo entre as duas listas: "o signatário A participa do documento B como avalista" — se já cumpriu, e de onde assinou. |
O método de autenticação e a ação são do signatário e valem para o envelope inteiro. Uma pessoa se identifica de um jeito só: quem assina com biometria facial assina todos os documentos daquele envelope com biometria facial. Isso é regra do modelo, não limitação de provedor.
O que varia por documento é a qualificação (com que título a pessoa assina). Num envelope com contrato e termo de garantia, a mesma pessoa pode ser devedora em um e caucionante no outro. É isso que o requisito expressa — junto com o progresso por par, que diz qual documento cada pessoa já cumpriu, e a evidência técnica de cada ato.
É como Clicksign ("Requisitos") e DocuSign (tabs por recipient e documento) organizam o fluxo. QI Sign, Confia e Unico Sign aceitam apenas uma regra por signatário — para eles, o mapper acha o conjunto na hora do envio.
Ciclo de vida
O envelope existe na plataforma antes de existir no provedor:
draft ──► running ──► partially_signed ──► completed
│ │
│ ├──► refused / expired / failed
└──────────┴──► canceled
| Etapa | O que acontece |
|---|---|
| 1. Criação | O envelope nasce em draft com um key público e um code sequencial. Documentos, signatários e requisitos são montados e recebem nid. Nada foi enviado ao provedor ainda. |
| 2. Montagem | Enquanto estiver em draft, tudo pode ser alterado. Fora de draft, qualquer edição devolve 1006025. |
| 3. Envio | Valida que há ao menos um documento assinável e um signatário com contato, marca sentAt, passa o envelope para running, os signatários para sent e os documentos para running. |
| 4. Acompanhamento | Cada mudança chega por webhook (ou consulta) e vira um evento na trilha, atualizando o status do envelope, do signatário e do requisito. |
| 5. Conclusão | Com todos os requisitos cumpridos, o envelope vai para completed e os dossiês ficam disponíveis. |
As URLs devolvidas pelos provedores — dossiê, imagem facial, foto do documento — têm validade curta (24 horas na QI Sign). O campo externalUrl é referência, não guarda: o binário precisa ser baixado e persistido no módulo de armazenamento assim que o envelope conclui. Depois disso, o arquivo armazenado é a fonte da evidência.
Ligação com o resto da plataforma
Quem aponta para o registro de origem é cada documento, não o envelope. Os campos ficam em documents[]:
| Campo | Papel |
|---|---|
documents[].feature | Qual módulo originou aquele documento: loan, authorization_term, billing… |
documents[].parentNid | O nid do registro daquele módulo. |
documents[].type | A natureza jurídica daquele documento: contrato, CCB, aditivo… |
É o mesmo par feature + parentNid usado por Charge e Payment.
Porque o envelope é só o pacote. Um mesmo envelope pode levar contratos de operações diferentes — três CCBs de três empréstimos distintos numa assinatura só, para o cliente assinar tudo de uma vez.
Se feature + parentNid estivessem no envelope, esse caso obrigaria a criar três envelopes e mandar três convites para a mesma pessoa.
Pelo mesmo motivo o type desceu junto: os documentos de um envelope não precisam ser todos do mesmo tipo. Um envelope pode levar a CCB e o termo de garantia dela.
parentNid no documento é o registro de origem, não o envelopeNos requisitos, nas autenticações do signatário e nos eventos, parentNid é o nid do envelope, na convenção usual de tabela filha. O signatário, como o documento, usa signatureNid.
No documento é diferente: parentNid é o registro de origem (o Loan), seguindo o idioma feature + parentNid de Charge e Payment, e o envelope fica em signatureNid.
A busca por (feature, parentNid) responde "quais envelopes contêm documentos deste empréstimo?" e é a porta de entrada dos webhooks de esteira de crédito, que identificam a operação e não o envelope.
Termos de Autorização registram cada aceite como um envelope deste módulo, com provedor internal, já concluído (completed), com um documento type = term / feature = authorization_term e o aceite do signatário como requisito cumprido. O campo signatures[] do termo devolve esses envelopes.
O que cada provedor suporta
Coluna vazia não é problema: o provedor simplesmente não gera aquelas linhas. O modelo acompanha o provedor mais rico porque degradar é trivial — o contrário exigiria refazer o schema com contrato assinado em produção.
| Recurso | QI Sign | Clicksign | Confia | Unico Sign | DocuSign |
|---|---|---|---|---|---|
| Envelope montado em etapas | ✅ | ✅ | ❌ | ❌ | ✅ |
| Qualificação por documento | ❌ | ✅ | ❌ | ❌ | ✅ |
| Grupos de assinatura | ❌ | ✅ | ❌ | ✅ | ✅ |
| Observador | ❌ | ✅ | ❌ | ❌ | ✅ |
| Dossiê de evidências | ✅ | ✅ | ✅ | ✅ | ✅ |
| Biometria / prova de vida | ✅ | ✅ | ❌ | ✅ | ✅ |
| Modelos de documento | ❌ | ✅ | ❌ | ✅ | ✅ |
| Assinatura embarcada | ❌ | ✅ | ❌ | ✅ | ✅ |
| Webhook assinado | HMAC-SHA1 | ✅ | ✅ | ✅ | HMAC |
Páginas desta seção
| Página | Conteúdo |
|---|---|
| Documentos | Arquivos do envelope, o registro que cada um atesta e o tipo de cada um. |
| Signatários | Pessoas, ação, autenticação, canais de notificação e biometria. |
| Requisitos | O elo signatário × documento: qualificação, progresso por par e evidência do ato. |
| Eventos | Trilha de auditoria imutável e recebimento de webhooks. |
Valores de domínio: Assinatura Eletrônica.
Campos do envelope
Convenções reutilizadas: Objeto de domínio, Campo de status, Referências organizacionais, Log de auditoria.
Identificação
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
id | — | string (uuid) | Identificador do envelope. Quando o provedor aceita id externo (QI Sign), é este valor que enviamos como id do envelope lá — o que também garante idempotência: reenviar o mesmo id devolve conflito em vez de criar duplicata. |
nid | — | integer | Identificador numérico interno. É por ele que documentos, signatários e requisitos referenciam o envelope. |
code | — | integer | Código sequencial por empresa. É o número que o operador vê. |
key | — | string (uuid) | Chave pública, gerada na criação. Permite buscar o envelope sem expor o id interno. |
title | title | string | Título do envelope. Aparece no assunto do e-mail enviado ao signatário. |
Provedor
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
provider | provider | object (code/key/name) | Plataforma que executa a assinatura. Determina qual implementação o resolver escolhe. Padrão internal. Ver SignatureProvider. |
providerAccount | providerAccount | string | null | Conta ou workspace dentro do provedor. Uma mesma empresa pode ter mais de uma; é este valor que resolve qual credencial (URL base, chave de API, chave de assinatura do webhook) usar. |
externalId | — | string | null | Id do envelope no provedor. Preenchido pela plataforma: é o nosso id quando o provedor aceita id externo, ou o UUID dele quando não aceita. |
externalUrl | — | string | null | Link de acompanhamento no provedor. |
externalStatusCode | — | integer | Código de status cru do provedor (ex.: 1 da Unico Sign). Guardado junto com o canônico porque os provedores não compartilham vocabulário. |
externalStatus | — | string | null | Texto do status cru ("signed", "Pendente", "Não Assinado"). Serve para diagnóstico quando o mapeamento canônico não cobre um caso novo. |
Fluxo e formato
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
flow | flow | object (code/key/name) | Se os grupos assinam em ordem ou ao mesmo tempo. Padrão parallel. Ver SignatureFlow. |
embedded | embedded | boolean | O envelope inteiro é assinado dentro da nossa aplicação, em widget embarcado, em vez de por link externo. Há também o controle por signatário. |
autoClose | autoClose | boolean | O envelope fecha sozinho assim que a última assinatura chega. Padrão true. Com false, alguém precisa finalizar manualmente. |
issuer | issuer | object | Emissor do envelope na conta do provedor: externalId (id do usuário emissor lá) e name. Quando não informado, o name recebe a razão social da empresa. |
Contadores e texto
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
signerCount | — | integer | Total de signatários. Calculado. Evita carregar a lista só para mostrar progresso em tela. |
signedCount | — | integer | Quantos já assinaram. Calculado. |
message | message | string | null | Mensagem exibida ao signatário no convite. |
Webhook
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
callbackUrl | callbackUrl | string | null | Endereço que o provedor chama a cada mudança de estado. |
callbackToken | callbackToken | string | null | Segredo usado para validar a assinatura HMAC do webhook. Gravado cifrado e nunca devolvido em leitura. Sem ele, um evento recebido é registrado mas não altera o estado do envelope. |
Link de assinatura
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
signUrl | — | string | null | Link de assinatura do envelope, devolvido pelo provedor no envio. Só é preenchido depois do submit. |
Não confundir com signers[].signUrl, que é o link individual de cada pessoa.
O do envelope existe nos provedores que expõem uma página única — útil em fluxo presencial, quando todo mundo assina no mesmo dispositivo. Quem trabalha só com link por signatário deixa este campo nulo.
Como o externalUrl, este endereço tem validade curta do lado do provedor. Ele serve para redirecionar alguém agora, não para ser arquivado como evidência — a evidência é o arquivo baixado e o requisito cumprido.
Datas
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
sentAt | — | string (date-time) | null | Momento do envio ao provedor. Até aqui o envelope era rascunho. |
deadline | deadline | string (date-time) | null | Prazo para assinar. Atingido, o provedor para de aceitar assinaturas. Anterior a sentAt → 1006023. |
expiresAt | expiresAt | string (date-time) | null | Expiração do envelope e dos links. Distinta do prazo: o prazo encerra a coleta, a expiração invalida o acesso. Anterior a sentAt → 1006024. |
completedAt | — | string (date-time) | null | Momento da conclusão. |
canceledAt | — | string (date-time) | null | Momento do cancelamento. |
Estado e extensão
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
status | status | object (Status) | Estado canônico. Nasce draft. Ver SignatureStatus. Inválido → 1006003. |
data | data | array de { key, label, value } | Campos específicos do provedor que não têm lugar no modelo canônico. É o que absorve um campo novo sem exigir mudança de schema. label é o rótulo de exibição. |
Listas filhas
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
documents | documents | array | Arquivos do envelope. Ver Documentos. Vazio no envio → 1006008. |
signers | signers | array | Pessoas. Ver Signatários. Vazio no envio → 1006007. |
requirements | requirements | array | Elo entre as duas listas. Ver Requisitos. Vazio gera o padrão: todos os signatários por todos os documentos assináveis, com role = party. |
Organização e auditoria
| Campo | Entrada | Tipo | Para que serve |
|---|---|---|---|
company, unit, partner, branch, agent, user | unitId, partnerId, branchId, agentId, userId | object (Referência) | Hierarquia organizacional. Define a quem o envelope pertence e alimenta o nível de acesso. Ver Referências organizacionais. |
log | — | object (Log de auditoria) | Criação, alteração, exclusão e versão do registro. Ver Log de auditoria. |
Referência de requisitos entre entidades
Os requisitos apontam para signatários e documentos por nid, que só existe depois da geração. No cadastro, informe o id que você atribuiu ao signatário e ao documento no mesmo payload — a plataforma resolve os nid correspondentes.
| Campo do requisito | Como referenciar |
|---|---|
signerId / documentId | Na criação, com o id informado por você em signers[].id e documents[].id. |
signerNid / documentNid | Em alterações de um envelope já gravado, com o nid devolvido na leitura. |
Requisito apontando para signatário inexistente → 1006021. Para documento inexistente → 1006022.
Erros do módulo
| Código | Significado |
|---|---|
1006001 | Assinatura não encontrada. |
1006002 | Tipo da Assinatura inválido. |
1006003 | Status da Assinatura inválido. |
1006004 | Provedor de Assinatura inválido. |
1006005 | Fluxo de Assinatura inválido. |
1006006 | Funcionalidade de origem da Assinatura inválida. |
1006007 | Informe ao menos um signatário. |
1006008 | Informe ao menos um documento. |
1006009 | Tipo de documento do signatário inválido. |
1006010 | Documento do signatário é obrigatório. |
1006011 | Informe e-mail ou telefone do signatário. |
1006012 | Ação do signatário inválida. |
1006013 | Canal de envio do signatário inválido. |
1006014 | Papel do documento inválido. |
1006015 | Origem do documento inválida. |
1006016 | Arquivo do documento é obrigatório. |
1006017 | Qualificação do signatário inválida. |
1006018 | Tipo de autenticação inválido. |
1006019 | Tipo de rubrica inválido. |
1006021 | Signatário do requisito não encontrado no envelope. |
1006022 | Documento do requisito não encontrado no envelope. |
1006023 | Prazo inválido: anterior à data de envio. |
1006024 | Expiração inválida: anterior à data de envio. |
1006025 | Assinatura já enviada ao provedor e não pode mais ser editada. |
1006026 | Assinatura já cancelada. |
1006027 | Assinatura já concluída. |
1006028 | Tipo de evento da Assinatura inválido. |
1006029 | Origem do evento da Assinatura inválida. |
1006030 | Tipo de pessoa do signatário inválido. |
Formato do envelope de erro: Tratamento de erros.