Audit trail
The audit trail is the record of everything that happens to an envelope, from the moment it is created until completion. It is the main evidence of an advanced electronic signature: it shows who did what, when, from where and with which identity confirmation.
What is recorded#
| Event | When it happens |
|---|---|
envelope_criado |
The envelope was created (panel, API or ChatISP) |
envelope_enviado |
The envelope was sent for signature |
notificacao_enviada |
An invitation was delivered to a signer |
link_aberto |
The signer opened the personal link |
documento_visualizado |
The signer opened the document |
otp_enviado |
A confirmation code was generated and sent |
otp_validado |
The signer entered the correct code |
otp_falhou |
The signer entered a wrong code |
assinado |
The signer signed |
recusado |
The signer declined, with the reason |
lembrete_enviado |
A reminder was sent |
expirado |
The deadline passed without all signatures |
cancelado |
The sender canceled the envelope, with the reason |
documento_final_gerado |
The final copy was assembled and signed by the platform |
concluido |
The envelope was completed |
conclusao_retomada |
Completion was resumed manually after a failure |
webhook_entregue |
An event notification was delivered to the account's system |
ancoragem |
The hash of the day was sealed with a timestamp (see below) |
Each event stores the date and time in UTC with microseconds, the IP and browser of whoever acted (when a person is acting), the location when the signer consented, and data specific to the event type (for example, the code channel or the hash of the final copy).
Note the trail never stores name, email address, phone number, CPF, selfie or identity document. It refers to the signer only by an internal identifier; personal data is kept separately and encrypted.
Hash chaining#
The events form a chain: the hash of each event is calculated from the content of the event and the hash of the previous event. Changing, inserting or deleting any older record changes all the following hashes, and the break shows up in verification. In addition, the records are append-only: no path in the system changes or deletes an event.
The chain is single for the whole platform, spanning all accounts. This means that not even rewriting the entire trail of an envelope would go unnoticed: it would break the sequence of the events of all the other envelopes recorded afterwards.
The hash of the last event of each envelope is printed on the manifest of the final copy and shown in the public validator.
Formula#
For anyone who needs to verify the trail independently (a forensic expert, for example), the formula is public:
hash = SHA-256( hash_anterior + "\n" + json_canonico(registro) )Where:
hash_anterioris the hash of the previous event in the chain, as 64 lowercase hexadecimal characters. The first event of the platform uses 64 zeros."\n"is a line break (a single byte 0x0A).registrois the object with exactly these fields:conta_id,envelope_id,signatario_id,tipo,dados,ip,user_agent,geoandocorrido_em. The sequential identifier of the event itself is not part of the calculation.- The result is written in lowercase hexadecimal.
Canonical JSON#
json_canonico always produces the same text for the same content:
- Keys are sorted alphabetically at all levels (including inside
dadosandgeo). - No spaces or line breaks between elements.
- Accented characters and other Unicode characters stay as they are (they do not become
\u00e7), and the slash/is not escaped. - Integers are output as integers (
42, not"42"). - A missing or empty field is output as
null. ocorrido_emis a UTC text in the formatAAAA-MM-DD HH:MM:SS.uuuuuu(with six digits of microseconds).
Verification example#
The snippet below recalculates the hash of an event from the previous hash and the record fields:
<?php
function ordenar($valor) {
if (!is_array($valor)) return $valor;
if (array_is_list($valor)) return array_map('ordenar', $valor);
ksort($valor, SORT_STRING);
return array_map('ordenar', $valor);
}
function hashEvento(string $hashAnterior, array $registro): string {
$canonico = json_encode(ordenar([
'conta_id' => $registro['conta_id'],
'envelope_id' => $registro['envelope_id'],
'signatario_id' => $registro['signatario_id'],
'tipo' => $registro['tipo'],
'dados' => $registro['dados'],
'ip' => $registro['ip'],
'user_agent' => $registro['user_agent'],
'geo' => $registro['geo'],
'ocorrido_em' => $registro['ocorrido_em'],
]), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
return hash('sha256', $hashAnterior . "\n" . $canonico);
}To verify a sequence, start from the hash_anterior of the first event in the range, recalculate each event in order and compare it with the recorded hash. The first difference points exactly to the altered record.
Daily anchoring#
Once a day, Ravisign takes the hash of the last event of the previous day and obtains an ICP-Brasil timestamp for it. The timestamp proves, through an independent authority, that this hash (and therefore the entire chain up to it) already existed on that date. The timestamp itself is recorded in the trail as an ancoragem event.
As a result, even if someone with full access to the platform tried to recalculate the entire chain from a given point, the hashes already anchored on previous days would no longer match the timestamps issued.
Where to view the trail#
- Panel: in the envelope detail view, in the History section, with the IP and hash of each event.
- API: the
envelopes/eventosaction returns the events in order with the hash of each one. For privacy, the API does not return personal data, IP or browser. See Envelopes in the API. - Public validator: shows the hash of the last event, the same one printed on the manifest.
Tip for a forensic examination that requires recalculating the chain with all fields, the account holder can request the complete records of the envelope from Ravi Systems support.
Retention#
The trail is evidence: it is kept even when the documents and personal data of an account are purged, for the period required for the regular exercise of rights. See Privacy and security.
Contact Ravi Systems support at the e-mail below.