Skip to content

EnvelopeAuditEvent: describe the payload actually signed, and name 'revoked' - #1139

Open
EgorPPS wants to merge 1 commit into
mainfrom
docusigner-audit-signed-payload
Open

EgorPPS wants to merge 1 commit into
mainfrom
docusigner-audit-signed-payload

Conversation

@EgorPPS

@EgorPPS EgorPPS commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #1111, which registered docusigner's five ontologies. Descriptions only — no field, type or enum changes, and the schemaId is unchanged.

docusigner now writes signed audit events for the first time. The occasion is withdrawal: a sender stopping a document they had already sent out for signature.

1. signedPayload described a string we do not sign.

It said the composition is ${action}|${envelopeId}|${actorEName}|${occurredAt}. What the wallet actually signs is that composition with a domain tag, hashed and prefixed:

audit_<sha256("docusigner.audit.v1|<action>|<envelopeId>|<actorEName>|<occurredAt>")>

The tag is domain separation — an audit signature must not be replayable as a signature on a document. The hash keeps the signed string short and of fixed length (70 characters), which matters because it travels to the wallet inside a QR code somebody has to photograph.

This is the kind of schema error worth fixing quickly: a verifier following the old sentence recomposes a string that never existed, and concludes that a perfectly good signature is bad.

2. The class description named only declined as the action worth signing.

revoked belongs beside it — it is equally a statement its author may have to defend. The description now also states the timing, because the timing is a deliberate design choice rather than an implementation detail: the withdrawal is written unsigned the instant it takes effect, since stopping a document must not wait for somebody to find their phone, and the signature is asked for immediately afterwards. isAttested is what tells a reader which of the two they are holding, and an unsigned one must never be read as the sender's own statement.

🤖 Generated with Claude Code

…evoked'

docusigner now signs audit events, starting with 'revoked' — a sender
withdrawing a document they had already sent. Two corrections follow, both to
descriptions; no field, type or enum changes.

signedPayload said the actor signs `${action}|${envelopeId}|${actorEName}|
${occurredAt}`. What is actually signed is that composition with a domain tag,
hashed and prefixed: `audit_<sha256(docusigner.audit.v1|...)>`. The tag keeps
an audit signature from being replayable as a signature on a document, and the
hash keeps the string short and fixed-length so it survives a QR a phone camera
has to read. A verifier following the old sentence would recompose a string
that never existed and conclude a good signature was bad, which is the worst
way for a schema to be wrong.

The class description named 'declined' as the action worth signing. 'revoked'
belongs beside it for the same reason — it is a statement its author may have
to defend — and the timing is worth stating: the withdrawal is written
unsigned the instant it takes effect, because stopping a document must not
wait for somebody to find their phone, and is signed straight afterwards.
isAttested is what tells the two apart, and an unsigned one must never be read
as the sender's own statement.
@EgorPPS
EgorPPS requested a review from coodos as a code owner September 15, 2026 20:28
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 8c05dd59-ddd3-4238-a1ff-d0861378e022


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant