Contest Ballot¶
Description¶
An individual Ballot cast in a Contest by a registered user.
Each ballot contains choices for all possible proposals eligible for the contest.
Multiple contest ballots can be cast by the same registered user in a contest, but only the latest (by its document_version) will be counted.
The reason the ballot is cast in a contest is because there may be multiple contests in a campaign, and they may be attached to either the brand, campaign or category level. Each level, (for example category) can in-theory have multiple contests.
Only eligible users can cast ballots in the respective contest.
Validation¶
- The
parametersmetadata MUST point to the Contest the ballot is being cast in. - The 'ref' metadata fields within the ballot payload (not the headers) must point to ALL the proposals eligible to be chosen in the contest.
Business Logic¶
Front End¶
- Always cast a ballot for all proposals in the contest.
- Any proposal not explicitely selected by a user must have the default selection applied.
Typically, this would be
abstain. - The voter signs this document to confirm their ballot.
- Ballots can not be cast outside the time allowed for the casting of ballots.
- The
document_idanddocument_vermust be within the time of allowed casting of ballots. Anydocument_idordocument_veroutside this time are invalid and will not be counted.
Back End¶
- Verifies that the Contest is valid, and that the ballot is cast in the appropriate
time frame, and has a valid
document_idanddocument_verin that range. - Verify the payload lists all the eligible proposals which can be chosen in the contest.
- Verify the proofs in the payload are correct.
COSE Header Parameters¶
- content type =
application/cbor - content-encoding =
[br]
Metadata¶
type¶
| Parameter | Value |
|---|---|
| Required | yes |
| Format | Document Type |
| Type | de1284b8-8533-4f7a-81cc-ff4bde5ef8d0 |
The document TYPE.
type Validation¶
MUST be a known document type.
id¶
| Parameter | Value |
|---|---|
| Required | yes |
| Format | Document Id |
Document ID, created the first time the document is created. This must be a properly created UUIDv7 which contains the timestamp of when the document was created.
id Validation¶
IF ver does not == id then a document with
id and ver being equal MUST exist.
ver¶
| Parameter | Value |
|---|---|
| Required | yes |
| Format | Document Ver |
The unique version of the document.
The first version of the document must set ver == id
ver represents new versions of the same document as it changes over time.
ver Validation¶
The document version must always be >= the document ID.
revocations¶
| Parameter | Value |
|---|---|
| Required | optional |
| Format | Version Revocations |
A document may include a list of any prior versions which are considered to be revoked.
Only the revocation list in the latest version of the document applies.
Revoked documents are flagged as no longer valid, and should not be displayed.
As a special case, if the revocations are set to true then all versions of the document
are revoked, including the latest document.
In this case, when the latest document is revoked, the payload may be nil.
Any older document that has revocations set to true is always to be filtered
and its payload is to be assumed to be invalid.
This allows for an entire document and any/all published versions to be revoked.
A new version of the document that is published after this, may reinstate prior
document versions, by not listing them as revoked.
However, any document where revocations was set true can never be reinstated.
revocations Validation¶
If the field is true the payload may be absent or invalid.
Such documents may never be submitted.
parameters¶
| Parameter | Value |
|---|---|
| Required | yes |
| Format | Document Reference |
| Valid References | Contest Parameters |
A reference to the Parameters Document this document lies under.
parameters Validation¶
In addition to the validation performed for Document Reference type fields:
- Any linked referenced document that includes a
parametersmetadata must match theparametersof the referencing document, or a parent of thoseparameters.
For example, a linked reference to Contest Parameters is transitively a reference to
the Parameters document it references, and each parameters document they reference
until the Brand parameters document is reached.
The use case here is for Templates. The profile template, or proposal templates could be defined at any of these levels, and as long as they all refer to the same chain of parameters in the hierarchy they are all valid.
Payload¶
The Payload is a CBOR document that must conform to the contest-ballot-payload CDDL.
Contents
-
document_ref => choices- The payload is a map keyed by a proposal
document_ref. - Each key identifies one specific proposal via
[document_id, document_ver, document_locator]. - The value for each key is that voter’s
choicesfor that proposal. - There is exactly one set of
choicesper referenced proposal (no duplicates).
- The payload is a map keyed by a proposal
-
choices- Discriminated union of unencrypted or encrypted choices.
-
row-proof(optional, inside encrypted choices)- Proves, without revealing contents, that the encrypted row encodes a unit vector with exactly one selection.
-
column-proof(optional, top-level)- Placeholder for future column-level proofs across proposals.
- Not defined at present; omit in implementations.
-
matrix-proof(optional, top-level)- Placeholder for future matrix-wide proofs across all proposals and positions.
- Not defined at present; omit in implementations.
-
voter-choice(optional, top-level)- This is ONLY Not included when the vote is unencrypted.
- Allows a voter to read back their ballot selections without decrypting the entire ballot.
Notes
document_locatoruses a CBOR Tag 42cidto locate the referenced proposal in content-addressed storage. Implementations should constrain the CID to SHA2-256 multihash; the multicodec SHOULD becbor (0x51)to reflect an unwrapped COSE_Sign CBOR block.- The application defines the permissible range and semantics of
clear-choiceintegers. - All CBOR must use core-deterministic encoding so that content addressing remains stable.
Schema¶
Payload CDDL Schema
; Catalyst Vote Payload data object.
;
; A vote payload that can hold both encrypted or unencrypted votes.
; Catalyst Vote Payload data object.
contest-ballot-payload = {
+ document_ref => choices
? "column-proof" : column-proof
? "matrix-proof" : matrix-proof
? "voter-choice" : voter-choice
}
; Reference to a single Signed Document
document_ref = [
document_id
document_ver
document_locator
]
; Document ID
document_id = uuid_v7
; UUIDv7
uuid_v7 = #6.37(bytes .size 16)
; Document Version
document_ver = uuid_v7
; Where a document can be located, must be a unique identifier.
document_locator = {
"cid" : cid
}
; IPLD content identifier.
; Currently limited to SHA2-256 based CIDs.
cid = #6.42(bytes .abnfb ("cid" .det cbor-cid ))
; CIDv1 ABNF Constrained for SHA2-256
cbor-cid = '
cid = cidv1 codec-cbor sha2-256 digest-32 digest
cidv1 = %x00 %x01
codec-cbor = %x51
sha2-256 = %x12
digest-32 = %x20
digest = 32(%x00-FF)
'
; Voters Choices.
choices = [ 0, clear-choices ] /
[ 1, elgamal-ristretto255-encrypted-choices ]
; Universal Unencrypted Set of Choices
clear-choices = ( +clear-choice )
; Universal Unencrypted Choice
clear-choice = int
; elgamal/ristretto255 Encrypted Choices
elgamal-ristretto255-encrypted-choices = [
[+ elgamal-ristretto255-encrypted-choice]
? row-proof
]
; The elgamal encrypted ciphertext `(c1, c2)`.
elgamal-ristretto255-encrypted-choice = [
c1: elgamal-ristretto255-group-element
c2: elgamal-ristretto255-group-element
]
; An individual Elgamal group element that composes the elgamal cipher text.
elgamal-ristretto255-group-element = bytes .size 32
; Universal Encrypted Row Proof
row-proof = [0, zkproof-elgamal-ristretto255-unit-vector-with-single-selection ]
zkproof-elgamal-ristretto255-unit-vector-with-single-selection = [ +zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item, zkproof-ed25519-scalar ]
; Proof that the row is a unit vector with a single selection.
zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item = ( zkproof-elgamal-announcement, ~elgamal-ristretto255-encrypted-choice, zkproof-ed25519-r-response )
; ZK Proof Announcement values for Elgamal.
zkproof-elgamal-announcement = ( zkproof-elgamal-group-element, zkproof-elgamal-group-element, zkproof-elgamal-group-element )
; An individual Elgamal group element used in ZK Proofs.
zkproof-elgamal-group-element = bytes .size 32
; ZK Proof Response values for Ed25519.
zkproof-ed25519-r-response = ( zkproof-ed25519-scalar, zkproof-ed25519-scalar, zkproof-ed25519-scalar )
; An individual Ed25519 scalar used in ZK Proofs.
zkproof-ed25519-scalar = bytes .size 32
; Universal Encrypted Column Proof (Placeholder)
column-proof = [ uint, [ +undefined ] ]
; Universal Encrypted Matrix Proof (Placeholder)
matrix-proof = [ uint, undefined ]
; Encrypted Voter Choice Payload
voter-choice = [ 0, aes-ctr-encrypted-choices ]
; Encrypted Voter Choices
aes-ctr-encrypted-choices = +aes-ctr-encrypted-block
; AES-CTR Encrypted Data Block
aes-ctr-encrypted-block = bytes .size 16
Sub-schemas¶
Required Definition: document_ref
; document_ref
; Reference to a single Signed Document
document_ref = [
document_id
document_ver
document_locator
]
; Document ID
document_id = uuid_v7
; UUIDv7
uuid_v7 = #6.37(bytes .size 16)
; Document Version
document_ver = uuid_v7
; Where a document can be located, must be a unique identifier.
document_locator = {
"cid" : cid
}
; IPLD content identifier.
; Currently limited to SHA2-256 based CIDs.
cid = #6.42(bytes .abnfb ("cid" .det cbor-cid ))
; CIDv1 ABNF Constrained for SHA2-256
cbor-cid = '
cid = cidv1 codec-cbor sha2-256 digest-32 digest
cidv1 = %x00 %x01
codec-cbor = %x51
sha2-256 = %x12
digest-32 = %x20
digest = 32(%x00-FF)
'
Required Definition: document_id
Required Definition: uuid_v7
Required Definition: document_ver
Required Definition: document_locator
; document_locator
; Where a document can be located, must be a unique identifier.
document_locator = {
"cid" : cid
}
; IPLD content identifier.
; Currently limited to SHA2-256 based CIDs.
cid = #6.42(bytes .abnfb ("cid" .det cbor-cid ))
; CIDv1 ABNF Constrained for SHA2-256
cbor-cid = '
cid = cidv1 codec-cbor sha2-256 digest-32 digest
cidv1 = %x00 %x01
codec-cbor = %x51
sha2-256 = %x12
digest-32 = %x20
digest = 32(%x00-FF)
'
Required Definition: cid
; IPLD content identifier.
; Also known as an IPFS CID.
; Currently limited to SHA2-256 based CIDs.
; See: https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid
; https://github.com/ipld/cid-cbor/
; IPLD content identifier.
; Currently limited to SHA2-256 based CIDs.
cid = #6.42(bytes .abnfb ("cid" .det cbor-cid ))
; CIDv1 ABNF Constrained for SHA2-256
cbor-cid = '
cid = cidv1 codec-cbor sha2-256 digest-32 digest
cidv1 = %x00 %x01
codec-cbor = %x51
sha2-256 = %x12
digest-32 = %x20
digest = 32(%x00-FF)
'
Required Definition: cbor-cid
Required Definition: choices
; Choices are an array of encrypted or unencrypted choices.
; Voters Choices.
choices = [ 0, clear-choices ] /
[ 1, elgamal-ristretto255-encrypted-choices ]
; Universal Unencrypted Set of Choices
clear-choices = ( +clear-choice )
; Universal Unencrypted Choice
clear-choice = int
; elgamal/ristretto255 Encrypted Choices
elgamal-ristretto255-encrypted-choices = [
[+ elgamal-ristretto255-encrypted-choice]
? row-proof
]
; The elgamal encrypted ciphertext `(c1, c2)`.
elgamal-ristretto255-encrypted-choice = [
c1: elgamal-ristretto255-group-element
c2: elgamal-ristretto255-group-element
]
; An individual Elgamal group element that composes the elgamal cipher text.
elgamal-ristretto255-group-element = bytes .size 32
; Universal Encrypted Row Proof
row-proof = [0, zkproof-elgamal-ristretto255-unit-vector-with-single-selection ]
zkproof-elgamal-ristretto255-unit-vector-with-single-selection = [ +zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item, zkproof-ed25519-scalar ]
; Proof that the row is a unit vector with a single selection.
zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item = ( zkproof-elgamal-announcement, ~elgamal-ristretto255-encrypted-choice, zkproof-ed25519-r-response )
; ZK Proof Announcement values for Elgamal.
zkproof-elgamal-announcement = ( zkproof-elgamal-group-element, zkproof-elgamal-group-element, zkproof-elgamal-group-element )
; An individual Elgamal group element used in ZK Proofs.
zkproof-elgamal-group-element = bytes .size 32
; ZK Proof Response values for Ed25519.
zkproof-ed25519-r-response = ( zkproof-ed25519-scalar, zkproof-ed25519-scalar, zkproof-ed25519-scalar )
; An individual Ed25519 scalar used in ZK Proofs.
zkproof-ed25519-scalar = bytes .size 32
Required Definition: clear-choices
Required Definition: clear-choice
Required Definition: elgamal-ristretto255-encrypted-choices
; Encrypted Choices are a Vector (list) of encrypted items.
; The size of the vector will depend on the cryptography used,
; and the number of choices.
;
; Typically, (but optionally) it has a proof attached which proves something
; about the encrypted choices, without disclosing their contents.
;
; For example, a ZKProof that there is only a single `1` in the choices,
; and all the rest are `0`.
;
; The size/contents of the proof depend on what is being proved, and the
; cryptography underlying the proof.
; elgamal/ristretto255 Encrypted Choices
elgamal-ristretto255-encrypted-choices = [
[+ elgamal-ristretto255-encrypted-choice]
? row-proof
]
; The elgamal encrypted ciphertext `(c1, c2)`.
elgamal-ristretto255-encrypted-choice = [
c1: elgamal-ristretto255-group-element
c2: elgamal-ristretto255-group-element
]
; An individual Elgamal group element that composes the elgamal cipher text.
elgamal-ristretto255-group-element = bytes .size 32
; Universal Encrypted Row Proof
row-proof = [0, zkproof-elgamal-ristretto255-unit-vector-with-single-selection ]
zkproof-elgamal-ristretto255-unit-vector-with-single-selection = [ +zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item, zkproof-ed25519-scalar ]
; Proof that the row is a unit vector with a single selection.
zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item = ( zkproof-elgamal-announcement, ~elgamal-ristretto255-encrypted-choice, zkproof-ed25519-r-response )
; ZK Proof Announcement values for Elgamal.
zkproof-elgamal-announcement = ( zkproof-elgamal-group-element, zkproof-elgamal-group-element, zkproof-elgamal-group-element )
; An individual Elgamal group element used in ZK Proofs.
zkproof-elgamal-group-element = bytes .size 32
; ZK Proof Response values for Ed25519.
zkproof-ed25519-r-response = ( zkproof-ed25519-scalar, zkproof-ed25519-scalar, zkproof-ed25519-scalar )
; An individual Ed25519 scalar used in ZK Proofs.
zkproof-ed25519-scalar = bytes .size 32
Required Definition: elgamal-ristretto255-encrypted-choice
; The elgamal encrypted ciphertext `(c1, c2)`.
; The elgamal encrypted ciphertext `(c1, c2)`.
elgamal-ristretto255-encrypted-choice = [
c1: elgamal-ristretto255-group-element
c2: elgamal-ristretto255-group-element
]
; An individual Elgamal group element that composes the elgamal cipher text.
elgamal-ristretto255-group-element = bytes .size 32
Required Definition: elgamal-ristretto255-group-element
Required Definition: row-proof
; A proof that the choices conform to a required set of properties.
; It is defined by the configured cryptography used for encrypted choices.
; This format is universal over all encrypted choice encoding.
; Universal Encrypted Row Proof
row-proof = [0, zkproof-elgamal-ristretto255-unit-vector-with-single-selection ]
zkproof-elgamal-ristretto255-unit-vector-with-single-selection = [ +zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item, zkproof-ed25519-scalar ]
; Proof that the row is a unit vector with a single selection.
zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item = ( zkproof-elgamal-announcement, ~elgamal-ristretto255-encrypted-choice, zkproof-ed25519-r-response )
; ZK Proof Announcement values for Elgamal.
zkproof-elgamal-announcement = ( zkproof-elgamal-group-element, zkproof-elgamal-group-element, zkproof-elgamal-group-element )
; An individual Elgamal group element used in ZK Proofs.
zkproof-elgamal-group-element = bytes .size 32
; The elgamal encrypted ciphertext `(c1, c2)`.
elgamal-ristretto255-encrypted-choice = [
c1: elgamal-ristretto255-group-element
c2: elgamal-ristretto255-group-element
]
; An individual Elgamal group element that composes the elgamal cipher text.
elgamal-ristretto255-group-element = bytes .size 32
; ZK Proof Response values for Ed25519.
zkproof-ed25519-r-response = ( zkproof-ed25519-scalar, zkproof-ed25519-scalar, zkproof-ed25519-scalar )
; An individual Ed25519 scalar used in ZK Proofs.
zkproof-ed25519-scalar = bytes .size 32
Required Definition: zkproof-elgamal-ristretto255-unit-vector-with-single-selection
; Proof that the choices form a unit vector with a single selection.
zkproof-elgamal-ristretto255-unit-vector-with-single-selection = [ +zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item, zkproof-ed25519-scalar ]
; Proof that the row is a unit vector with a single selection.
zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item = ( zkproof-elgamal-announcement, ~elgamal-ristretto255-encrypted-choice, zkproof-ed25519-r-response )
; ZK Proof Announcement values for Elgamal.
zkproof-elgamal-announcement = ( zkproof-elgamal-group-element, zkproof-elgamal-group-element, zkproof-elgamal-group-element )
; An individual Elgamal group element used in ZK Proofs.
zkproof-elgamal-group-element = bytes .size 32
; The elgamal encrypted ciphertext `(c1, c2)`.
elgamal-ristretto255-encrypted-choice = [
c1: elgamal-ristretto255-group-element
c2: elgamal-ristretto255-group-element
]
; An individual Elgamal group element that composes the elgamal cipher text.
elgamal-ristretto255-group-element = bytes .size 32
; ZK Proof Response values for Ed25519.
zkproof-ed25519-r-response = ( zkproof-ed25519-scalar, zkproof-ed25519-scalar, zkproof-ed25519-scalar )
; An individual Ed25519 scalar used in ZK Proofs.
zkproof-ed25519-scalar = bytes .size 32
Required Definition: zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item
; Proof that the row is a unit vector with a single selection.
; Proof that the row is a unit vector with a single selection.
zkproof-elgamal-ristretto255-unit-vector-with-single-selection-item = ( zkproof-elgamal-announcement, ~elgamal-ristretto255-encrypted-choice, zkproof-ed25519-r-response )
; ZK Proof Announcement values for Elgamal.
zkproof-elgamal-announcement = ( zkproof-elgamal-group-element, zkproof-elgamal-group-element, zkproof-elgamal-group-element )
; An individual Elgamal group element used in ZK Proofs.
zkproof-elgamal-group-element = bytes .size 32
; The elgamal encrypted ciphertext `(c1, c2)`.
elgamal-ristretto255-encrypted-choice = [
c1: elgamal-ristretto255-group-element
c2: elgamal-ristretto255-group-element
]
; An individual Elgamal group element that composes the elgamal cipher text.
elgamal-ristretto255-group-element = bytes .size 32
; ZK Proof Response values for Ed25519.
zkproof-ed25519-r-response = ( zkproof-ed25519-scalar, zkproof-ed25519-scalar, zkproof-ed25519-scalar )
; An individual Ed25519 scalar used in ZK Proofs.
zkproof-ed25519-scalar = bytes .size 32
Required Definition: zkproof-elgamal-announcement
; ZK Proof Announcement values for Elgamal.
; ZK Proof Announcement values for Elgamal.
zkproof-elgamal-announcement = ( zkproof-elgamal-group-element, zkproof-elgamal-group-element, zkproof-elgamal-group-element )
; An individual Elgamal group element used in ZK Proofs.
zkproof-elgamal-group-element = bytes .size 32
Required Definition: zkproof-elgamal-group-element
Required Definition: zkproof-ed25519-r-response
Required Definition: zkproof-ed25519-scalar
Required Definition: column-proof
; Proof that values in a column have a required arrangement.
; This is similar to the `row-proof` but for all values in a
; single column.
; It is an array that matches the length of `choices`.
; If it is a different length, then it is invalid.
;
; Currently there are no `column-proof` defined, this value is
; a placeholder for documentation purposes only.
;
; It is NOT to be implemented.
; `column-proof` should be assumed to be missing until such time
; as a concrete `column-proof` is defined.
;
; Similar to `row-proof` there can be multiple column-proofs defined which prove
; certain characteristics of the encrypted column values.
; They are identified by the unsigned integer starting the proof.
; Universal Encrypted Column Proof (Placeholder)
column-proof = [ uint, [ +undefined ] ]
Required Definition: matrix-proof
; Proof that values in the matrix of all columns and rows have a required arrangement.
; This is similar to the `row-proof` and `column-proof` but for all values in a
; ballot taken together.
;
; There is a single `matrix-proof` but it may be chosen from a pre-defined
; known set of valid proofs.
;
; Currently there are no `matrix-proof` defined, this value is
; a placeholder for documentation purposes only.
;
; It is NOT to be implemented.
; `matrix-proof` should be assumed to be missing until such time
; as a concrete `matrix-proof` is defined.
;
; Similar to `row-proof` and `column-proof` there can be multiple matrix-proofs defined
; which prove certain characteristics of the encrypted column values.
; They are identified by the unsigned integer starting the proof.
; Universal Encrypted Matrix Proof (Placeholder)
matrix-proof = [ uint, undefined ]
Required Definition: voter-choice
; This is an encrypted payload that a voter, and ONLY the voter can decrypt.
; It allows the voter to recover their choices without needing to decrypt the
; encrypted votes used in the tally.
;
; There is no way to associate this data with the encrypted choices directly, but
; it is created by the voter from the same data used to create the choices.
; Encrypted Voter Choice Payload
voter-choice = [ 0, aes-ctr-encrypted-choices ]
; Encrypted Voter Choices
aes-ctr-encrypted-choices = +aes-ctr-encrypted-block
; AES-CTR Encrypted Data Block
aes-ctr-encrypted-block = bytes .size 16
Required Definition: aes-ctr-encrypted-choices
; Choices are constructed as a CBOR multidimensional array of the form:
; `[ +[+choice] ]`
; reflecting the choices in the rows and columns as present 1:1 in the encrypted
; choices.
;
; This data is then compressed using `brotli` compression, and the result is encrypted
; using AES-CTR and encoded as a sequence of blocks here.
;
; Data needs to be pre-compressed before encryption as encryption will make the data
; incompressible.
;
; The Encryption Key is to be derived from the Voters catalyst key-chain and not to be
; published.
; Derivation *MUST* include the contest Document ID and Version, so that the same
; encryption key is never used twice for different contests, but can still be re-derived
; by a voter that holds their catalyst key-chain recovery keys.
; Encrypted Voter Choices
aes-ctr-encrypted-choices = +aes-ctr-encrypted-block
; AES-CTR Encrypted Data Block
aes-ctr-encrypted-block = bytes .size 16
Required Definition: aes-ctr-encrypted-block
; AES-CTR encrypted data.
; The Nonce/IV is the UUIDv7 `document_ver`.
; This is the correct size, and has the necessary randomness properties.
; The first block uses the `document_ver` the second `document_ver+1` and so on.
; The document_ver is interpreted as a Big Endian 128bit integer for the purpose
; of the addition.
;
; As the CTR is predictable, the blocks can be decrypted in parallel for maximum performance.
; AES-CTR Encrypted Data Block
aes-ctr-encrypted-block = bytes .size 16
Signers¶
The following User roles may sign documents of this type:
- Registered
Only the original author can update and sign a new version of documents.
Copyright¶
| Copyright | |
|---|---|
| License | This document is licensed under CC-BY-4.0 |
| Created | 2024-12-27 |
| Modified | 2025-11-10 |
| Authors | Alex Pozhylenkov alex.pozhylenkov@iohk.io |
| Nathan Bogale nathan.bogale@iohk.io | |
| Neil McAuliffe neil.mcauliffe@iohk.io | |
| Steven Johnson steven.johnson@iohk.io |
Changelog¶
0.1.5 (2025-11-03)¶
- Add Voting Ballots and Ballot Checkpoint Documents