Signing & E-Signature Audit
ClientCove's E-Signature system is browser-based: signers verify their identity with a one-time passcode, draw their signature directly in the browser, and the system generates a cryptographically hashed signed PDF with a complete audit trail. No external e-sign account needed.
The Signing Flow
A recipient's path from email to signed contract:
- Receive the notification email with a "View Contract" link
- Click the link — auto-authenticates and lands on the contract's view page
- Status flips from Pending → Viewed in the recipients table;
viewed_dateis stamped - Review the PDF in the embedded viewer
- Click Sign Contract
- OTP request — choose Email or SMS (if both are enabled), receive a 6-digit code
- Enter the code on screen — verification is logged with timestamp + IP
- Signature pad opens — draw signature with mouse or touch
- Confirm — ClientCove generates the signed PDF, applies the signature image to all your placed fields, and computes the SHA-256 hash
- Status flips to Signed,
sign_dateis stamped, sender is notified - Signer sees a confirmation page with download link to the signed PDF
The whole flow takes 60–90 seconds for most signers.
OTP Verification
A one-time passcode confirms the signer is who the contract was sent to (not someone who happened to get the email forwarded).
How it works
- Signer clicks Sign Contract
- ClientCove generates a 6-digit code, stores it in
wp_ccesign_otpswith a 10-minute expiry - The code is delivered via the configured method (Email or SMS)
- Signer enters the code on the contract page
- ClientCove verifies — match + not expired = success
- The verification is logged in the audit table with timestamp, IP, and user agent
What if the code expires?
The signer can request a new code from the OTP entry screen. The new code invalidates the old one.
What if delivery fails?
If email delivery is configured wrong (no SMTP) or SMS isn't set up, the OTP send will silently fail and the signer will see "Code sent" without receiving anything. Verify your email/SMS configuration in Settings → Email and Settings → SMS before going live.
OTP Methods: Email vs SMS
The OTP delivery method is set per contract via the esign_otp_method field:
| Method | Setup Required | Best For |
|---|---|---|
| Email (default) | WP Mail SMTP + a transactional sender (SendGrid, Mailgun, SES) | Default — works for any signer with an email address |
| SMS | Twilio configured in Settings → SMS | Signers who want a phone-based 2FA experience |
| Both | Both configured | Signer picks per-sign |
When Both is enabled, the signing page shows a method picker:
- Email — code sent to the signer's profile email
- SMS — code sent to the signer's profile phone
If you want SMS, the signer needs a phone number in their WordPress user profile.
Drawing the Signature
After OTP verification, the signature pad opens.
The pad
- A blank canvas sized to roughly match a real signature
- Mouse / trackpad / touch — draw with continuous strokes
- Clear button — wipe the canvas if you make a mistake
- Cancel — bails out of the signing flow without saving
Behavior on confirm
- The drawn signature is captured as a PNG
- ClientCove applies the PNG to every signature field placed for this signer
- Initial fields are auto-filled from the first letter(s) of each name part
- Name fields get the signer's full display name typed in
- Date fields get the current date
The same signature image is reused across all signature fields for this signer in this contract — they only draw it once, no matter how many places need their signature.
Multi-Signer Contracts
When a contract has multiple signers, each signer signs independently in their own browser session.
Per-signer state
The contract page intelligently shows different content based on who's viewing:
| Viewer state | What they see |
|---|---|
| Hasn't signed | Sign Contract button, signing flow available |
| Already signed | Their signed PDF + audit certificate |
| Doesn't have signing permission | View-only access to the original PDF |
For multi-recipient template sends, each recipient has their own submission post — so signing one recipient's copy doesn't affect another's.
Order of signing
Multi-signer contracts don't enforce a signing order — any signer can sign first, second, or last. The contract status only flips to Signed when all signers complete.
If you need ordered signing (signer 2 only sees the contract after signer 1 finishes), implement that with separate contracts: send contract A to signer 1, configure a content access grant on signing that unlocks contract B for signer 2.
Declining a Contract
A signer who doesn't want to sign can decline:
- On the contract page, click Decline
- A reason prompt appears (optional but recommended)
- Submit
- Status flips to Declined for this signer
- The rejection is logged: who, when, reason
- The sender is notified
For multi-signer contracts, declining by one signer doesn't void the entire contract. The contract stays open for other signers, but the contract status will never reach Signed until either:
- The declining signer reverses (rare; usually you'd void and re-send)
- An admin removes the declining signer from the contract
The Signed PDF
ClientCove generates the signed PDF on the server-side after each signer completes:
- Take the original PDF template
- Composite each placed field with the signer's signature image, initial, name, or date
- Flatten the layers into a single signed PDF
- Store in cloud storage (Google Cloud Storage by default)
- Save the public/signed URL to the
signed_pdf(orsubmission_signed_pdffor submissions) field - Compute the SHA-256 hash of the resulting PDF
The signed PDF is what recipients download — the original template is preserved separately.
PDF Hash & Integrity
After signing, ClientCove stores a SHA-256 hash of the signed PDF in the esign_pdf_hash field.
This hash:
- Is computed once at signing time
- Is stored alongside the signature record
- Can be re-computed at any time on the stored PDF and compared to the original hash to prove the file hasn't been altered
If you ever need to defend the contract in a dispute, the hash gives you a cryptographic proof that the PDF on file is byte-for-byte identical to what was signed.
To verify manually:
- Download the signed PDF
- Compute its SHA-256 hash with
shasum -a 256 <file>or any hash tool - Compare to the
esign_pdf_hashvalue in the contract record - Match = file is intact; mismatch = file has been altered after signing
The Audit Trail
Every event in the signing flow is logged to the wp_ccesign_audits table:
| Field | Purpose |
|---|---|
post_id | The contract or submission |
event | What happened (viewed, otp_requested, otp_verified, signed, declined, resent) |
actor_id | The user who triggered the event |
ip_address | Their IP at the time |
user_agent | Their browser/OS string |
metadata | JSON blob with event-specific details (OTP method, signature dimensions, etc.) |
timestamp | When it happened |
The audit table is append-only — entries are never modified or deleted.
Signing Certificate
After signing, the contract page displays a Signing Certificate section showing the audit trail in human-readable form.
For each signer, the certificate shows:
- Signer name and email
- Date and time of signature
- IP address and approximate location
- OTP delivery method used
- A list of audit events with timestamps
The certificate is included with the signed PDF when the recipient downloads — they get both the signed document and the proof of signing.
For multi-recipient contracts, each submission has its own certificate showing only that recipient's events.
The signing certificate is a permanent legal record. Once a contract is signed, the certificate cannot be edited or deleted. If you need to correct a contract, void it and create a new one — the original certificate remains in the database for audit purposes.