diff --git a/services/ontology/schemas/documentKey.json b/services/ontology/schemas/documentKey.json new file mode 100644 index 000000000..76a153c71 --- /dev/null +++ b/services/ontology/schemas/documentKey.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "83e80d2b-eb06-46f9-9ef8-a2d0ea262801", + "title": "DocumentKey", + "description": "The key that opens an encrypted document, held in a vault rather than in any application's database.\n\nThis exists for INTEROPERABILITY, not secrecy. A signing document belongs to the people signing it, not to the service that happened to send it — so if the key lived in one platform's database, that platform would be the only software able to open the document, and a signer using a different application simply could not read what they were asked to sign. Putting the key in the participants' own storage is what keeps the document theirs.\n\nBe exact about what this does and does not protect. Encryption keeps the bytes from anyone who merely knows the blob URL — which matters, because blob storage serves those bytes to unauthenticated requests. It does NOT keep them from other platforms: any admitted platform can read this envelope, as it can read any other. Nothing available today changes that; the eID wallet can sign and nothing else, so wrapping a key to a person's own key is not currently possible.\n\nAlso: access here cannot be withdrawn. A key that has been read has been read, and a copy in someone else's vault cannot be deleted. Anything an interface calls 'revoke' is a change of status, never a removal of access.", + "type": "object", + "properties": { + "isReference": { "type": "boolean", "description": "false on the canonical record held by the initiator, true on each participant's reference to it." }, + "keyId": { "type": "string", "minLength": 1 }, + "envelopeId": { "type": "string", "minLength": 1, "description": "The signing envelope this key opens." }, + "canonicalOwnerEName": { "type": "string", "minLength": 1 }, + "canonicalKeyId": { "type": "string", "minLength": 1, "description": "Meta envelope id of the canonical key record. References only." }, + "algorithm": { "type": "string", "enum": ["aes-256-gcm"] }, + "key": { "type": "string", "description": "The symmetric key, base64. Present on the canonical record and on references — a reference that does not carry the key would not let its holder open anything, which is the entire purpose." }, + "iv": { "type": "string", "description": "Initialisation vector for the document ciphertext, base64. Random per encryption and never reused: two ciphertexts under one key and IV break GCM completely." }, + "authTag": { "type": "string", "description": "GCM authentication tag, base64." }, + "plaintextSha256": { "type": "string", "pattern": "^[a-f0-9]{64}$", "description": "SHA-256 of the decrypted document, so a holder can confirm they decrypted the thing that was signed. Deliberately repeated from the signing envelope: a key record that cannot be checked against the document is a key to an unknown lock." }, + "sharedBy": { "type": "string", "description": "References only." }, + "sharedAt": { "type": "string", "format": "date-time", "description": "References only." }, + "createdAt": { "type": "string", "format": "date-time" } + }, + "required": ["isReference", "keyId", "envelopeId", "canonicalOwnerEName", "algorithm", "key", "iv", "authTag", "createdAt"], + "oneOf": [ + { + "title": "CanonicalDocumentKey", + "properties": { "isReference": { "const": false } }, + "required": ["isReference", "keyId", "envelopeId", "canonicalOwnerEName", "algorithm", "key", "iv", "authTag", "plaintextSha256", "createdAt"], + "not": { "anyOf": [{ "required": ["canonicalKeyId"] }, { "required": ["sharedBy"] }, { "required": ["sharedAt"] }] } + }, + { + "title": "DocumentKeyReference", + "properties": { "isReference": { "const": true } }, + "required": ["isReference", "keyId", "envelopeId", "canonicalOwnerEName", "canonicalKeyId", "algorithm", "key", "iv", "authTag", "sharedBy", "sharedAt", "createdAt"] + } + ] +} diff --git a/services/ontology/schemas/eidSignature.json b/services/ontology/schemas/eidSignature.json new file mode 100644 index 000000000..86fec77b0 --- /dev/null +++ b/services/ontology/schemas/eidSignature.json @@ -0,0 +1,175 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "ede4c610-9e22-4074-9598-82c915058f4f", + "title": "EIDSignature", + "description": "One participant's eID signature over a signing envelope, always written to the signer's own vault so they can produce it even if the initiator disappears. Carries the signer's own field values inline, because fieldsHash cannot be recomputed without them and verification must not depend on the platform's database. Distinct from the registered Signature ontology (b2c3d4e5-f6a7-8901-bcde-f12345678901), which sets additionalProperties:false and so cannot carry envelopeId, fieldsHash, role or order.", + "type": "object", + "properties": { + "signatureId": { + "type": "string", + "minLength": 1 + }, + "envelopeId": { + "type": "string", + "minLength": 1 + }, + "canonicalOwnerEName": { + "type": "string", + "minLength": 1, + "description": "eName of the envelope initiator. Required: this ontology exists so a signer can produce their signature when the initiator is gone, and without this field an envelope found on a vault cannot be tied back to the canonical record without our database — which is exactly the situation the field is for." + }, + "signerEName": { + "type": "string", + "minLength": 1, + "description": "eName of the signer. The registered Signature ontology calls this field publicKey and stores an eName in it in live data; this ontology names it honestly." + }, + "docPlaintextSha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$", + "description": "SHA-256 of the original unencrypted PDF, as covered by this signature." + }, + "fieldValues": { + "type": "array", + "description": "This signer's own field values, exactly as canonicalised into fieldsHash. Present so a third party can recompute fieldsHash a year from now without access to our database. Layout (page, coordinates, widget size) is deliberately absent: it is a product concern and proves nothing.", + "items": { + "type": "object", + "properties": { + "fieldId": { + "type": "string", + "minLength": 1 + }, + "type": { + "type": "string", + "enum": [ + "signature", + "initials", + "date", + "text", + "checkbox", + "dropdown" + ] + }, + "label": { + "type": "string" + }, + "value": { + "type": [ + "string", + "boolean", + "null" + ], + "description": "For signature and initials this is the SHA-256 of the drawn mark, not the mark itself, so the visual does not leak through an unencrypted envelope." + } + }, + "required": [ + "fieldId", + "type", + "value" + ] + } + }, + "fieldsHash": { + "type": "string", + "pattern": "^[a-f0-9]{64}$", + "description": "SHA-256 of the canonical JSON of fieldValues." + }, + "fieldSchemaVersion": { + "type": "integer", + "minimum": 1, + "description": "Canonicalisation version, so the meaning of fieldsHash stays provable over time." + }, + "signedPayload": { + "type": "string", + "minLength": 1, + "description": "The exact string handed to the wallet and covered by the signature, recorded verbatim so verification never has to reconstruct how it was composed." + }, + "signature": { + "type": "string", + "minLength": 1, + "description": "The signature returned by the eID wallet." + }, + "role": { + "type": "string", + "enum": [ + "signer", + "approver" + ] + }, + "identityAssurance": { + "type": "object", + "description": "What the signing platform knew about this person's identity at the moment of the act, read from their own vault. RECORDED, not recomputed: a passport check added a year later does not make an earlier signature better evidence, and an attestation withdrawn since does not make it worse, so a reader of the finished document needs what was true then. IMPORTANT: this is an observation made BY the platform, sitting beside the signature. It is not covered by the signature and must never be presented as a claim the person made. Anyone who does not wish to take it on trust can recompute today's answer from the same vault.", + "properties": { + "level": { + "type": "string", + "enum": [ + "verified", + "attested", + "unknown", + "unavailable" + ], + "description": "verified — a licensed identity vendor checked an identity document, and the attestation is signed by an authority whose key is published. attested — no document was checked, but other people have mutually attested to this identity. unknown — we looked and nothing at all is known about who holds this eName. unavailable — we could not look: their storage did not answer at the time. The last two are deliberately distinct and MUST NOT be collapsed by a reader: 'we found nothing' is an observation about the person, 'we could not ask' is an admission about us. This record is written once beside a signature and read for years, so a momentary failure recorded as 'unknown' would be a permanent false statement about somebody whose identity is in fact established." + }, + "verifiedName": { + "type": [ + "string", + "null" + ], + "description": "The name the vendor checked. Never a name the person stated about themselves." + }, + "verifiedBy": { + "type": [ + "string", + "null" + ], + "description": "Which identity vendor performed the check." + }, + "attestations": { + "type": "integer", + "minimum": 0, + "description": "How many other people had mutually attested to this identity at the time." + }, + "authenticatedBy": { + "type": "string", + "description": "How the person proved, in this act, that they hold the eName. Currently always 'eid-key-signature' — a signature from the key their eID wallet holds. Named explicitly so a reader is not left to assume something weaker or stronger." + }, + "capturedAt": { + "type": "string", + "format": "date-time", + "description": "When the observation was made — the moment of signing or sealing." + } + }, + "required": [ + "level", + "authenticatedBy", + "capturedAt" + ] + }, + "order": { + "type": "integer", + "minimum": 1, + "description": "Product-level position in the signing order. Signatures remain cryptographically independent of one another." + }, + "signedAt": { + "type": "string", + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "signatureId", + "envelopeId", + "canonicalOwnerEName", + "signerEName", + "docPlaintextSha256", + "fieldValues", + "fieldsHash", + "fieldSchemaVersion", + "signedPayload", + "signature", + "signedAt", + "createdAt" + ] +} diff --git a/services/ontology/schemas/envelopeAuditEvent.json b/services/ontology/schemas/envelopeAuditEvent.json new file mode 100644 index 000000000..b2351b824 --- /dev/null +++ b/services/ontology/schemas/envelopeAuditEvent.json @@ -0,0 +1,91 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "8c2c245e-8714-41da-8407-14ab5ce8ea38", + "title": "EnvelopeAuditEvent", + "description": "One recorded step in the life of a signing envelope, written to the vault of whoever performed it.\n\nIMPORTANT — what this is and is not. Any platform holding a developer key can write an envelope to any vault by naming its owner in X-ENAME; there is no place in the request for the owner's consent. An unsigned event is therefore FORGEABLE: a 'signed' or 'opened' event can be fabricated on the vault of someone who never opened the application. Unsigned events are an operational journal, not evidence.\n\nFor the actions a person may genuinely need to prove — above all 'declined', which is a statement someone may have to defend — the actor signs the event with their eID key and fills signedPayload and signature. Only those events carry evidentiary weight, on exactly the same footing as EIDSignature: the private key lives in the wallet and the platform key cannot forge it. This is deliberately carried no IP address or user agent: those are personal data and would be written into someone else's vault.", + "type": "object", + "properties": { + "eventId": { + "type": "string", + "minLength": 1 + }, + "envelopeId": { + "type": "string", + "minLength": 1 + }, + "canonicalOwnerEName": { + "type": "string", + "minLength": 1, + "description": "eName of the envelope initiator. Required for the same reason as on EIDSignature: an event found on a vault must be tied back to the canonical envelope without our database." + }, + "actorEName": { + "type": "string", + "minLength": 1, + "description": "eName of whoever performed the action. Equals the vault this event is written to." + }, + "action": { + "type": "string", + "enum": [ + "created", + "sent", + "access_granted", + "opened", + "fields_filled", + "signed", + "declined", + "completed", + "revoked", + "expired", + "downloaded" + ] + }, + "subjectEName": { + "type": [ + "string", + "null" + ], + "description": "eName the action was directed at, where that differs from the actor. For example the invitee on access_granted." + }, + "detail": { + "type": "string", + "description": "Short human-readable note. Must not contain document contents." + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "signedPayload": { + "type": "string", + "description": "The exact string signed by the actor, composed as `${action}|${envelopeId}|${actorEName}|${occurredAt}`. Present only on signed events. Absent means this event is unproven and must not be presented as evidence." + }, + "signature": { + "type": "string", + "description": "The actor's eID signature over signedPayload. Its presence is what turns this record from a journal entry into something provable." + }, + "isAttested": { + "type": "boolean", + "description": "True when signedPayload and signature are present and verified. Explicit rather than inferred, so a reader cannot mistake a missing signature for an unchecked one." + } + }, + "required": [ + "eventId", + "envelopeId", + "canonicalOwnerEName", + "actorEName", + "action", + "occurredAt", + "createdAt" + ], + "dependencies": { + "signature": [ + "signedPayload" + ], + "signedPayload": [ + "signature" + ] + } +} diff --git a/services/ontology/schemas/handwrittenSignature.json b/services/ontology/schemas/handwrittenSignature.json new file mode 100644 index 000000000..7b1dbaaca --- /dev/null +++ b/services/ontology/schemas/handwrittenSignature.json @@ -0,0 +1,27 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "2a062bd7-c7a3-451e-b4ff-d1ada729bf46", + "title": "HandwrittenSignature", + "description": "A person's handwritten signature or initials, kept as a property of the person rather than of any one document — like their name or avatar. It lives on their own vault so that ANY signing application can offer it back to them instead of making them draw it again in every service.\n\nIMPORTANT — this is a convenience, not a credential. Possessing this image lets nobody sign anything: what binds a document is the eID signature, and the signature envelope records the SHA-256 of the mark rather than the mark itself. Treat a stolen image as an embarrassment, not a compromise, and do not build any check that trusts it.\n\nIt is still personal, so the image is stored encrypted and referenced by w3ds://file rather than inlined. Be honest about what that buys: it keeps the bytes away from anyone who merely knows the blob URL, which is a real exposure, but not away from platforms — the key is readable by any of them, as everything in a vault is.", + "type": "object", + "properties": { + "signatureId": { "type": "string", "minLength": 1 }, + "ownerEName": { "type": "string", "minLength": 1, "description": "The person this signature belongs to. Always the vault it lives on." }, + "kind": { "type": "string", "enum": ["signature", "initials"], "description": "A full signature or a short initials mark. People generally want both." }, + "label": { "type": "string", "description": "Optional name for this mark, so somebody can keep more than one (a formal signature and a quick one, say)." }, + "method": { + "type": "string", + "enum": ["drawn", "typed", "uploaded"], + "description": "How the mark was produced. Recorded because it is honest to show, not because it changes what the mark is worth." + }, + "imageUri": { "type": "string", "description": "w3ds://file URI of the image. Referenced rather than inlined: an inline image bloats every read of this envelope, and the File record supplies size and content type for free." }, + "contentEncoding": { "type": "string", "enum": ["none", "aes-256-gcm"], "description": "How the bytes behind imageUri are protected." }, + "imageSha256": { "type": "string", "pattern": "^[a-f0-9]{64}$", "description": "SHA-256 of the decrypted image. This is the value a signature envelope records when this mark is used, so a verifier can confirm the mark shown on a document is the one that was signed for." }, + "widthPx": { "type": "integer", "minimum": 1 }, + "heightPx": { "type": "integer", "minimum": 1 }, + "isDefault": { "type": "boolean", "description": "Offer this one first." }, + "createdAt": { "type": "string", "format": "date-time" }, + "updatedAt": { "type": "string", "format": "date-time" } + }, + "required": ["signatureId", "ownerEName", "kind", "imageUri", "imageSha256", "createdAt"] +} diff --git a/services/ontology/schemas/signingEnvelope.json b/services/ontology/schemas/signingEnvelope.json new file mode 100644 index 000000000..ae65dae4e --- /dev/null +++ b/services/ontology/schemas/signingEnvelope.json @@ -0,0 +1,352 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "schemaId": "256510c7-692c-4bf5-8136-820cd178a266", + "title": "SigningEnvelope", + "description": "A document sent for signature by one or more parties. The canonical envelope lives on the initiator's vault; every signer holds a reference on their own vault. Field layout and process state live in the platform database, not here. The completed PDF is deliberately 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 evidence. The canonical envelope carries the initiator's seal (initiatorSignature): without it the envelope is unsigned data that any admitted platform could rewrite.", + "type": "object", + "properties": { + "isReference": { + "type": "boolean", + "description": "false on the initiator's canonical envelope, true on each signer's reference." + }, + "envelopeId": { + "type": "string", + "minLength": 1, + "description": "Stable id shared by the canonical envelope and all of its references." + }, + "canonicalOwnerEName": { + "type": "string", + "minLength": 1, + "description": "eName of the initiator, whose vault holds the canonical envelope." + }, + "canonicalEnvelopeId": { + "type": "string", + "minLength": 1, + "description": "Meta envelope id of the canonical record. References only." + }, + "title": { + "type": "string", + "description": "Human-readable title. Note this is visible to any platform that can read the envelope; it is not protected by the document encryption." + }, + "message": { + "type": "string", + "description": "Optional note from the initiator to the signers." + }, + "fileUri": { + "type": "string", + "description": "w3ds://file URI of the stored ciphertext. The File envelope behind it records filename, size and md5Hash of the CIPHERTEXT; see contentEncoding and hashSubject." + }, + "contentEncoding": { + "type": "string", + "enum": [ + "none", + "aes-256-gcm" + ], + "description": "How the bytes behind fileUri are protected. Present so an outside reader cannot mistake File.md5Hash for a hash of the document." + }, + "hashSubject": { + "type": "string", + "enum": [ + "plaintext", + "ciphertext" + ], + "description": "What plaintextSha256 refers to. Always plaintext; stated explicitly because File.md5Hash refers to the ciphertext and the two are easily confused." + }, + "plaintextSha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$", + "description": "SHA-256 of the ORIGINAL UNENCRYPTED PDF. This is what signatures cover. Note: for a low-entropy document this value is a confirmation oracle, letting a reader test a guessed plaintext. It cannot be removed without breaking independent verification; the tradeoff is accepted deliberately." + }, + "ciphertextSha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$", + "description": "SHA-256 of the stored ciphertext, for integrity of the blob itself." + }, + "keyCustody": { + "type": "string", + "enum": [ + "platform", + "participant-wrapped" + ], + "description": "platform = the operator can decrypt; participant-wrapped = end-to-end. Currently always platform: the eID wallet exposes only sign() and getPublicKey(), and its ECDSA P-256 key cannot perform key agreement." + }, + "fieldSchemaVersion": { + "type": "integer", + "minimum": 1, + "description": "Version of the field-value canonicalisation used for fieldsHash, included in every signed payload." + }, + "signingOrder": { + "type": "string", + "enum": [ + "parallel", + "sequential" + ], + "description": "Product-level ordering only; signatures are cryptographically independent." + }, + "status": { + "type": "string", + "enum": [ + "draft", + "sent", + "partially_signed", + "completed", + "declined", + "revoked", + "expired" + ] + }, + "participants": { + "type": "array", + "description": "Signers and their roles. Visible to any platform that can read this envelope: who is signing what, and when, cannot be hidden in this model. Canonical envelope only. Pinned by initiatorSignature: any change to this list invalidates the seal.", + "items": { + "type": "object", + "properties": { + "participantId": { + "type": "string", + "minLength": 1 + }, + "eName": { + "type": "string", + "minLength": 1 + }, + "role": { + "type": "string", + "enum": [ + "signer", + "approver", + "viewer" + ] + }, + "order": { + "type": "integer", + "minimum": 1 + }, + "status": { + "type": "string", + "enum": [ + "pending", + "opened", + "signed", + "declined" + ] + } + }, + "required": [ + "participantId", + "eName", + "role" + ] + } + }, + "role": { + "type": "string", + "enum": [ + "signer", + "approver", + "viewer" + ], + "description": "This holder's role. References only." + }, + "order": { + "type": "integer", + "minimum": 1, + "description": "This holder's position in the signing order. References only." + }, + "sharedBy": { + "type": "string", + "description": "eName of whoever created this reference. References only." + }, + "sharedAt": { + "type": "string", + "format": "date-time", + "description": "References only." + }, + "finalPlaintextSha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$", + "description": "SHA-256 of the completed, flattened PDF as the user downloads it. This is an INTEGRITY CHECKSUM, not evidence: nothing signs it. The authority of the completed document comes from the participants' signatures over the original document and their field values, not from any signature over the rendering. A platform vault cannot supply one — it is provisioned with a placeholder key and advertises no key-binding certificate, so a naive verifier following the standard chain would return valid=true for anything at all. The bytes are served only through the platform's authorised endpoint and never uploaded to a vault." + }, + "expiresAt": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "initiatorSignedPayload": { + "type": "string", + "description": "The exact string the initiator sealed, composed as `docusigner.envelope-seal.v1||||sha256(canonical participant eNames)`, then hashed and prefixed with `seal_`. Recorded verbatim; a verifier must recompute it rather than trust it." + }, + "initiatorSignature": { + "type": "string", + "description": "The initiator's eID signature over initiatorSignedPayload. This is what makes the envelope trustworthy at all. Any admitted platform can rewrite an envelope on any vault via updateMetaEnvelope, replacing fileUri and plaintextSha256 TOGETHER so that the document still matches its recorded hash; checking bytes against the envelope cannot detect a substituted pair. Only this seal can, because forging it needs the initiator's key, which no platform holds. It also pins the participant list against silent additions or eName swaps." + }, + "initiatorAssurance": { + "type": "object", + "description": "What the platform knew about the INITIATOR's identity when they sealed and sent this envelope. What the signing platform knew about this person's identity at the moment of the act, read from their own vault. RECORDED, not recomputed: a passport check added a year later does not make an earlier signature better evidence, and an attestation withdrawn since does not make it worse, so a reader of the finished document needs what was true then. IMPORTANT: this is an observation made BY the platform, not part of the seal, and must never be presented as a claim the initiator made.", + "properties": { + "level": { + "type": "string", + "enum": [ + "verified", + "attested", + "unknown", + "unavailable" + ], + "description": "verified — a licensed identity vendor checked an identity document, and the attestation is signed by an authority whose key is published. attested — no document was checked, but other people have mutually attested to this identity. unknown — we looked and nothing at all is known about who holds this eName. unavailable — we could not look: their storage did not answer at the time. The last two are deliberately distinct and MUST NOT be collapsed by a reader: 'we found nothing' is an observation about the person, 'we could not ask' is an admission about us. This record is written once beside a signature and read for years, so a momentary failure recorded as 'unknown' would be a permanent false statement about somebody whose identity is in fact established." + }, + "verifiedName": { + "type": [ + "string", + "null" + ], + "description": "The name the vendor checked. Never a name the person stated about themselves." + }, + "verifiedBy": { + "type": [ + "string", + "null" + ], + "description": "Which identity vendor performed the check." + }, + "attestations": { + "type": "integer", + "minimum": 0, + "description": "How many other people had mutually attested to this identity at the time." + }, + "authenticatedBy": { + "type": "string", + "description": "How the person proved, in this act, that they hold the eName. Currently always 'eid-key-signature' — a signature from the key their eID wallet holds. Named explicitly so a reader is not left to assume something weaker or stronger." + }, + "capturedAt": { + "type": "string", + "format": "date-time", + "description": "When the observation was made — the moment of signing or sealing." + } + }, + "required": [ + "level", + "authenticatedBy", + "capturedAt" + ] + }, + "sealSchemaVersion": { + "type": "integer", + "minimum": 1, + "description": "Version of the seal canonicalisation (participant-list normalisation and composition order). Deliberately separate from fieldSchemaVersion: the two are independent formats and will need to change at different times." + } + }, + "required": [ + "isReference", + "envelopeId", + "canonicalOwnerEName", + "createdAt" + ], + "oneOf": [ + { + "title": "CanonicalSigningEnvelope", + "properties": { + "isReference": { + "const": false + } + }, + "required": [ + "isReference", + "envelopeId", + "canonicalOwnerEName", + "title", + "fileUri", + "contentEncoding", + "hashSubject", + "plaintextSha256", + "keyCustody", + "fieldSchemaVersion", + "status", + "participants", + "createdAt", + "initiatorSignedPayload", + "initiatorSignature", + "sealSchemaVersion" + ], + "not": { + "anyOf": [ + { + "required": [ + "canonicalEnvelopeId" + ] + }, + { + "required": [ + "role" + ] + }, + { + "required": [ + "order" + ] + }, + { + "required": [ + "sharedBy" + ] + }, + { + "required": [ + "sharedAt" + ] + } + ] + } + }, + { + "title": "SigningEnvelopeReference", + "properties": { + "isReference": { + "const": true + } + }, + "required": [ + "isReference", + "envelopeId", + "canonicalOwnerEName", + "canonicalEnvelopeId", + "role", + "sharedBy", + "sharedAt", + "createdAt" + ], + "not": { + "anyOf": [ + { + "required": [ + "participants" + ] + }, + { + "required": [ + "initiatorSignature" + ] + }, + { + "required": [ + "initiatorSignedPayload" + ] + }, + { + "required": [ + "sealSchemaVersion" + ] + } + ] + } + } + ] +}