Skip to main content

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.

Status de implementação

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çaO que é
EnvelopeO contêiner: prazo, provedor, status.
DocumentosOs 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áriosAs pessoas: nome, documento, contato, canal de notificação, ação, método de autenticação e resultado biométrico.
RequisitosO elo entre as duas listas: "o signatário A participa do documento B como avalista" — se já cumpriu, e de onde assinou.
O que é do signatário e o que é do requisito

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
EtapaO que acontece
1. CriaçãoO 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. MontagemEnquanto estiver em draft, tudo pode ser alterado. Fora de draft, qualquer edição devolve 1006025.
3. EnvioValida 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. AcompanhamentoCada 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ãoCom todos os requisitos cumpridos, o envelope vai para completed e os dossiês ficam disponíveis.
Os arquivos do provedor expiram

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[]:

CampoPapel
documents[].featureQual módulo originou aquele documento: loan, authorization_term, billing…
documents[].parentNidO nid do registro daquele módulo.
documents[].typeA natureza jurídica daquele documento: contrato, CCB, aditivo…

É o mesmo par feature + parentNid usado por Charge e Payment.

Por que no documento e não no envelope

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 envelope

Nos 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.

O aceite do termo de autorização também é um 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.

RecursoQI SignClicksignConfiaUnico SignDocuSign
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 assinadoHMAC-SHA1✅✅✅HMAC

Páginas desta seção​

PáginaConteúdo
DocumentosArquivos do envelope, o registro que cada um atesta e o tipo de cada um.
SignatáriosPessoas, ação, autenticação, canais de notificação e biometria.
RequisitosO elo signatário × documento: qualificação, progresso por par e evidência do ato.
EventosTrilha 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​

CampoEntradaTipoPara 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—integerIdentificador numérico interno. É por ele que documentos, signatários e requisitos referenciam o envelope.
code—integerCó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.
titletitlestringTítulo do envelope. Aparece no assunto do e-mail enviado ao signatário.

Provedor​

CampoEntradaTipoPara que serve
providerproviderobject (code/key/name)Plataforma que executa a assinatura. Determina qual implementação o resolver escolhe. Padrão internal. Ver SignatureProvider.
providerAccountproviderAccountstring | nullConta 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 | nullId 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 | nullLink de acompanhamento no provedor.
externalStatusCode—integerCó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 | nullTexto 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​

CampoEntradaTipoPara que serve
flowflowobject (code/key/name)Se os grupos assinam em ordem ou ao mesmo tempo. Padrão parallel. Ver SignatureFlow.
embeddedembeddedbooleanO 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.
autoCloseautoClosebooleanO envelope fecha sozinho assim que a última assinatura chega. Padrão true. Com false, alguém precisa finalizar manualmente.
issuerissuerobjectEmissor 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​

CampoEntradaTipoPara que serve
signerCount—integerTotal de signatários. Calculado. Evita carregar a lista só para mostrar progresso em tela.
signedCount—integerQuantos já assinaram. Calculado.
messagemessagestring | nullMensagem exibida ao signatário no convite.

Webhook​

CampoEntradaTipoPara que serve
callbackUrlcallbackUrlstring | nullEndereço que o provedor chama a cada mudança de estado.
callbackTokencallbackTokenstring | nullSegredo 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.
CampoEntradaTipoPara que serve
signUrl—string | nullLink 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.

O link expira

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​

CampoEntradaTipoPara que serve
sentAt—string (date-time) | nullMomento do envio ao provedor. Até aqui o envelope era rascunho.
deadlinedeadlinestring (date-time) | nullPrazo para assinar. Atingido, o provedor para de aceitar assinaturas. Anterior a sentAt → 1006023.
expiresAtexpiresAtstring (date-time) | nullExpiraçã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) | nullMomento da conclusão.
canceledAt—string (date-time) | nullMomento do cancelamento.

Estado e extensão​

CampoEntradaTipoPara que serve
statusstatusobject (Status)Estado canônico. Nasce draft. Ver SignatureStatus. Inválido → 1006003.
datadataarray 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​

CampoEntradaTipoPara que serve
documentsdocumentsarrayArquivos do envelope. Ver Documentos. Vazio no envio → 1006008.
signerssignersarrayPessoas. Ver Signatários. Vazio no envio → 1006007.
requirementsrequirementsarrayElo 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​

CampoEntradaTipoPara que serve
company, unit, partner, branch, agent, userunitId, partnerId, branchId, agentId, userIdobject (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 requisitoComo referenciar
signerId / documentIdNa criação, com o id informado por você em signers[].id e documents[].id.
signerNid / documentNidEm 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ódigoSignificado
1006001Assinatura não encontrada.
1006002Tipo da Assinatura inválido.
1006003Status da Assinatura inválido.
1006004Provedor de Assinatura inválido.
1006005Fluxo de Assinatura inválido.
1006006Funcionalidade de origem da Assinatura inválida.
1006007Informe ao menos um signatário.
1006008Informe ao menos um documento.
1006009Tipo de documento do signatário inválido.
1006010Documento do signatário é obrigatório.
1006011Informe e-mail ou telefone do signatário.
1006012Ação do signatário inválida.
1006013Canal de envio do signatário inválido.
1006014Papel do documento inválido.
1006015Origem do documento inválida.
1006016Arquivo do documento é obrigatório.
1006017Qualificação do signatário inválida.
1006018Tipo de autenticação inválido.
1006019Tipo de rubrica inválido.
1006021Signatário do requisito não encontrado no envelope.
1006022Documento do requisito não encontrado no envelope.
1006023Prazo inválido: anterior à data de envio.
1006024Expiração inválida: anterior à data de envio.
1006025Assinatura já enviada ao provedor e não pode mais ser editada.
1006026Assinatura já cancelada.
1006027Assinatura já concluída.
1006028Tipo de evento da Assinatura inválido.
1006029Origem do evento da Assinatura inválida.
1006030Tipo de pessoa do signatário inválido.

Formato do envelope de erro: Tratamento de erros.