Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey) - #1111

Open
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration
Open

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey)#1111
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration

Conversation

@EgorPPS

Copy link
Copy Markdown
Contributor

Registers the five ontologies written by docusigner — document signing with eID, where signers are addressed by eName and every signature is made with the signer's own eID key. Live at https://docusigner.postplatforms.com

SchemaschemaIdWritten to
SigningEnvelope256510c7-692c-4bf5-8136-820cd178a266initiator's vault (canonical) + every signer's vault (reference)
EIDSignatureede4c610-9e22-4074-9598-82c915058f4fthe signer's own vault
EnvelopeAuditEvent8c2c245e-8714-41da-8407-14ab5ce8ea38the vault of whoever performed the step
HandwrittenSignature2a062bd7-c7a3-451e-b4ff-d1ada729bf46the person's own vault
DocumentKey83e80d2b-eb06-46f9-9ef8-a2d0ea262801every party's own vault

All five are in production use today. None is a placeholder.

Why these are separate types, not fields on existing ones

EIDSignature vs the registered Signature (b2c3d4e5-…-f12345678901).Signature sets additionalProperties: false and carries fileId / userId / md5Hash. A signature over a signing envelope needs envelopeId, fieldsHash, fieldSchemaVersion, role and order, and additionalProperties: false forecloses every one of them. It also needs the signer's own field values inlinefieldsHash cannot be recomputed without them, and verification must not depend on the signing platform's database still existing. Different subject, different verification procedure.

SigningEnvelope vs File. A File is bytes. A document under signature is a process: who was asked, in what order, what each of them has done, and — critically — the initiator's seal binding this document to exactly this list of signers. Without that seal an envelope is unsigned data that any admitted platform could rewrite.

DocumentKey vs putting the key in the envelope. The key is shared per party, on each party's own vault, so a signer can open the document in an application that is not ours. Its lifetime and its ACL are not the envelope's.

HandwrittenSignature. A person's drawn or typed signature image is their data, reusable across any application that needs it, and does not belong to whichever product they happened to draw it in.

Shape, in one line each

SigningEnvelopeoneOf discriminated on isReference. The canonical form (isReference: false) lives on the initiator's vault and requiresinitiatorSignature, initiatorSignedPayload, sealSchemaVersion and participants; the reference form lives on each signer's vault, carries canonicalOwnerEName + canonicalEnvelopeId, and is forbidden from carrying any of the canonical-only fields. The discriminator is enforced both ways so a reference cannot masquerade as an original.

EIDSignature — one participant's signature: signedPayload (the exact string handed to the wallet), signature, fieldsHash, fieldValues inline, docPlaintextSha256.

EnvelopeAuditEvent — one recorded step. isAttested says whether the actor signed it; dependencies makes signedPayload and signature live and die together, because half a proof is not a proof.

DocumentKey — AES-256-GCM key material, oneOf on isReference like the envelope.

HandwrittenSignature — the image (imageUri, imageSha256), how it was made (method: drawn / typed / uploaded), and whether it is the owner's default.

Cross-vault model

(eName, envelopeId) is the addressable unit, so every reference carries canonicalOwnerEName alongside canonicalEnvelopeId — an envelope id without a tenant addresses nothing. The canonical record is the single source of truth; signers hold references, never copies, because N copies of a document under signature is N versions of what was agreed.

What is NOT here, deliberately

  • The completed PDF is not referenced by a w3ds://file URI. It would land on the same public CDN as the source blob, carrying the decrypted document plus the identities of everyone who signed it. Only its hash is recorded, as an integrity checksum rather than as evidence.
  • No additionalProperties: false anywhere. eVault does not validate — measured: its own uploadFile writes envelopes that violate the registered File schema — so the restriction buys no safety and forecloses extension permanently.
  • identityAssurance is not a claim by the signer. It records what the signing platform knew about that person's identity at the moment they signed, read from their own vault. It sits beside the signature and is not covered by it; the schema description says so explicitly, so no reader can mistake it for something the signer asserted.

Checks

Schemas are draft-07 and validated by an ajv conformance suite in the docusigner repository, which asserts both directions of every discriminator and every required-field dependency. (That suite is how dependentRequired — a draft 2019-09 keyword, silently ignored under draft-07 — was caught and replaced with dependencies.)

None of these five schemaIds currently resolves on the ontology service, so nothing here collides.

…nvelopeAuditEvent, HandwrittenSignature, DocumentKey)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS
EgorPPS requested a review from coodos as a code ownerAugust 20, 2026 07:55
@coderabbitai

coderabbitaiBot commented Aug 20, 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: Pro Plus

Run ID: 3fb32423-3894-4bed-b1fe-55b56ac93eab


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.

…ound nothing'
This record is written once beside a signature and read for years, so a
momentary storage failure recorded as 'unknown' becomes a permanent false
statement about somebody whose identity is in fact established. The two are now
distinct levels, and the schema description says explicitly that a reader must
not collapse them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS

Copy link
Copy Markdown
ContributorAuthor

Pushed a correction to identityAssurance.level (on both eidSignature and signingEnvelope).

The enum was verified | attested | unknown. It is now verified | attested | unknown | unavailable, splitting two things that were one value:

  • unknown — we looked, and nothing at all is known about who holds this eName. An observation about the person.
  • unavailable — we could not look: their storage did not answer. An admission about us.

Worth a schema change rather than a comment because of where this value lives. It is written once, beside a signature, and read for years — there is no later pass that corrects it, the way a cache is corrected by the next refresh. A rate limit at the wrong second would therefore freeze "nothing is known about who holds this eName" into a contract about somebody whose passport had in fact been checked, and neither party would ever have a way to discover that the platform had simply failed to ask.

The description now states that the two must not be collapsed by a reader, since a reader who treats them as one reintroduces exactly the fault.

Credit where due: this came out of comparing notes with the Nootropic session, which was tracking the same class of fault — a transport failure being reported as a substantive answer — across several platforms.

Sign up for freeto 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.

2 participants

@EgorPPS@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey) - #1111

Open
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration
Open

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey)#1111
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration

Conversation

@EgorPPS

Copy link
Copy Markdown
Contributor

Registers the five ontologies written by docusigner — document signing with eID, where signers are addressed by eName and every signature is made with the signer's own eID key. Live at https://docusigner.postplatforms.com

SchemaschemaIdWritten to
SigningEnvelope256510c7-692c-4bf5-8136-820cd178a266initiator's vault (canonical) + every signer's vault (reference)
EIDSignatureede4c610-9e22-4074-9598-82c915058f4fthe signer's own vault
EnvelopeAuditEvent8c2c245e-8714-41da-8407-14ab5ce8ea38the vault of whoever performed the step
HandwrittenSignature2a062bd7-c7a3-451e-b4ff-d1ada729bf46the person's own vault
DocumentKey83e80d2b-eb06-46f9-9ef8-a2d0ea262801every party's own vault

All five are in production use today. None is a placeholder.

Why these are separate types, not fields on existing ones

EIDSignature vs the registered Signature (b2c3d4e5-…-f12345678901).Signature sets additionalProperties: false and carries fileId / userId / md5Hash. A signature over a signing envelope needs envelopeId, fieldsHash, fieldSchemaVersion, role and order, and additionalProperties: false forecloses every one of them. It also needs the signer's own field values inlinefieldsHash cannot be recomputed without them, and verification must not depend on the signing platform's database still existing. Different subject, different verification procedure.

SigningEnvelope vs File. A File is bytes. A document under signature is a process: who was asked, in what order, what each of them has done, and — critically — the initiator's seal binding this document to exactly this list of signers. Without that seal an envelope is unsigned data that any admitted platform could rewrite.

DocumentKey vs putting the key in the envelope. The key is shared per party, on each party's own vault, so a signer can open the document in an application that is not ours. Its lifetime and its ACL are not the envelope's.

HandwrittenSignature. A person's drawn or typed signature image is their data, reusable across any application that needs it, and does not belong to whichever product they happened to draw it in.

Shape, in one line each

SigningEnvelopeoneOf discriminated on isReference. The canonical form (isReference: false) lives on the initiator's vault and requiresinitiatorSignature, initiatorSignedPayload, sealSchemaVersion and participants; the reference form lives on each signer's vault, carries canonicalOwnerEName + canonicalEnvelopeId, and is forbidden from carrying any of the canonical-only fields. The discriminator is enforced both ways so a reference cannot masquerade as an original.

EIDSignature — one participant's signature: signedPayload (the exact string handed to the wallet), signature, fieldsHash, fieldValues inline, docPlaintextSha256.

EnvelopeAuditEvent — one recorded step. isAttested says whether the actor signed it; dependencies makes signedPayload and signature live and die together, because half a proof is not a proof.

DocumentKey — AES-256-GCM key material, oneOf on isReference like the envelope.

HandwrittenSignature — the image (imageUri, imageSha256), how it was made (method: drawn / typed / uploaded), and whether it is the owner's default.

Cross-vault model

(eName, envelopeId) is the addressable unit, so every reference carries canonicalOwnerEName alongside canonicalEnvelopeId — an envelope id without a tenant addresses nothing. The canonical record is the single source of truth; signers hold references, never copies, because N copies of a document under signature is N versions of what was agreed.

What is NOT here, deliberately

  • The completed PDF is not referenced by a w3ds://file URI. It would land on the same public CDN as the source blob, carrying the decrypted document plus the identities of everyone who signed it. Only its hash is recorded, as an integrity checksum rather than as evidence.
  • No additionalProperties: false anywhere. eVault does not validate — measured: its own uploadFile writes envelopes that violate the registered File schema — so the restriction buys no safety and forecloses extension permanently.
  • identityAssurance is not a claim by the signer. It records what the signing platform knew about that person's identity at the moment they signed, read from their own vault. It sits beside the signature and is not covered by it; the schema description says so explicitly, so no reader can mistake it for something the signer asserted.

Checks

Schemas are draft-07 and validated by an ajv conformance suite in the docusigner repository, which asserts both directions of every discriminator and every required-field dependency. (That suite is how dependentRequired — a draft 2019-09 keyword, silently ignored under draft-07 — was caught and replaced with dependencies.)

None of these five schemaIds currently resolves on the ontology service, so nothing here collides.

…nvelopeAuditEvent, HandwrittenSignature, DocumentKey)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS
EgorPPS requested a review from coodos as a code ownerAugust 20, 2026 07:55
@coderabbitai

coderabbitaiBot commented Aug 20, 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: Pro Plus

Run ID: 3fb32423-3894-4bed-b1fe-55b56ac93eab


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.

…ound nothing'
This record is written once beside a signature and read for years, so a
momentary storage failure recorded as 'unknown' becomes a permanent false
statement about somebody whose identity is in fact established. The two are now
distinct levels, and the schema description says explicitly that a reader must
not collapse them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS

Copy link
Copy Markdown
ContributorAuthor

Pushed a correction to identityAssurance.level (on both eidSignature and signingEnvelope).

The enum was verified | attested | unknown. It is now verified | attested | unknown | unavailable, splitting two things that were one value:

  • unknown — we looked, and nothing at all is known about who holds this eName. An observation about the person.
  • unavailable — we could not look: their storage did not answer. An admission about us.

Worth a schema change rather than a comment because of where this value lives. It is written once, beside a signature, and read for years — there is no later pass that corrects it, the way a cache is corrected by the next refresh. A rate limit at the wrong second would therefore freeze "nothing is known about who holds this eName" into a contract about somebody whose passport had in fact been checked, and neither party would ever have a way to discover that the platform had simply failed to ask.

The description now states that the two must not be collapsed by a reader, since a reader who treats them as one reintroduces exactly the fault.

Credit where due: this came out of comparing notes with the Nootropic session, which was tracking the same class of fault — a transport failure being reported as a substantive answer — across several platforms.

Sign up for freeto 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.

2 participants

@EgorPPS@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey) - #1111

Open
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration
Open

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey)#1111
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration

Conversation

@EgorPPS

Copy link
Copy Markdown
Contributor

Registers the five ontologies written by docusigner — document signing with eID, where signers are addressed by eName and every signature is made with the signer's own eID key. Live at https://docusigner.postplatforms.com

SchemaschemaIdWritten to
SigningEnvelope256510c7-692c-4bf5-8136-820cd178a266initiator's vault (canonical) + every signer's vault (reference)
EIDSignatureede4c610-9e22-4074-9598-82c915058f4fthe signer's own vault
EnvelopeAuditEvent8c2c245e-8714-41da-8407-14ab5ce8ea38the vault of whoever performed the step
HandwrittenSignature2a062bd7-c7a3-451e-b4ff-d1ada729bf46the person's own vault
DocumentKey83e80d2b-eb06-46f9-9ef8-a2d0ea262801every party's own vault

All five are in production use today. None is a placeholder.

Why these are separate types, not fields on existing ones

EIDSignature vs the registered Signature (b2c3d4e5-…-f12345678901).Signature sets additionalProperties: false and carries fileId / userId / md5Hash. A signature over a signing envelope needs envelopeId, fieldsHash, fieldSchemaVersion, role and order, and additionalProperties: false forecloses every one of them. It also needs the signer's own field values inlinefieldsHash cannot be recomputed without them, and verification must not depend on the signing platform's database still existing. Different subject, different verification procedure.

SigningEnvelope vs File. A File is bytes. A document under signature is a process: who was asked, in what order, what each of them has done, and — critically — the initiator's seal binding this document to exactly this list of signers. Without that seal an envelope is unsigned data that any admitted platform could rewrite.

DocumentKey vs putting the key in the envelope. The key is shared per party, on each party's own vault, so a signer can open the document in an application that is not ours. Its lifetime and its ACL are not the envelope's.

HandwrittenSignature. A person's drawn or typed signature image is their data, reusable across any application that needs it, and does not belong to whichever product they happened to draw it in.

Shape, in one line each

SigningEnvelopeoneOf discriminated on isReference. The canonical form (isReference: false) lives on the initiator's vault and requiresinitiatorSignature, initiatorSignedPayload, sealSchemaVersion and participants; the reference form lives on each signer's vault, carries canonicalOwnerEName + canonicalEnvelopeId, and is forbidden from carrying any of the canonical-only fields. The discriminator is enforced both ways so a reference cannot masquerade as an original.

EIDSignature — one participant's signature: signedPayload (the exact string handed to the wallet), signature, fieldsHash, fieldValues inline, docPlaintextSha256.

EnvelopeAuditEvent — one recorded step. isAttested says whether the actor signed it; dependencies makes signedPayload and signature live and die together, because half a proof is not a proof.

DocumentKey — AES-256-GCM key material, oneOf on isReference like the envelope.

HandwrittenSignature — the image (imageUri, imageSha256), how it was made (method: drawn / typed / uploaded), and whether it is the owner's default.

Cross-vault model

(eName, envelopeId) is the addressable unit, so every reference carries canonicalOwnerEName alongside canonicalEnvelopeId — an envelope id without a tenant addresses nothing. The canonical record is the single source of truth; signers hold references, never copies, because N copies of a document under signature is N versions of what was agreed.

What is NOT here, deliberately

  • The completed PDF is not referenced by a w3ds://file URI. It would land on the same public CDN as the source blob, carrying the decrypted document plus the identities of everyone who signed it. Only its hash is recorded, as an integrity checksum rather than as evidence.
  • No additionalProperties: false anywhere. eVault does not validate — measured: its own uploadFile writes envelopes that violate the registered File schema — so the restriction buys no safety and forecloses extension permanently.
  • identityAssurance is not a claim by the signer. It records what the signing platform knew about that person's identity at the moment they signed, read from their own vault. It sits beside the signature and is not covered by it; the schema description says so explicitly, so no reader can mistake it for something the signer asserted.

Checks

Schemas are draft-07 and validated by an ajv conformance suite in the docusigner repository, which asserts both directions of every discriminator and every required-field dependency. (That suite is how dependentRequired — a draft 2019-09 keyword, silently ignored under draft-07 — was caught and replaced with dependencies.)

None of these five schemaIds currently resolves on the ontology service, so nothing here collides.

…nvelopeAuditEvent, HandwrittenSignature, DocumentKey)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS
EgorPPS requested a review from coodos as a code ownerAugust 20, 2026 07:55
@coderabbitai

coderabbitaiBot commented Aug 20, 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: Pro Plus

Run ID: 3fb32423-3894-4bed-b1fe-55b56ac93eab


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.

…ound nothing'
This record is written once beside a signature and read for years, so a
momentary storage failure recorded as 'unknown' becomes a permanent false
statement about somebody whose identity is in fact established. The two are now
distinct levels, and the schema description says explicitly that a reader must
not collapse them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS

Copy link
Copy Markdown
ContributorAuthor

Pushed a correction to identityAssurance.level (on both eidSignature and signingEnvelope).

The enum was verified | attested | unknown. It is now verified | attested | unknown | unavailable, splitting two things that were one value:

  • unknown — we looked, and nothing at all is known about who holds this eName. An observation about the person.
  • unavailable — we could not look: their storage did not answer. An admission about us.

Worth a schema change rather than a comment because of where this value lives. It is written once, beside a signature, and read for years — there is no later pass that corrects it, the way a cache is corrected by the next refresh. A rate limit at the wrong second would therefore freeze "nothing is known about who holds this eName" into a contract about somebody whose passport had in fact been checked, and neither party would ever have a way to discover that the platform had simply failed to ask.

The description now states that the two must not be collapsed by a reader, since a reader who treats them as one reintroduces exactly the fault.

Credit where due: this came out of comparing notes with the Nootropic session, which was tracking the same class of fault — a transport failure being reported as a substantive answer — across several platforms.

Sign up for freeto 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.

2 participants

@EgorPPS@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey) - #1111

Open
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration
Open

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey)#1111
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration

Conversation

@EgorPPS

Copy link
Copy Markdown
Contributor

Registers the five ontologies written by docusigner — document signing with eID, where signers are addressed by eName and every signature is made with the signer's own eID key. Live at https://docusigner.postplatforms.com

SchemaschemaIdWritten to
SigningEnvelope256510c7-692c-4bf5-8136-820cd178a266initiator's vault (canonical) + every signer's vault (reference)
EIDSignatureede4c610-9e22-4074-9598-82c915058f4fthe signer's own vault
EnvelopeAuditEvent8c2c245e-8714-41da-8407-14ab5ce8ea38the vault of whoever performed the step
HandwrittenSignature2a062bd7-c7a3-451e-b4ff-d1ada729bf46the person's own vault
DocumentKey83e80d2b-eb06-46f9-9ef8-a2d0ea262801every party's own vault

All five are in production use today. None is a placeholder.

Why these are separate types, not fields on existing ones

EIDSignature vs the registered Signature (b2c3d4e5-…-f12345678901).Signature sets additionalProperties: false and carries fileId / userId / md5Hash. A signature over a signing envelope needs envelopeId, fieldsHash, fieldSchemaVersion, role and order, and additionalProperties: false forecloses every one of them. It also needs the signer's own field values inlinefieldsHash cannot be recomputed without them, and verification must not depend on the signing platform's database still existing. Different subject, different verification procedure.

SigningEnvelope vs File. A File is bytes. A document under signature is a process: who was asked, in what order, what each of them has done, and — critically — the initiator's seal binding this document to exactly this list of signers. Without that seal an envelope is unsigned data that any admitted platform could rewrite.

DocumentKey vs putting the key in the envelope. The key is shared per party, on each party's own vault, so a signer can open the document in an application that is not ours. Its lifetime and its ACL are not the envelope's.

HandwrittenSignature. A person's drawn or typed signature image is their data, reusable across any application that needs it, and does not belong to whichever product they happened to draw it in.

Shape, in one line each

SigningEnvelopeoneOf discriminated on isReference. The canonical form (isReference: false) lives on the initiator's vault and requiresinitiatorSignature, initiatorSignedPayload, sealSchemaVersion and participants; the reference form lives on each signer's vault, carries canonicalOwnerEName + canonicalEnvelopeId, and is forbidden from carrying any of the canonical-only fields. The discriminator is enforced both ways so a reference cannot masquerade as an original.

EIDSignature — one participant's signature: signedPayload (the exact string handed to the wallet), signature, fieldsHash, fieldValues inline, docPlaintextSha256.

EnvelopeAuditEvent — one recorded step. isAttested says whether the actor signed it; dependencies makes signedPayload and signature live and die together, because half a proof is not a proof.

DocumentKey — AES-256-GCM key material, oneOf on isReference like the envelope.

HandwrittenSignature — the image (imageUri, imageSha256), how it was made (method: drawn / typed / uploaded), and whether it is the owner's default.

Cross-vault model

(eName, envelopeId) is the addressable unit, so every reference carries canonicalOwnerEName alongside canonicalEnvelopeId — an envelope id without a tenant addresses nothing. The canonical record is the single source of truth; signers hold references, never copies, because N copies of a document under signature is N versions of what was agreed.

What is NOT here, deliberately

  • The completed PDF is not referenced by a w3ds://file URI. It would land on the same public CDN as the source blob, carrying the decrypted document plus the identities of everyone who signed it. Only its hash is recorded, as an integrity checksum rather than as evidence.
  • No additionalProperties: false anywhere. eVault does not validate — measured: its own uploadFile writes envelopes that violate the registered File schema — so the restriction buys no safety and forecloses extension permanently.
  • identityAssurance is not a claim by the signer. It records what the signing platform knew about that person's identity at the moment they signed, read from their own vault. It sits beside the signature and is not covered by it; the schema description says so explicitly, so no reader can mistake it for something the signer asserted.

Checks

Schemas are draft-07 and validated by an ajv conformance suite in the docusigner repository, which asserts both directions of every discriminator and every required-field dependency. (That suite is how dependentRequired — a draft 2019-09 keyword, silently ignored under draft-07 — was caught and replaced with dependencies.)

None of these five schemaIds currently resolves on the ontology service, so nothing here collides.

…nvelopeAuditEvent, HandwrittenSignature, DocumentKey)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS
EgorPPS requested a review from coodos as a code ownerAugust 20, 2026 07:55
@coderabbitai

coderabbitaiBot commented Aug 20, 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: Pro Plus

Run ID: 3fb32423-3894-4bed-b1fe-55b56ac93eab


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.

…ound nothing'
This record is written once beside a signature and read for years, so a
momentary storage failure recorded as 'unknown' becomes a permanent false
statement about somebody whose identity is in fact established. The two are now
distinct levels, and the schema description says explicitly that a reader must
not collapse them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS

Copy link
Copy Markdown
ContributorAuthor

Pushed a correction to identityAssurance.level (on both eidSignature and signingEnvelope).

The enum was verified | attested | unknown. It is now verified | attested | unknown | unavailable, splitting two things that were one value:

  • unknown — we looked, and nothing at all is known about who holds this eName. An observation about the person.
  • unavailable — we could not look: their storage did not answer. An admission about us.

Worth a schema change rather than a comment because of where this value lives. It is written once, beside a signature, and read for years — there is no later pass that corrects it, the way a cache is corrected by the next refresh. A rate limit at the wrong second would therefore freeze "nothing is known about who holds this eName" into a contract about somebody whose passport had in fact been checked, and neither party would ever have a way to discover that the platform had simply failed to ask.

The description now states that the two must not be collapsed by a reader, since a reader who treats them as one reintroduces exactly the fault.

Credit where due: this came out of comparing notes with the Nootropic session, which was tracking the same class of fault — a transport failure being reported as a substantive answer — across several platforms.

Sign up for freeto 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.

2 participants

@EgorPPS@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey) - #1111

Open
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration
Open

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey)#1111
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration

Conversation

@EgorPPS

Copy link
Copy Markdown
Contributor

Registers the five ontologies written by docusigner — document signing with eID, where signers are addressed by eName and every signature is made with the signer's own eID key. Live at https://docusigner.postplatforms.com

SchemaschemaIdWritten to
SigningEnvelope256510c7-692c-4bf5-8136-820cd178a266initiator's vault (canonical) + every signer's vault (reference)
EIDSignatureede4c610-9e22-4074-9598-82c915058f4fthe signer's own vault
EnvelopeAuditEvent8c2c245e-8714-41da-8407-14ab5ce8ea38the vault of whoever performed the step
HandwrittenSignature2a062bd7-c7a3-451e-b4ff-d1ada729bf46the person's own vault
DocumentKey83e80d2b-eb06-46f9-9ef8-a2d0ea262801every party's own vault

All five are in production use today. None is a placeholder.

Why these are separate types, not fields on existing ones

EIDSignature vs the registered Signature (b2c3d4e5-…-f12345678901).Signature sets additionalProperties: false and carries fileId / userId / md5Hash. A signature over a signing envelope needs envelopeId, fieldsHash, fieldSchemaVersion, role and order, and additionalProperties: false forecloses every one of them. It also needs the signer's own field values inlinefieldsHash cannot be recomputed without them, and verification must not depend on the signing platform's database still existing. Different subject, different verification procedure.

SigningEnvelope vs File. A File is bytes. A document under signature is a process: who was asked, in what order, what each of them has done, and — critically — the initiator's seal binding this document to exactly this list of signers. Without that seal an envelope is unsigned data that any admitted platform could rewrite.

DocumentKey vs putting the key in the envelope. The key is shared per party, on each party's own vault, so a signer can open the document in an application that is not ours. Its lifetime and its ACL are not the envelope's.

HandwrittenSignature. A person's drawn or typed signature image is their data, reusable across any application that needs it, and does not belong to whichever product they happened to draw it in.

Shape, in one line each

SigningEnvelopeoneOf discriminated on isReference. The canonical form (isReference: false) lives on the initiator's vault and requiresinitiatorSignature, initiatorSignedPayload, sealSchemaVersion and participants; the reference form lives on each signer's vault, carries canonicalOwnerEName + canonicalEnvelopeId, and is forbidden from carrying any of the canonical-only fields. The discriminator is enforced both ways so a reference cannot masquerade as an original.

EIDSignature — one participant's signature: signedPayload (the exact string handed to the wallet), signature, fieldsHash, fieldValues inline, docPlaintextSha256.

EnvelopeAuditEvent — one recorded step. isAttested says whether the actor signed it; dependencies makes signedPayload and signature live and die together, because half a proof is not a proof.

DocumentKey — AES-256-GCM key material, oneOf on isReference like the envelope.

HandwrittenSignature — the image (imageUri, imageSha256), how it was made (method: drawn / typed / uploaded), and whether it is the owner's default.

Cross-vault model

(eName, envelopeId) is the addressable unit, so every reference carries canonicalOwnerEName alongside canonicalEnvelopeId — an envelope id without a tenant addresses nothing. The canonical record is the single source of truth; signers hold references, never copies, because N copies of a document under signature is N versions of what was agreed.

What is NOT here, deliberately

  • The completed PDF is not referenced by a w3ds://file URI. It would land on the same public CDN as the source blob, carrying the decrypted document plus the identities of everyone who signed it. Only its hash is recorded, as an integrity checksum rather than as evidence.
  • No additionalProperties: false anywhere. eVault does not validate — measured: its own uploadFile writes envelopes that violate the registered File schema — so the restriction buys no safety and forecloses extension permanently.
  • identityAssurance is not a claim by the signer. It records what the signing platform knew about that person's identity at the moment they signed, read from their own vault. It sits beside the signature and is not covered by it; the schema description says so explicitly, so no reader can mistake it for something the signer asserted.

Checks

Schemas are draft-07 and validated by an ajv conformance suite in the docusigner repository, which asserts both directions of every discriminator and every required-field dependency. (That suite is how dependentRequired — a draft 2019-09 keyword, silently ignored under draft-07 — was caught and replaced with dependencies.)

None of these five schemaIds currently resolves on the ontology service, so nothing here collides.

…nvelopeAuditEvent, HandwrittenSignature, DocumentKey)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS
EgorPPS requested a review from coodos as a code ownerAugust 20, 2026 07:55
@coderabbitai

coderabbitaiBot commented Aug 20, 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: Pro Plus

Run ID: 3fb32423-3894-4bed-b1fe-55b56ac93eab


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.

…ound nothing'
This record is written once beside a signature and read for years, so a
momentary storage failure recorded as 'unknown' becomes a permanent false
statement about somebody whose identity is in fact established. The two are now
distinct levels, and the schema description says explicitly that a reader must
not collapse them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS

Copy link
Copy Markdown
ContributorAuthor

Pushed a correction to identityAssurance.level (on both eidSignature and signingEnvelope).

The enum was verified | attested | unknown. It is now verified | attested | unknown | unavailable, splitting two things that were one value:

  • unknown — we looked, and nothing at all is known about who holds this eName. An observation about the person.
  • unavailable — we could not look: their storage did not answer. An admission about us.

Worth a schema change rather than a comment because of where this value lives. It is written once, beside a signature, and read for years — there is no later pass that corrects it, the way a cache is corrected by the next refresh. A rate limit at the wrong second would therefore freeze "nothing is known about who holds this eName" into a contract about somebody whose passport had in fact been checked, and neither party would ever have a way to discover that the platform had simply failed to ask.

The description now states that the two must not be collapsed by a reader, since a reader who treats them as one reintroduces exactly the fault.

Credit where due: this came out of comparing notes with the Nootropic session, which was tracking the same class of fault — a transport failure being reported as a substantive answer — across several platforms.

Sign up for freeto 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.

2 participants

@EgorPPS@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey) - #1111

Open
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration
Open

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey)#1111
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration

Conversation

@EgorPPS

Copy link
Copy Markdown
Contributor

Registers the five ontologies written by docusigner — document signing with eID, where signers are addressed by eName and every signature is made with the signer's own eID key. Live at https://docusigner.postplatforms.com

SchemaschemaIdWritten to
SigningEnvelope256510c7-692c-4bf5-8136-820cd178a266initiator's vault (canonical) + every signer's vault (reference)
EIDSignatureede4c610-9e22-4074-9598-82c915058f4fthe signer's own vault
EnvelopeAuditEvent8c2c245e-8714-41da-8407-14ab5ce8ea38the vault of whoever performed the step
HandwrittenSignature2a062bd7-c7a3-451e-b4ff-d1ada729bf46the person's own vault
DocumentKey83e80d2b-eb06-46f9-9ef8-a2d0ea262801every party's own vault

All five are in production use today. None is a placeholder.

Why these are separate types, not fields on existing ones

EIDSignature vs the registered Signature (b2c3d4e5-…-f12345678901).Signature sets additionalProperties: false and carries fileId / userId / md5Hash. A signature over a signing envelope needs envelopeId, fieldsHash, fieldSchemaVersion, role and order, and additionalProperties: false forecloses every one of them. It also needs the signer's own field values inlinefieldsHash cannot be recomputed without them, and verification must not depend on the signing platform's database still existing. Different subject, different verification procedure.

SigningEnvelope vs File. A File is bytes. A document under signature is a process: who was asked, in what order, what each of them has done, and — critically — the initiator's seal binding this document to exactly this list of signers. Without that seal an envelope is unsigned data that any admitted platform could rewrite.

DocumentKey vs putting the key in the envelope. The key is shared per party, on each party's own vault, so a signer can open the document in an application that is not ours. Its lifetime and its ACL are not the envelope's.

HandwrittenSignature. A person's drawn or typed signature image is their data, reusable across any application that needs it, and does not belong to whichever product they happened to draw it in.

Shape, in one line each

SigningEnvelopeoneOf discriminated on isReference. The canonical form (isReference: false) lives on the initiator's vault and requiresinitiatorSignature, initiatorSignedPayload, sealSchemaVersion and participants; the reference form lives on each signer's vault, carries canonicalOwnerEName + canonicalEnvelopeId, and is forbidden from carrying any of the canonical-only fields. The discriminator is enforced both ways so a reference cannot masquerade as an original.

EIDSignature — one participant's signature: signedPayload (the exact string handed to the wallet), signature, fieldsHash, fieldValues inline, docPlaintextSha256.

EnvelopeAuditEvent — one recorded step. isAttested says whether the actor signed it; dependencies makes signedPayload and signature live and die together, because half a proof is not a proof.

DocumentKey — AES-256-GCM key material, oneOf on isReference like the envelope.

HandwrittenSignature — the image (imageUri, imageSha256), how it was made (method: drawn / typed / uploaded), and whether it is the owner's default.

Cross-vault model

(eName, envelopeId) is the addressable unit, so every reference carries canonicalOwnerEName alongside canonicalEnvelopeId — an envelope id without a tenant addresses nothing. The canonical record is the single source of truth; signers hold references, never copies, because N copies of a document under signature is N versions of what was agreed.

What is NOT here, deliberately

  • The completed PDF is not referenced by a w3ds://file URI. It would land on the same public CDN as the source blob, carrying the decrypted document plus the identities of everyone who signed it. Only its hash is recorded, as an integrity checksum rather than as evidence.
  • No additionalProperties: false anywhere. eVault does not validate — measured: its own uploadFile writes envelopes that violate the registered File schema — so the restriction buys no safety and forecloses extension permanently.
  • identityAssurance is not a claim by the signer. It records what the signing platform knew about that person's identity at the moment they signed, read from their own vault. It sits beside the signature and is not covered by it; the schema description says so explicitly, so no reader can mistake it for something the signer asserted.

Checks

Schemas are draft-07 and validated by an ajv conformance suite in the docusigner repository, which asserts both directions of every discriminator and every required-field dependency. (That suite is how dependentRequired — a draft 2019-09 keyword, silently ignored under draft-07 — was caught and replaced with dependencies.)

None of these five schemaIds currently resolves on the ontology service, so nothing here collides.

…nvelopeAuditEvent, HandwrittenSignature, DocumentKey)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS
EgorPPS requested a review from coodos as a code ownerAugust 20, 2026 07:55
@coderabbitai

coderabbitaiBot commented Aug 20, 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: Pro Plus

Run ID: 3fb32423-3894-4bed-b1fe-55b56ac93eab


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.

…ound nothing'
This record is written once beside a signature and read for years, so a
momentary storage failure recorded as 'unknown' becomes a permanent false
statement about somebody whose identity is in fact established. The two are now
distinct levels, and the schema description says explicitly that a reader must
not collapse them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS

Copy link
Copy Markdown
ContributorAuthor

Pushed a correction to identityAssurance.level (on both eidSignature and signingEnvelope).

The enum was verified | attested | unknown. It is now verified | attested | unknown | unavailable, splitting two things that were one value:

  • unknown — we looked, and nothing at all is known about who holds this eName. An observation about the person.
  • unavailable — we could not look: their storage did not answer. An admission about us.

Worth a schema change rather than a comment because of where this value lives. It is written once, beside a signature, and read for years — there is no later pass that corrects it, the way a cache is corrected by the next refresh. A rate limit at the wrong second would therefore freeze "nothing is known about who holds this eName" into a contract about somebody whose passport had in fact been checked, and neither party would ever have a way to discover that the platform had simply failed to ask.

The description now states that the two must not be collapsed by a reader, since a reader who treats them as one reintroduces exactly the fault.

Credit where due: this came out of comparing notes with the Nootropic session, which was tracking the same class of fault — a transport failure being reported as a substantive answer — across several platforms.

Sign up for freeto 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.

2 participants

@EgorPPS@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey) - #1111

Open
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration
Open

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey)#1111
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration

Conversation

@EgorPPS

Copy link
Copy Markdown
Contributor

Registers the five ontologies written by docusigner — document signing with eID, where signers are addressed by eName and every signature is made with the signer's own eID key. Live at https://docusigner.postplatforms.com

SchemaschemaIdWritten to
SigningEnvelope256510c7-692c-4bf5-8136-820cd178a266initiator's vault (canonical) + every signer's vault (reference)
EIDSignatureede4c610-9e22-4074-9598-82c915058f4fthe signer's own vault
EnvelopeAuditEvent8c2c245e-8714-41da-8407-14ab5ce8ea38the vault of whoever performed the step
HandwrittenSignature2a062bd7-c7a3-451e-b4ff-d1ada729bf46the person's own vault
DocumentKey83e80d2b-eb06-46f9-9ef8-a2d0ea262801every party's own vault

All five are in production use today. None is a placeholder.

Why these are separate types, not fields on existing ones

EIDSignature vs the registered Signature (b2c3d4e5-…-f12345678901).Signature sets additionalProperties: false and carries fileId / userId / md5Hash. A signature over a signing envelope needs envelopeId, fieldsHash, fieldSchemaVersion, role and order, and additionalProperties: false forecloses every one of them. It also needs the signer's own field values inlinefieldsHash cannot be recomputed without them, and verification must not depend on the signing platform's database still existing. Different subject, different verification procedure.

SigningEnvelope vs File. A File is bytes. A document under signature is a process: who was asked, in what order, what each of them has done, and — critically — the initiator's seal binding this document to exactly this list of signers. Without that seal an envelope is unsigned data that any admitted platform could rewrite.

DocumentKey vs putting the key in the envelope. The key is shared per party, on each party's own vault, so a signer can open the document in an application that is not ours. Its lifetime and its ACL are not the envelope's.

HandwrittenSignature. A person's drawn or typed signature image is their data, reusable across any application that needs it, and does not belong to whichever product they happened to draw it in.

Shape, in one line each

SigningEnvelopeoneOf discriminated on isReference. The canonical form (isReference: false) lives on the initiator's vault and requiresinitiatorSignature, initiatorSignedPayload, sealSchemaVersion and participants; the reference form lives on each signer's vault, carries canonicalOwnerEName + canonicalEnvelopeId, and is forbidden from carrying any of the canonical-only fields. The discriminator is enforced both ways so a reference cannot masquerade as an original.

EIDSignature — one participant's signature: signedPayload (the exact string handed to the wallet), signature, fieldsHash, fieldValues inline, docPlaintextSha256.

EnvelopeAuditEvent — one recorded step. isAttested says whether the actor signed it; dependencies makes signedPayload and signature live and die together, because half a proof is not a proof.

DocumentKey — AES-256-GCM key material, oneOf on isReference like the envelope.

HandwrittenSignature — the image (imageUri, imageSha256), how it was made (method: drawn / typed / uploaded), and whether it is the owner's default.

Cross-vault model

(eName, envelopeId) is the addressable unit, so every reference carries canonicalOwnerEName alongside canonicalEnvelopeId — an envelope id without a tenant addresses nothing. The canonical record is the single source of truth; signers hold references, never copies, because N copies of a document under signature is N versions of what was agreed.

What is NOT here, deliberately

  • The completed PDF is not referenced by a w3ds://file URI. It would land on the same public CDN as the source blob, carrying the decrypted document plus the identities of everyone who signed it. Only its hash is recorded, as an integrity checksum rather than as evidence.
  • No additionalProperties: false anywhere. eVault does not validate — measured: its own uploadFile writes envelopes that violate the registered File schema — so the restriction buys no safety and forecloses extension permanently.
  • identityAssurance is not a claim by the signer. It records what the signing platform knew about that person's identity at the moment they signed, read from their own vault. It sits beside the signature and is not covered by it; the schema description says so explicitly, so no reader can mistake it for something the signer asserted.

Checks

Schemas are draft-07 and validated by an ajv conformance suite in the docusigner repository, which asserts both directions of every discriminator and every required-field dependency. (That suite is how dependentRequired — a draft 2019-09 keyword, silently ignored under draft-07 — was caught and replaced with dependencies.)

None of these five schemaIds currently resolves on the ontology service, so nothing here collides.

…nvelopeAuditEvent, HandwrittenSignature, DocumentKey)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS
EgorPPS requested a review from coodos as a code ownerAugust 20, 2026 07:55
@coderabbitai

coderabbitaiBot commented Aug 20, 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: Pro Plus

Run ID: 3fb32423-3894-4bed-b1fe-55b56ac93eab


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.

…ound nothing'
This record is written once beside a signature and read for years, so a
momentary storage failure recorded as 'unknown' becomes a permanent false
statement about somebody whose identity is in fact established. The two are now
distinct levels, and the schema description says explicitly that a reader must
not collapse them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS

Copy link
Copy Markdown
ContributorAuthor

Pushed a correction to identityAssurance.level (on both eidSignature and signingEnvelope).

The enum was verified | attested | unknown. It is now verified | attested | unknown | unavailable, splitting two things that were one value:

  • unknown — we looked, and nothing at all is known about who holds this eName. An observation about the person.
  • unavailable — we could not look: their storage did not answer. An admission about us.

Worth a schema change rather than a comment because of where this value lives. It is written once, beside a signature, and read for years — there is no later pass that corrects it, the way a cache is corrected by the next refresh. A rate limit at the wrong second would therefore freeze "nothing is known about who holds this eName" into a contract about somebody whose passport had in fact been checked, and neither party would ever have a way to discover that the platform had simply failed to ask.

The description now states that the two must not be collapsed by a reader, since a reader who treats them as one reintroduces exactly the fault.

Credit where due: this came out of comparing notes with the Nootropic session, which was tracking the same class of fault — a transport failure being reported as a substantive answer — across several platforms.

Sign up for freeto 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.

2 participants

@EgorPPS@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey) - #1111

Open
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration
Open

Register five docusigner ontologies (SigningEnvelope, EIDSignature, EnvelopeAuditEvent, HandwrittenSignature, DocumentKey)#1111
EgorPPS wants to merge 2 commits into
mainfrom
docusigner-ontologies-registration

Conversation

@EgorPPS

Copy link
Copy Markdown
Contributor

Registers the five ontologies written by docusigner — document signing with eID, where signers are addressed by eName and every signature is made with the signer's own eID key. Live at https://docusigner.postplatforms.com

SchemaschemaIdWritten to
SigningEnvelope256510c7-692c-4bf5-8136-820cd178a266initiator's vault (canonical) + every signer's vault (reference)
EIDSignatureede4c610-9e22-4074-9598-82c915058f4fthe signer's own vault
EnvelopeAuditEvent8c2c245e-8714-41da-8407-14ab5ce8ea38the vault of whoever performed the step
HandwrittenSignature2a062bd7-c7a3-451e-b4ff-d1ada729bf46the person's own vault
DocumentKey83e80d2b-eb06-46f9-9ef8-a2d0ea262801every party's own vault

All five are in production use today. None is a placeholder.

Why these are separate types, not fields on existing ones

EIDSignature vs the registered Signature (b2c3d4e5-…-f12345678901).Signature sets additionalProperties: false and carries fileId / userId / md5Hash. A signature over a signing envelope needs envelopeId, fieldsHash, fieldSchemaVersion, role and order, and additionalProperties: false forecloses every one of them. It also needs the signer's own field values inlinefieldsHash cannot be recomputed without them, and verification must not depend on the signing platform's database still existing. Different subject, different verification procedure.

SigningEnvelope vs File. A File is bytes. A document under signature is a process: who was asked, in what order, what each of them has done, and — critically — the initiator's seal binding this document to exactly this list of signers. Without that seal an envelope is unsigned data that any admitted platform could rewrite.

DocumentKey vs putting the key in the envelope. The key is shared per party, on each party's own vault, so a signer can open the document in an application that is not ours. Its lifetime and its ACL are not the envelope's.

HandwrittenSignature. A person's drawn or typed signature image is their data, reusable across any application that needs it, and does not belong to whichever product they happened to draw it in.

Shape, in one line each

SigningEnvelopeoneOf discriminated on isReference. The canonical form (isReference: false) lives on the initiator's vault and requiresinitiatorSignature, initiatorSignedPayload, sealSchemaVersion and participants; the reference form lives on each signer's vault, carries canonicalOwnerEName + canonicalEnvelopeId, and is forbidden from carrying any of the canonical-only fields. The discriminator is enforced both ways so a reference cannot masquerade as an original.

EIDSignature — one participant's signature: signedPayload (the exact string handed to the wallet), signature, fieldsHash, fieldValues inline, docPlaintextSha256.

EnvelopeAuditEvent — one recorded step. isAttested says whether the actor signed it; dependencies makes signedPayload and signature live and die together, because half a proof is not a proof.

DocumentKey — AES-256-GCM key material, oneOf on isReference like the envelope.

HandwrittenSignature — the image (imageUri, imageSha256), how it was made (method: drawn / typed / uploaded), and whether it is the owner's default.

Cross-vault model

(eName, envelopeId) is the addressable unit, so every reference carries canonicalOwnerEName alongside canonicalEnvelopeId — an envelope id without a tenant addresses nothing. The canonical record is the single source of truth; signers hold references, never copies, because N copies of a document under signature is N versions of what was agreed.

What is NOT here, deliberately

  • The completed PDF is not referenced by a w3ds://file URI. It would land on the same public CDN as the source blob, carrying the decrypted document plus the identities of everyone who signed it. Only its hash is recorded, as an integrity checksum rather than as evidence.
  • No additionalProperties: false anywhere. eVault does not validate — measured: its own uploadFile writes envelopes that violate the registered File schema — so the restriction buys no safety and forecloses extension permanently.
  • identityAssurance is not a claim by the signer. It records what the signing platform knew about that person's identity at the moment they signed, read from their own vault. It sits beside the signature and is not covered by it; the schema description says so explicitly, so no reader can mistake it for something the signer asserted.

Checks

Schemas are draft-07 and validated by an ajv conformance suite in the docusigner repository, which asserts both directions of every discriminator and every required-field dependency. (That suite is how dependentRequired — a draft 2019-09 keyword, silently ignored under draft-07 — was caught and replaced with dependencies.)

None of these five schemaIds currently resolves on the ontology service, so nothing here collides.

…nvelopeAuditEvent, HandwrittenSignature, DocumentKey)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS
EgorPPS requested a review from coodos as a code ownerAugust 20, 2026 07:55
@coderabbitai

coderabbitaiBot commented Aug 20, 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: Pro Plus

Run ID: 3fb32423-3894-4bed-b1fe-55b56ac93eab


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.

…ound nothing'
This record is written once beside a signature and read for years, so a
momentary storage failure recorded as 'unknown' becomes a permanent false
statement about somebody whose identity is in fact established. The two are now
distinct levels, and the schema description says explicitly that a reader must
not collapse them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@EgorPPS

Copy link
Copy Markdown
ContributorAuthor

Pushed a correction to identityAssurance.level (on both eidSignature and signingEnvelope).

The enum was verified | attested | unknown. It is now verified | attested | unknown | unavailable, splitting two things that were one value:

  • unknown — we looked, and nothing at all is known about who holds this eName. An observation about the person.
  • unavailable — we could not look: their storage did not answer. An admission about us.

Worth a schema change rather than a comment because of where this value lives. It is written once, beside a signature, and read for years — there is no later pass that corrects it, the way a cache is corrected by the next refresh. A rate limit at the wrong second would therefore freeze "nothing is known about who holds this eName" into a contract about somebody whose passport had in fact been checked, and neither party would ever have a way to discover that the platform had simply failed to ask.

The description now states that the two must not be collapsed by a reader, since a reader who treats them as one reintroduces exactly the fault.

Credit where due: this came out of comparing notes with the Nootropic session, which was tracking the same class of fault — a transport failure being reported as a substantive answer — across several platforms.

Sign up for freeto 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.

2 participants

@EgorPPS@claude