diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/.pages b/docs/src/architecture/08_concepts/signed_doc/docs/.pages index 8669c9fee0..9bee0998a4 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/.pages +++ b/docs/src/architecture/08_concepts/signed_doc/docs/.pages @@ -7,6 +7,7 @@ nav: - Category Parameters: category_parameters.md - Category Parameters Form Template: category_parameters_form_template.md - Comment Moderation Action: comment_moderation_action.md + - Conditions: conditions.md - Contest Ballot: contest_ballot.md - Contest Ballot Checkpoint: contest_ballot_checkpoint.md - Contest Delegation: contest_delegation.md diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/conditions.md b/docs/src/architecture/08_concepts/signed_doc/docs/conditions.md new file mode 100644 index 0000000000..5b784f5d22 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/conditions.md @@ -0,0 +1,444 @@ +# Conditions + +> **DRAFT STATUS** +> This document is currently in **DRAFT** status. +> Development should **NOT** begin until this specification is formally released. +> This specification is subject to change without notice. + +## Description + +Conditions documents are simple document types published by authoritative parties +(such as Catalyst admins) to define terms and conditions that users must accept +before submitting documents to the system. + +The Conditions document type supports multiple condition documents for different purposes, such as: + +* Terms of Use (TOU) +* License agreements +* Operational guidelines +* Regional restrictions +* Privacy policies +* Other legal or operational requirements + +The payload of a Conditions document contains the text of the terms and +conditions, typically in Markdown or HTML format. +This allows for rich formatting while maintaining human readability. + +Conditions documents are versioned and can be revoked, enabling administrators to +update terms over time while maintaining an auditable history of what terms were +in effect at any given time. + +Conditions documents are referenced by parameter documents (Brand, Campaign, +Category, and Contest Parameters) to specify which conditions are required at each +level of the system hierarchy. +User-submitted documents (such as Proposals and Comments) must reference all +required conditions from their parameter hierarchy, with the act of listing these +references and signing the document serving as the user's digital signature and +acceptance. + + + +```graphviz dot conditions.dot.svg + +{{ include_file('./../diagrams/conditions.dot', indent=4) }} +``` + + + +### Validation + +The Conditions document *MUST* be a valid signed document according to the +Signed Document Standard. + +When a Conditions document is referenced in a parameter document's +[`conditions`](../metadata.md#conditions) metadata field, the referenced document +*MUST* exist and be of type "Conditions". + +When a Conditions document is referenced in a user-submitted document's +[`conditions`](../metadata.md#conditions) metadata field, the referenced document +*MUST* exist, be of type "Conditions", and not be revoked. + +### Business Logic + +#### Front End + +Front-end applications should: + +* Display Conditions documents to users when they are required to accept them +* Store user acceptance locally to minimize friction (users only need to explicitly accept conditions the first time they encounter them) +* Gray out submission buttons until all required conditions have been accepted +* Display a disclosure on submission listing all accepted conditions under which the document is being submitted +* Provide clear error messages if required conditions are missing or invalid + +#### Back End + +Back-end validation must: + +* Verify that all Conditions documents referenced in user-submitted documents + exist and are valid +* Collect all required conditions from the parameter hierarchy + (Brand → Campaign → Category → Contest) +* Ensure user-submitted documents include exactly the union of all required + conditions from their parameter hierarchy +* Reject documents that reference revoked Conditions documents +* Reject documents that are missing required conditions or include conditions not + in the parameter hierarchy + +The decentralized system (Hermes) will also reject documents without the required +conditions, ensuring validation occurs at multiple layers. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +* [content type](../spec.md#content-type) = `text/markdown` or `text/html` +* [content-encoding](../spec.md#content-encoding) = `[br]` + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | b664afc2-6472-4028-b90f-875bf6eefab8 | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +The document ID validation is performed based on timestamp thresholds: + +* If `future_threshold` is configured, +the document [`id`](../metadata.md#id) cannot be too far in the future from the +current time. +* If `past_threshold` is configured, the document [`id`](../metadata.md#id) cannot be too far in the past from the +current time. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +1. The document version must always be >= the document ID. +2. IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) + then a document with [`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. +3. When a document with the same [`id`](../metadata.md#id) already exists, + the new document's [`ver`](../metadata.md#ver) must be greater than + the latest known submitted version for that [`id`](../metadata.md#id). +4. When a document with the same [`id`](../metadata.md#id) already exists, + the new document's [`type`](../metadata.md#type) must be the same as + the latest known submitted document's [`type`](../metadata.md#type) for that [`id`](../metadata.md#id). + +### [`ref`](../metadata.md#ref) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](../metadata.md#document-reference) | + +Reference to a Linked Document or Documents. + +This field may be used to reference related documents, such as: + +* Related Conditions documents (e.g., a privacy policy that references a terms of + use) +* Legal documents or regulations that the conditions are based on +* Other relevant documentation + +#### [`ref`](../metadata.md#ref) Validation + +The following must be true for a valid reference: + +* The Referenced Document **MUST** Exist +* Every value in the `document_locator` must consistently reference the exact same document. +* The `document_id` and `document_ver` **MUST** match the values in the referenced document. +* In the event there are **MULTIPLE** [`ref`](../metadata.md#ref) listed, they **MUST** be sorted. + +Sorting for each element of [`ref`](../metadata.md#ref) follows the same sort order as specified for Map Keys, +as defined by [CBOR Deterministic Encoding][CBOR-LFD-ENCODING] (4.3.2 Length-First Map Key Ordering). + +### [`revocations`](../metadata.md#revocations) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Version Revocations](../metadata.md#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`](../metadata.md#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`](../metadata.md#revocations) Validation + +If the field is `true` the payload may be absent or invalid. +Such documents may never be submitted. + +**Important**: User-submitted documents that reference revoked Conditions documents *MUST* be rejected during validation. + +## Payload + +The Conditions document payload contains the text of the terms and conditions. + +The payload *MUST* be valid according to the content type specified in the COSE header: + +* If `content-type` is `text/markdown`, the payload must be valid Markdown +* If `content-type` is `text/html`, the payload must be valid HTML5 + +The payload is compressed using Brotli compression (`br` encoding) as specified +in the `content-encoding` header. + +The payload content should be human-readable and clearly state: + +* The purpose of the conditions +* What users are agreeing to +* Any obligations or restrictions +* Effective dates or version information +* Contact information for questions + +## Signers + +The following Admin roles may sign documents of this type: + +* Brand Admin +* Campaign Admin +* Category Admin +* Contest Admin + +The specific admin role required depends on the level at which the Conditions +document is intended to be used. +For example: + +* Brand-level conditions should be signed by Brand Admin +* Campaign-level conditions should be signed by Campaign Admin or Brand Admin +* Category-level conditions should be signed by Category Admin or a parent-level + admin +* Contest-level conditions should be signed by Contest Admin or a parent-level + admin + +Updates are allowed only by the original author of the document. +Collaborators listed in the `collaborators` metadata field do not have permission to update Conditions documents. + +## JSON Specification Requirements + +> **DRAFT STATUS** +> The following JSON specification changes are documented here but **MUST NOT** be +> implemented until this specification is formally released. +> The `signed_doc.json` file is the source of truth for code generation and must +> be marked as `draft: true` when these changes are added. + +### Required Changes to `signed_doc.json` + +The following changes must be made to `catalyst-libs/specs/signed_doc.json`: + +#### 1. Add "Conditions" Document Type + +Add a new entry to the `docs` section with the following structure: + +```json +"Conditions": { + "authors": { + "Nathan Bogale": "nathan.bogale@iohk.io", + "Steven Johnson": "steven.johnson@iohk.io" + }, + "description": "Conditions documents define terms and conditions that users must accept before submitting documents to the system. Supports multiple condition types (TOU, license agreements, operational guidelines, regional restrictions).", + "draft": true, + "type": "", + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": "text/markdown" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": ["br"] + } + }, + "metadata": { + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "Document Id", + "required": "yes" + }, + "ver": { + "description": "The unique version of the document.", + "format": "Document Ver", + "required": "yes" + }, + "ref": { + "description": "Reference to a Linked Document or Documents.", + "format": "Document Reference", + "required": "optional" + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.", + "format": "Version Revocations", + "required": "optional" + } + }, + "payload": { + "description": "The Conditions document payload contains the text of the terms and conditions in Markdown or HTML format.", + "nil": false + }, + "signers": { + "roles": { + "admin": ["Brand Admin", "Campaign Admin", "Category Admin", "Contest Admin"], + "user": [] + }, + "update": { + "description": "Only the original author can update and sign a new version of documents.", + "type": "author" + } + }, + "validation": "The Conditions document *MUST* be a valid signed document according to the Signed Document Standard.", + "versions": [ + { + "version": "0.01", + "modified": "2025-01-XX", + "changes": "* First Published Version (DRAFT)" + } + ] +} +``` + +**Important Notes:** + +* Generate a new UUIDv4 for the `type` field +* Set `draft: true` as required by Steven Johnson +* The `value` for `content type` may be `text/markdown` or `text/html` + (consider supporting both) + +#### 2. Add "conditions" Metadata Field + +Add the `conditions` metadata field to the following document types in their `metadata` sections: + +**Parameter Documents** (Brand Parameters, Campaign Parameters, Category +Parameters, Contest Parameters): + +```json +"conditions": { + "description": "An array of references to Conditions documents that define terms and conditions required at this level.", + "format": "Document Reference", + "required": "optional", + "multiple": true, + "type": ["Conditions"], + "validation": "If present, must be an array of valid Conditions document +references. All referenced documents must exist and be of type 'Conditions'. The +array must be sorted according to CBOR Deterministic Encoding rules." +} +``` + +**User-Submitted Documents** (Proposal, Proposal Comment, etc.): + +```json +"conditions": { + "description": "An array of references to all Conditions documents that the +user has accepted. Must include ALL conditions required by the parameter +hierarchy (Brand → Campaign → Category → Contest).", + "format": "Document Reference", + "required": "optional", + "multiple": true, + "type": ["Conditions"], + "validation": "Must exactly match the union of all required conditions from +the parameter hierarchy. All referenced documents must exist, be valid, and not +be revoked. The array must be sorted according to CBOR Deterministic Encoding +rules." +} +``` + +**Important Notes:** + +* Set `multiple: true` to allow arrays of document references +* Set `required: "optional"` (but required when conditions are specified in + parameter hierarchy for user documents) +* The validation logic for user documents requires transitive collection from + parameter hierarchy + +#### 3. Update Document Types Table + +The `types.md` file will be automatically regenerated from the JSON specification once these changes are made. Ensure the Conditions document type appears in the generated table. + +### Code Generation Impact + +Once these changes are made to `signed_doc.json` and the specification is +released (draft status removed), the following code will need to be updated: + +* **Rust**: Add `conditions` field to metadata structs and implement validation + rules +* **Python**: Add `conditions` to `DocType` enum and metadata handling +* **Dart**: Add `conditions` to `DocumentType` enum +* **Backend Validation**: Implement transitive condition collection and matching + logic +* **CLI Tools**: Add condition querying and acceptance prompts + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2025-01-XX | +| Modified | 2025-01-XX | +| | Nathan Bogale | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-01-XX) + +* First Published Version (DRAFT) + +[CBOR-LFD-ENCODING]: https://www.rfc-editor.org/rfc/rfc8949.html#section-4.2.3 +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md index d7d5f2223d..17b3eb7cb1 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md @@ -76,9 +76,9 @@ with the highest priority. references are invalid. This is to prevent a Representative changing their nomination invalidating a delegation with multiple representatives. -* The payload MUST be nil. +* The payload MAY be nil, or if present, MUST conform to the JSON schema defined in the [Payload](#payload) section. -A Representative *MUST* Delegate to their latest Nomination for a Category, +A Representative *MUST* Delegate to their latest Nomination for a Contest, otherwise their Nomination is invalid. This is because Delegation points to a *SPECIFIC* Nomination, and it @@ -313,21 +313,28 @@ valid drep nominations. ], "title": "Contest Delegation Schema", "description": "Structure of the payload of a Contest Delegation.", - "type": "object", - "properties": { - "weights": { - "description": "List of weights to apply to each delegate.\nThis list is in the same order as the delegate references.\nIf there are fewer entries than delegates, then the missing weights are set to `1`.\nIf there are more weights, then the extra weights are ignored. If the payload is missing, OR the array is empty, then the weights assigned is `1`.", - "items": { - "exclusiveMinimum": 0, - "type": "integer" + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "weights": { + "description": "List of weights to apply to each delegate.\nThis list is in the same order as the delegate references.\nIf there are fewer entries than delegates, then the missing weights are set to `1`.\nIf there are more weights, then the extra weights are ignored. If the payload is missing, OR the array is empty, then the weights assigned is `1`.", + "items": { + "exclusiveMinimum": 0, + "type": "integer" + }, + "minItems": 0, + "type": "array" + } }, - "minItems": 0, - "type": "array" + "required": [ + "weights" + ] } - }, - "additionalProperties": false, - "required": [ - "weights" ], "x-changelog": { "2025-03-01": [ diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md index b3920042a9..74e893d2cf 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md @@ -37,7 +37,7 @@ The payload of a profile is controlled by its template. ### Validation -* The signer MUST be a registered 'Representative'. +* The signer MUST be a registered 'Representative' (the signature MUST use the Representative role from the Catalyst ID, not the normal Role0 signature) and MUST be the same as the author of the referenced Rep Profile document. * The 'ref' metadata field MUST point to a valid 'Representative Profile' document. * The 'parameters' metadata field MUST point to a valid 'Contest Parameters' document. * The 'template' metadata field MUST point to a valid 'Representative Nomination Form Template' document. diff --git a/docs/src/architecture/08_concepts/signed_doc/metadata.md b/docs/src/architecture/08_concepts/signed_doc/metadata.md index e72f34382d..1d178e1207 100644 --- a/docs/src/architecture/08_concepts/signed_doc/metadata.md +++ b/docs/src/architecture/08_concepts/signed_doc/metadata.md @@ -414,6 +414,138 @@ 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. +### `conditions` + +> **DRAFT STATUS** +> This metadata field is currently in **DRAFT** status. +> Development should **NOT** begin until this specification is formally released. +> This specification is subject to change without notice. + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](metadata.md#document-reference) | +| Multiple References | yes | +| Valid References | [Conditions](./docs/conditions.md) | + +An array of references to [Conditions](./docs/conditions.md) documents that define terms and conditions. + +The `conditions` metadata field serves two distinct purposes depending on the document type: + +1. **On Parameter Documents** (Brand Parameters, Campaign Parameters, Category Parameters, Contest Parameters): + * Lists the required condition documents for that level of the system hierarchy + * Specifies which terms users must accept when submitting documents at this level + * The field is optional - if not present, no conditions are required at that level + +2. **On User-Submitted Documents** (Proposals, Proposal Comments, etc.): + * References all condition documents that the user has accepted + * Must include ALL conditions required by the parameter hierarchy (Brand → Campaign → Category → Contest) + * The act of listing these references and signing the document serves as the user's digital signature and acceptance + * **Schema-level**: The field is marked as optional in the schema, allowing documents to be created without it + * **Validation-level**: During validation, this field becomes required when the parameter hierarchy specifies conditions. + If conditions are required by any level in the parameter hierarchy, the field must be present and must exactly + match all required conditions. If no conditions are specified in the parameter hierarchy, the field may be omitted + +#### `conditions` Validation + +**For Parameter Documents:** + +* The `conditions` field is optional +* If present, must be an array of valid [Conditions](./docs/conditions.md) document references +* All referenced documents must exist and be of type "Conditions" +* The array must be sorted according to [CBOR Deterministic Encoding][CBOR-LFD-ENCODING] (4.3.2 Length-First Map Key Ordering) +* All array elements must be unique + +**For User-Submitted Documents:** + +**Important**: While the `conditions` field is optional at the schema level, validation enforces conditional requirements +based on the parameter hierarchy. This validation occurs at runtime, not during schema validation. + +The validation process for user-submitted documents involves transitive collection of required conditions: + +1. Extract the [`parameters`](metadata.md#parameters) reference from the user document +2. Starting from the referenced parameters document, follow the parent chain upward to Brand: + * If the document references **Contest Parameters**, determine its parent by examining the Contest Parameters document's `parameters` metadata field, then follow the appropriate path: + - If Contest's parent is **Brand**: Contest → Brand + - If Contest's parent is **Campaign**: Contest → Campaign → Brand + - If Contest's parent is **Category**: Contest → Category → Campaign → Brand + * If the document references **Category Parameters**, follow: Category → Campaign → Brand + * If the document references **Campaign Parameters**, follow: Campaign → Brand + * If the document references **Brand Parameters**, only Brand is included + + **Note:** Contest Parameters can anchor to Brand, Campaign, or Category (as specified in the Contest Parameters document's `parameters` field). The validation must examine the actual Contest Parameters document to determine which parent chain applies. This is not a fixed hierarchy - the path depends on where the specific Contest is anchored. +3. Collect all `conditions` arrays from each parameter level encountered in the upward chain +4. Union all condition references (removing duplicates based on document ID and + version) +5. Sort the unified list according to [CBOR Deterministic Encoding][CBOR-LFD-ENCODING] +6. Compare the user document's `conditions` array with this unified, sorted list +7. Validation succeeds only if they match exactly + +**Important**: The chain traversal always moves UPWARD from the document's referenced parameters document to Brand. Contest Parameters are only included if the document directly references them. The chain order depends on where the document is anchored in the hierarchy. + +**If the unified list is non-empty** (conditions are required by the parameter hierarchy), the `conditions` field +becomes required and must be present in the user document. **If the unified list is empty** (no conditions are +required), the `conditions` field may be omitted. + +**Drafts Requirement**: Conditions must be included on **every submission**, including draft versions of proposals +or other documents. This ensures positive and current assent at every stage of document creation. Without this +requirement, a user could accept terms for the first draft, change their mind, and then submit a subsequent draft +without the terms, meaning their assent is no longer positively asserted. It also ensures that rules, such as those +against objectionable material, apply to the document at every stage of its creation. + +**Collaborators Exclusion**: The acceptance of terms is tied to the act of submission by an individual. The terms +and conditions apply only to the individual who signs and submits the document. Collaborators listed on the +document are **not required** to accept the conditions. This mirrors how contracts typically work, where each +party must sign individually. Only the document author (signer) must include the `conditions` field to indicate +their acceptance. + +**Validation Rules:** + +* The user document's `conditions` array must exactly match the union of all required conditions from the parameter hierarchy +* All referenced Conditions documents must exist and be valid +* All referenced Conditions documents must not be revoked +* The array must be sorted (CBOR deterministic encoding order) +* All array elements must be unique + +**Validation Failures:** + +The document will be rejected if: + +* Missing required conditions (conditions specified in parameter hierarchy but not + in user document) +* Includes extra conditions (conditions in user document not in parameter + hierarchy) +* Array is not sorted correctly +* Any referenced condition document doesn't exist or is invalid +* Any referenced condition document is revoked +* Array contains duplicate references + +**Edge Cases:** + +* **Parameter documents with no `conditions` field**: User documents don't need to include conditions at that level +* **Empty `conditions` arrays**: Valid if no conditions are required by any level in the parameter hierarchy +* **Revoked condition documents**: User documents referencing revoked conditions must be rejected +* **Multiple conditions at same level**: All conditions from a parameter level are required +* **Conditions at multiple levels**: User must accept all conditions from all levels (Brand, Campaign, Category, Contest) + +**Example:** + +A user submitting a Proposal to a Category must accept: + +* All conditions from the Category Parameters (if any) +* All conditions from the Campaign Parameters (if any) +* All conditions from the Brand Parameters (if any) + +The Proposal's `conditions` array must contain the union of all these conditions, sorted and deduplicated. + +Note: Contest Parameters are below Category in the hierarchy, so they do not apply to documents at the Category level. If a Proposal is submitted to a Contest, then Contest Parameters would be included in the chain (Contest → Category → Campaign → Brand). + +In the event there are **MULTIPLE** [`conditions`](metadata.md#conditions) listed, they **MUST** be sorted. + +Sorting for each element of [`conditions`](metadata.md#conditions) follows the same sort order as specified for Map Keys, +as defined by [CBOR Deterministic Encoding][CBOR-LFD-ENCODING] (4.3.2 Length-First Map Key Ordering). + ### `chain` diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index aeefad96f9..c3377fc22d 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -14,6 +14,7 @@ All Defined Document Types | [Category Parameters](docs/category_parameters.md) | 48c20109-362a-4d32-9bba-e0a9cf8b45be | `#6.37(h'48c20109362a4d329bbae0a9cf8b45be')` | | [Category Parameters Form Template](docs/category_parameters_form_template.md) | 65b1e8b0-51f1-46a5-9970-72cdf26884be | `#6.37(h'65b1e8b051f146a5997072cdf26884be')` | | [Comment Moderation Action](docs/comment_moderation_action.md) | 84a4b502-3b7e-47fd-84e4-6fee08794bd7 | `#6.37(h'84a4b5023b7e47fd84e46fee08794bd7')` | +| [Conditions](docs/conditions.md) | b664afc2-6472-4028-b90f-875bf6eefab8 | `#6.37(h'b664afc264724028b90f875bf6eefab8')` | | [Contest Ballot](docs/contest_ballot.md) | de1284b8-8533-4f7a-81cc-ff4bde5ef8d0 | `#6.37(h'de1284b885334f7a81ccff4bde5ef8d0')` | | [Contest Ballot Checkpoint](docs/contest_ballot_checkpoint.md) | 58608925-bda3-47df-b39a-ae0d0a1dd6ed | `#6.37(h'58608925bda347dfb39aae0d0a1dd6ed')` | | [Contest Delegation](docs/contest_delegation.md) | 764f17fb-cc50-4979-b14a-b213dbac5994 | `#6.37(h'764f17fbcc504979b14ab213dbac5994')` | diff --git a/specs/definitions/signed_doc_types/defs.cue b/specs/definitions/signed_doc_types/defs.cue index 90ccc78dd7..869fabbc9f 100644 --- a/specs/definitions/signed_doc_types/defs.cue +++ b/specs/definitions/signed_doc_types/defs.cue @@ -38,12 +38,13 @@ allDocNames: [...#docName] & [ #DocClusters: [string]: #DocumentCluster doc_clusters: #DocClusters & { - // System parameters define the system, excludes Contests. + // System parameters define the system hierarchy. "System Parameters": { docs: [ "Brand Parameters", "Campaign Parameters", "Category Parameters", + "Contest Parameters", ] } } diff --git a/specs/definitions/signed_doc_types/types.cue b/specs/definitions/signed_doc_types/types.cue index e5fb859c96..f38e75d505 100644 --- a/specs/definitions/signed_doc_types/types.cue +++ b/specs/definitions/signed_doc_types/types.cue @@ -30,6 +30,7 @@ allDocTypes: { "Contest Delegation": "764f17fb-cc50-4979-b14a-b213dbac5994" "Contest Ballot": "de1284b8-8533-4f7a-81cc-ff4bde5ef8d0" "Contest Ballot Checkpoint": "58608925-bda3-47df-b39a-ae0d0a1dd6ed" + "Conditions": "b664afc2-6472-4028-b90f-875bf6eefab8" //"Rep Profile Moderation Action": "0e20010b-eeaf-4938-a7ee-ceb3df9e8af6" // speculative //"Rep Nomination Moderation Action": "d27ecb44-bd4d-42bb-9273-5e5433cdfdb6" // speculative } diff --git a/specs/definitions/signed_docs/docs/conditions.cue b/specs/definitions/signed_docs/docs/conditions.cue new file mode 100644 index 0000000000..3094672477 --- /dev/null +++ b/specs/definitions/signed_docs/docs/conditions.cue @@ -0,0 +1,163 @@ +package signed_docs + +import ( + "github.com/input-output-hk/catalyst-libs/specs/signed_doc_types" +) + +// Conditions Document Definition + +docs: #DocumentDefinitions & { + Conditions: { + description: """ + Conditions documents define terms and conditions that users must accept + before submitting documents to the system. + + Supports multiple condition types (TOU, license agreements, operational + guidelines, regional restrictions). + + The payload of a Conditions document contains the text of the terms and + conditions, typically in Markdown or HTML format. + This allows for rich formatting while maintaining human readability. + + Conditions documents are versioned and can be revoked, enabling + administrators to update terms over time while maintaining an auditable + history of what terms were in effect at any given time. + """ + + validation: """ + The Conditions document *MUST* be a valid signed document according to + the Signed Document Standard. + + When a Conditions document is referenced in a parameter document's + `conditions` metadata field, the referenced document *MUST* exist and be + of type "Conditions". + + When a Conditions document is referenced in a user-submitted document's + `conditions` metadata field, the referenced document *MUST* exist, be of + type "Conditions", and not be revoked. + """ + + business_logic: { + front_end: """ + Front-end applications should: + + * Display Conditions documents to users when they are required to + accept them + * Store user acceptance locally to minimize friction (users only need + to explicitly accept conditions the first time they encounter them) + * Gray out submission buttons until all required conditions have been + accepted + * Display a disclosure on submission listing all accepted conditions + under which the document is being submitted + * Provide clear error messages if required conditions are missing or + invalid + """ + + back_end: """ + Back-end validation must: + + * Verify that all Conditions documents referenced in user-submitted + documents exist and are valid + * Collect all required conditions from the parameter hierarchy + (Brand → Campaign → Category → Contest) + * Ensure user-submitted documents include exactly the union of all + required conditions from their parameter hierarchy + * Reject documents that reference revoked Conditions documents + * Reject documents that are missing required conditions or include + conditions not in the parameter hierarchy + + The decentralized system (Hermes) will also reject documents without + the required conditions, ensuring validation occurs at multiple layers. + """ + } + + headers: "content type": value: [ + "text/markdown; charset=utf-8", + "text/html; charset=utf-8", + ] + + headers: "content-encoding": value: ["br"] + + metadata: { + ref: { + required: "optional" + type: signed_doc_types.allDocNames + } + + collaborators: { + required: "optional" + description: """ + A list of collaborators who may be associated with this document. + + **Important**: For Conditions documents, only the original author can update + and sign new versions. Collaborators listed here do not have permission to + publish updates to this document. This field is optional and may be used for + documentation or organizational purposes only. + """ + validation: """ + For Conditions documents, collaborators do not have update permissions. + Only the original author can create new versions of Conditions documents. + + In the event there are **MULTIPLE** `collaborators` listed, they **MUST** be + sorted. + + Sorting for each element of `collaborators` follows the same sort order as + specified for Map Keys, as defined by CBOR Deterministic Encoding + (4.3.2 Length-First Map Key Ordering). + """ + } + + revocations: required: "optional" + } + + payload: description: """ + The Conditions document payload contains the text of the terms and + conditions. + + The payload *MUST* be valid according to the content type specified in + the COSE header: + + * If `content-type` is `text/markdown; charset=utf-8`, the payload must be + valid Markdown + * If `content-type` is `text/html; charset=utf-8`, the payload must be + valid HTML5 + + The payload is compressed using Brotli compression (`br` encoding) as + specified in the `content-encoding` header. + + The payload content should be human-readable and clearly state: + * The purpose of the conditions + * What users are agreeing to + * Any obligations or restrictions + * Effective dates or version information + * Contact information for questions + """ + + signers: { + roles: admin: [ + "Brand Admin", + "Campaign Admin", + "Category Admin", + "Contest Admin", + ] + + update: type: "author" + } + + authors: { + "Nathan Bogale": "nathan.bogale@iohk.io" + "Steven Johnson": "steven.johnson@iohk.io" + } + + versions: [ + { + version: "0.01" + modified: "2025-01-XX" + changes: """ + * First Published Version (DRAFT) + """ + }, + ] + } +} + diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue index 9aa1b05498..0321caa519 100644 --- a/specs/definitions/signed_docs/docs/contest_delegation.cue +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -68,9 +68,9 @@ docs: "Contest Delegation": { references are invalid. This is to prevent a Representative changing their nomination invalidating a delegation with multiple representatives. - * The payload MUST be nil. + * The payload MAY be nil, or if present, MUST conform to the JSON schema defined in the payload section. - A Representative *MUST* Delegate to their latest Nomination for a Category, + A Representative *MUST* Delegate to their latest Nomination for a Contest, otherwise their Nomination is invalid. \(docs."Rep Nomination"._latest_nomination_note) diff --git a/specs/definitions/signed_docs/docs/generic_parameters.cue b/specs/definitions/signed_docs/docs/generic_parameters.cue index 9222a61c79..856aedea8b 100644 --- a/specs/definitions/signed_docs/docs/generic_parameters.cue +++ b/specs/definitions/signed_docs/docs/generic_parameters.cue @@ -47,6 +47,8 @@ _parameters_payload_description: """ revocations: required: "optional" parameters: required: _ | *"yes" + + conditions: required: "optional" } headers: "content type": value: "application/json" diff --git a/specs/definitions/signed_docs/docs/payload_schemas/contest_delegation.schema.json b/specs/definitions/signed_docs/docs/payload_schemas/contest_delegation.schema.json index 6e49605627..76b68a54b3 100644 --- a/specs/definitions/signed_docs/docs/payload_schemas/contest_delegation.schema.json +++ b/specs/definitions/signed_docs/docs/payload_schemas/contest_delegation.schema.json @@ -13,20 +13,27 @@ "First Version Created." ] }, - "type": "object", - "additionalProperties": false, - "properties": { - "weights": { - "type": "array", - "description": "List of weights to apply to each delegate.\nThis list is in the same order as the delegate references.\nIf there are fewer entries than delegates, then the missing weights are set to `1`.\nIf there are more weights, then the extra weights are ignored. If the payload is missing, OR the array is empty, then the weights assigned is `1`.", - "items": { - "type": "integer", - "exclusiveMinimum": 0 + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "weights": { + "type": "array", + "description": "List of weights to apply to each delegate.\nThis list is in the same order as the delegate references.\nIf there are fewer entries than delegates, then the missing weights are set to `1`.\nIf there are more weights, then the extra weights are ignored. If the payload is missing, OR the array is empty, then the weights assigned is `1`.", + "items": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "minItems": 0 + } }, - "minItems": 0 + "required": [ + "weights" + ] } - }, - "required": [ - "weights" ] } \ No newline at end of file diff --git a/specs/definitions/signed_docs/docs/rep_nomintion.cue b/specs/definitions/signed_docs/docs/rep_nomintion.cue index 8356ec2ea7..2e6bc0ddb0 100644 --- a/specs/definitions/signed_docs/docs/rep_nomintion.cue +++ b/specs/definitions/signed_docs/docs/rep_nomintion.cue @@ -44,7 +44,7 @@ docs: "Rep Nomination": { """ validation: """ - * The signer MUST be a registered 'Representative'. + * The signer MUST be a registered 'Representative' (the signature MUST use the Representative role from the Catalyst ID, not the normal Role0 signature) and MUST be the same as the author of the referenced Rep Profile document. * The 'ref' metadata field MUST point to a valid 'Representative Profile' document. * The 'parameters' metadata field MUST point to a valid 'Contest Parameters' document. * The 'template' metadata field MUST point to a valid 'Representative Nomination Form Template' document. diff --git a/specs/definitions/signed_docs/metadata.cue b/specs/definitions/signed_docs/metadata.cue index 68ecd8cf89..bd00851688 100644 --- a/specs/definitions/signed_docs/metadata.cue +++ b/specs/definitions/signed_docs/metadata.cue @@ -87,6 +87,7 @@ _metadataNames: [ "collaborators", "revocations", "parameters", + "conditions", "chain", ] @@ -275,6 +276,76 @@ _allMetadataNames: or([ """ } + conditions: { + format: "Document Reference" + description: """ + An array of references to Conditions documents that define terms and conditions. + + The `conditions` metadata field serves two distinct purposes depending on the document type: + + 1. **On Parameter Documents** (Brand Parameters, Campaign Parameters, Category Parameters, Contest Parameters): + * Lists the required condition documents for that level of the system hierarchy + * Specifies which terms users must accept when submitting documents at this level + * The field is optional - if not present, no conditions are required at that level + + 2. **On User-Submitted Documents** (Proposals, Proposal Comments, etc.): + * References all condition documents that the user has accepted + * Must include ALL conditions required by the parameter hierarchy (Brand → Campaign → Category → Contest) + * The act of listing these references and signing the document serves as the user's digital signature and acceptance + * The field is optional when no conditions are required by the parameter hierarchy, but required when conditions are specified + """ + validation: """ + **For Parameter Documents:** + + * The `conditions` field is optional + * If present, must be an array of valid Conditions document references + * All referenced documents must exist and be of type "Conditions" + * The array must be sorted according to CBOR Deterministic Encoding (4.3.2 Length-First Map Key Ordering) + * All array elements must be unique + + **For User-Submitted Documents:** + + The validation process for user-submitted documents involves transitive collection of required conditions: + + 1. Extract the `parameters` reference from the user document + 2. Starting from the referenced parameters document, follow the parent chain upward to Brand: + * If the document references Contest Parameters, determine its parent by examining the Contest Parameters document's `parameters` metadata field, then follow the appropriate path: + - If Contest's parent is Brand: Contest → Brand + - If Contest's parent is Campaign: Contest → Campaign → Brand + - If Contest's parent is Category: Contest → Category → Campaign → Brand + * If the document references Category Parameters, follow: Category → Campaign → Brand + * If the document references Campaign Parameters, follow: Campaign → Brand + * If the document references Brand Parameters, only Brand is included + + Note: Contest Parameters can anchor to Brand, Campaign, or Category (as specified in the Contest Parameters document's `parameters` field). The validation must examine the actual Contest Parameters document to determine which parent chain applies. This is not a fixed hierarchy - the path depends on where the specific Contest is anchored. + 3. Collect all `conditions` arrays from each parameter level encountered in the upward chain + 4. Union all condition references (removing duplicates based on document ID and version) + 5. Sort the unified list according to CBOR Deterministic Encoding + 6. Compare the user document's `conditions` array with this unified, sorted list + 7. Validation succeeds only if they match exactly + + Important: The chain traversal always moves UPWARD from the document's referenced parameters document to Brand. Contest Parameters are only included if the document directly references them. The chain order depends on where the document is anchored in the hierarchy. + + **Validation Rules:** + + * The user document's `conditions` array must exactly match the union of all required conditions from the parameter hierarchy + * All referenced Conditions documents must exist and be valid + * All referenced Conditions documents must not be revoked + * The array must be sorted (CBOR deterministic encoding order) + * All array elements must be unique + + **Validation Failures:** + + The document will be rejected if: + * Missing required conditions (conditions specified in parameter hierarchy but not in user document) + * Includes extra conditions (conditions in user document not in parameter hierarchy) + * Array is not sorted correctly + * Any referenced condition document doesn't exist or is invalid + * Any referenced condition document is revoked + * Array contains duplicate references + """ + } + } // Note: we make all normally excluded fields optional at the global level, because they are globally optional @@ -288,6 +359,12 @@ metadata: headers: { reply: type: signed_doc_types.commentDocNamesList section: required: "optional" collaborators: required: "optional" + conditions: { + required: "optional" + format: "Document Reference" + type: ["Conditions"] + multiple: true + } } // Preferred display order diff --git a/specs/generators/uv.lock b/specs/generators/uv.lock index ffb314b9c9..c1d1f694dc 100644 --- a/specs/generators/uv.lock +++ b/specs/generators/uv.lock @@ -413,7 +413,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.12.4" +version = "2.12.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -421,9 +421,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/96/ad/a17bc283d7d81837c061c49e3eaa27a45991759a1b7eae1031921c6bd924/pydantic-2.12.4.tar.gz", hash = "sha256:0f8cb9555000a4b5b617f66bfd2566264c4984b27589d3b845685983e8ea85ac", size = 821038, upload-time = "2025-11-05T10:50:08.59Z" } +sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl", hash = "sha256:92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e", size = 463400, upload-time = "2025-11-05T10:50:06.732Z" }, + { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, ] [[package]] diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 2d42af0377..3038e93fde 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -689,7 +689,8 @@ "docs": [ "Brand Parameters", "Campaign Parameters", - "Category Parameters" + "Category Parameters", + "Contest Parameters" ] } }, @@ -744,6 +745,16 @@ "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, + "conditions": { + "description": "An array of references to Conditions documents that define terms and conditions required at this level.\n\nLists the required condition documents for this level of the system hierarchy.\nSpecifies which terms users must accept when submitting documents at this level.\nThe field is optional - if not present, no conditions are required at that level.", + "format": "Document Reference", + "required": "optional", + "multiple": true, + "type": [ + "Conditions" + ], + "validation": "If present, must be an array of valid Conditions document references.\nAll referenced documents must exist and be of type \"Conditions\".\nThe array must be sorted according to CBOR Deterministic Encoding rules.\nAll array elements must be unique." + }, "ref": { "description": "Reference to a Linked Document or Documents.\nThis is the primary hierarchical reference to a related document.\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n\n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", "format": "Document Reference", @@ -1001,6 +1012,16 @@ "type": "Brand Parameters", "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, + "conditions": { + "description": "An array of references to Conditions documents that define terms and conditions required at this level.\n\nLists the required condition documents for this level of the system hierarchy.\nSpecifies which terms users must accept when submitting documents at this level.\nThe field is optional - if not present, no conditions are required at that level.", + "format": "Document Reference", + "required": "optional", + "multiple": true, + "type": [ + "Conditions" + ], + "validation": "If present, must be an array of valid Conditions document references.\nAll referenced documents must exist and be of type \"Conditions\".\nThe array must be sorted according to CBOR Deterministic Encoding rules.\nAll array elements must be unique." + }, "ref": { "description": "Reference to a Linked Document or Documents.\nThis is the primary hierarchical reference to a related document.\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n\n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", "format": "Document Reference", @@ -1263,6 +1284,16 @@ "type": "Campaign Parameters", "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, + "conditions": { + "description": "An array of references to Conditions documents that define terms and conditions required at this level.\n\nLists the required condition documents for this level of the system hierarchy.\nSpecifies which terms users must accept when submitting documents at this level.\nThe field is optional - if not present, no conditions are required at that level.", + "format": "Document Reference", + "required": "optional", + "multiple": true, + "type": [ + "Conditions" + ], + "validation": "If present, must be an array of valid Conditions document references.\nAll referenced documents must exist and be of type \"Conditions\".\nThe array must be sorted according to CBOR Deterministic Encoding rules.\nAll array elements must be unique." + }, "ref": { "description": "Reference to a Linked Document or Documents.\nThis is the primary hierarchical reference to a related document.\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n\n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", "format": "Document Reference", @@ -1592,6 +1623,108 @@ } ] }, + "Conditions": { + "authors": { + "Nathan Bogale": "nathan.bogale@iohk.io", + "Steven Johnson": "steven.johnson@iohk.io" + }, + "description": "Conditions documents define terms and conditions that users must accept before submitting documents to the system. Supports multiple condition types (TOU, license agreements, operational guidelines, regional restrictions).\n\nThe payload of a Conditions document contains the text of the terms and conditions, typically in Markdown or HTML format. This allows for rich formatting while maintaining human readability.\n\nConditions documents are versioned and can be revoked, enabling administrators to update terms over time while maintaining an auditable history of what terms were in effect at any given time.", + "draft": true, + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": [ + "text/markdown; charset=utf-8", + "text/html; charset=utf-8" + ] + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may be associated with this document.\n\n**Important**: For Conditions documents, only the original author can update and sign new versions.\nCollaborators listed here do not have permission to publish updates to this document.\nThis field is optional and may be used for documentation or organizational purposes only.", + "format": "Collaborators Reference List", + "required": "optional", + "validation": "For Conditions documents, collaborators do not have update permissions.\nOnly the original author can create new versions of Conditions documents.\n\nIn the event there are **MULTIPLE** `collaborators` listed, they **MUST** be sorted.\n\nSorting for each element of `collaborators` follows the same sort order as specified for Map Keys, \nas defined by CBOR Deterministic Encoding (4.3.2 Length-First Map Key Ordering)." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the\ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "The document ID validation is performed based on timestamp thresholds:\n\n* If `future_threshold` is configured,\nthe document `id` cannot be too far in the future from the\ncurrent time.\n* If `past_threshold` is configured, the document `id` cannot be too far in the past from the\ncurrent time." + }, + "ref": { + "description": "Reference to a Linked Document or Documents.\n\nThis field may be used to reference related documents, such as:\n* Related Conditions documents (e.g., a privacy policy that references a terms of use)\n* Legal documents or regulations that the conditions are based on\n* Other relevant documentation", + "format": "Document Reference", + "required": "optional", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document.\n* In the event there are **MULTIPLE** `ref` listed, they **MUST** be sorted.\n\nSorting for each element of `ref` follows the same sort order as specified for Map Keys, \nas defined by CBOR Deterministic Encoding (4.3.2 Length-First Map Key Ordering)." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be `nil`.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked.\nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "optional", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted.\n\n**Important**: User-submitted documents that reference revoked Conditions documents *MUST* be rejected during validation." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "1. The document version must always be >= the document ID.\n2. IF `ver` does not == `id`\n then a document with `id` and `ver` being equal *MUST* exist.\n3. When a document with the same `id` already exists,\n the new document's `ver` must be greater than\n the latest known submitted version for that `id`.\n4. When a document with the same `id` already exists,\n the new document's `type` must be the same as\n the latest known submitted document's `type` for that `id`." + } + }, + "notes": [], + "payload": { + "description": "The Conditions document payload contains the text of the terms and conditions.\n\nThe payload *MUST* be valid according to the content type specified in the COSE header:\n\n* If `content-type` is `text/markdown; charset=utf-8`, the payload must be valid Markdown\n* If `content-type` is `text/html; charset=utf-8`, the payload must be valid HTML5\n\nThe payload is compressed using Brotli compression (`br` encoding) as specified in the `content-encoding` header.\n\nThe payload content should be human-readable and clearly state:\n* The purpose of the conditions\n* What users are agreeing to\n* Any obligations or restrictions\n* Effective dates or version information\n* Contact information for questions", + "nil": false + }, + "signers": { + "roles": { + "admin": [ + "Brand Admin", + "Campaign Admin", + "Category Admin", + "Contest Admin" + ], + "user": [] + }, + "update": { + "description": "Only the original author can update and sign a new version of documents.", + "type": "author" + } + }, + "type": "b664afc2-6472-4028-b90f-875bf6eefab8", + "validation": "The Conditions document *MUST* be a valid signed document according to the Signed Document Standard.\n\nWhen a Conditions document is referenced in a parameter document's `conditions` metadata field, the referenced document *MUST* exist and be of type \"Conditions\".\n\nWhen a Conditions document is referenced in a user-submitted document's `conditions` metadata field, the referenced document *MUST* exist, be of type \"Conditions\", and not be revoked.", + "versions": [ + { + "changes": "* First Published Version (DRAFT)", + "modified": "2025-01-XX", + "version": "0.01" + } + ] + }, "Contest Ballot": { "authors": { "Steven Johnson": "steven.johnson@iohk.io" @@ -2009,10 +2142,9 @@ "title": "Three Delegation Weights" } ], - "nil": false, + "nil": true, "schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": false, "description": "Structure of the payload of a Contest Delegation.", "maintainers": [ { @@ -2020,22 +2152,30 @@ "url": "https://projectcatalyst.io/" } ], - "properties": { - "weights": { - "description": "List of weights to apply to each delegate.\nThis list is in the same order as the delegate references.\nIf there are fewer entries than delegates, then the missing weights are set to `1`.\nIf there are more weights, then the extra weights are ignored. If the payload is missing, OR the array is empty, then the weights assigned is `1`.", - "items": { - "exclusiveMinimum": 0, - "type": "integer" + "oneOf": [ + { + "type": "null" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "weights": { + "description": "List of weights to apply to each delegate.\nThis list is in the same order as the delegate references.\nIf there are fewer entries than delegates, then the missing weights are set to `1`.\nIf there are more weights, then the extra weights are ignored. If the payload is missing, OR the array is empty, then the weights assigned is `1`.", + "items": { + "exclusiveMinimum": 0, + "type": "integer" + }, + "minItems": 0, + "type": "array" + } }, - "minItems": 0, - "type": "array" + "required": [ + "weights" + ] } - }, - "required": [ - "weights" ], "title": "Contest Delegation Schema", - "type": "object", "x-changelog": { "2025-03-01": [ "First Version Created." @@ -2055,7 +2195,7 @@ } }, "type": "764f17fb-cc50-4979-b14a-b213dbac5994", - "validation": "* The `parameters` metadata *MUST* point to the same Contest as the \n\tNomination of the Representative.\n* The 'ref' metadata field MUST point to a valid 'Representative Nomination'.\n IF there are multiple representatives, then any which are not pointing\n to a valid `Representative Nomination` are excluded. \n The nomination is only invalid if ALL references `Representative Nomination` \n references are invalid.\n This is to prevent a Representative changing their nomination invalidating a\n delegation with multiple representatives.\n* The payload MUST be nil.\n\nA Representative *MUST* Delegate to their latest Nomination for a Category,\notherwise their Nomination is invalid.\n\nThis is because Delegation points to a *SPECIFIC* Nomination, and it\n*MUST* be the latest for the Representative on the Contest.\nAs the Nomination contains information that the User relies on\nwhen choosing to delegate, changing that information could have a \nreal and detrimental result in the Delegation choice.\nTherefore, for a Delegation to be valid, it *MUST* point to the\nlatest Nomination for a Representative.\n\nPublishing a newer version of the Nomination Document to a specific contest will\ninvalidate all pre-existing delegations, and all voters will need\nto re-delegate to affirm the delegates latest nomination.\n\nA Voter may withdraw their Delegation by revoking all delegation documents.\n`revocations` must be set to `true` to withdraw a delegation, OR\na later contest delegation may change the delegated representative without\nfirst revoking the prior delegation, as only the latest delegation is\nconsidered.", + "validation": "* The `parameters` metadata *MUST* point to the same Contest as the \n\tNomination of the Representative.\n* The 'ref' metadata field MUST point to a valid 'Representative Nomination'.\n IF there are multiple representatives, then any which are not pointing\n to a valid `Representative Nomination` are excluded. \n The nomination is only invalid if ALL references `Representative Nomination` \n references are invalid.\n This is to prevent a Representative changing their nomination invalidating a\n delegation with multiple representatives.\n* The payload MAY be nil, or if present, MUST conform to the JSON schema defined in the payload section.\n\nA Representative *MUST* Delegate to their latest Nomination for a Contest,\notherwise their Nomination is invalid.\n\nThis is because Delegation points to a *SPECIFIC* Nomination, and it\n*MUST* be the latest for the Representative on the Contest.\nAs the Nomination contains information that the User relies on\nwhen choosing to delegate, changing that information could have a \nreal and detrimental result in the Delegation choice.\nTherefore, for a Delegation to be valid, it *MUST* point to the\nlatest Nomination for a Representative.\n\nPublishing a newer version of the Nomination Document to a specific contest will\ninvalidate all pre-existing delegations, and all voters will need\nto re-delegate to affirm the delegates latest nomination.\n\nA Voter may withdraw their Delegation by revoking all delegation documents.\n`revocations` must be set to `true` to withdraw a delegation, OR\na later contest delegation may change the delegated representative without\nfirst revoking the prior delegation, as only the latest delegation is\nconsidered.", "versions": [ { "changes": "* First Published Version", @@ -2122,10 +2262,21 @@ "type": [ "Brand Parameters", "Campaign Parameters", - "Category Parameters" + "Category Parameters", + "Contest Parameters" ], "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, + "conditions": { + "description": "An array of references to Conditions documents that define terms and conditions required at this level.\n\nLists the required condition documents for this level of the system hierarchy.\nSpecifies which terms users must accept when submitting documents at this level.\nThe field is optional - if not present, no conditions are required at that level.", + "format": "Document Reference", + "required": "optional", + "multiple": true, + "type": [ + "Conditions" + ], + "validation": "If present, must be an array of valid Conditions document references.\nAll referenced documents must exist and be of type \"Conditions\".\nThe array must be sorted according to CBOR Deterministic Encoding rules.\nAll array elements must be unique." + }, "ref": { "description": "Reference to a Linked Document or Documents.\nThis is the primary hierarchical reference to a related document.\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n\n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", "format": "Document Reference", @@ -2254,7 +2405,8 @@ "type": [ "Brand Parameters", "Campaign Parameters", - "Category Parameters" + "Category Parameters", + "Contest Parameters" ], "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, @@ -2387,7 +2539,8 @@ "type": [ "Brand Parameters", "Campaign Parameters", - "Category Parameters" + "Category Parameters", + "Contest Parameters" ], "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, @@ -2607,10 +2760,21 @@ "type": [ "Brand Parameters", "Campaign Parameters", - "Category Parameters" + "Category Parameters", + "Contest Parameters" ], "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, + "conditions": { + "description": "An array of references to all Conditions documents that the user has accepted.\n\nMust include ALL conditions required by the parameter hierarchy (Brand → Campaign → Category → Contest).\nThe act of listing these references and signing the document serves as the user's digital signature and acceptance.\n\n**Schema-level requirement**: This field is marked as optional in the schema, allowing documents to be created without it.\n\n**Validation-level requirement**: During validation, this field becomes required when the parameter hierarchy specifies conditions.\nIf conditions are required by any level in the parameter hierarchy (Brand, Campaign, Category, or Contest),\nthe field must be present and must exactly match all required conditions. If no conditions are specified\nin the parameter hierarchy, the field may be omitted.\n\n**Drafts Requirement**: Conditions must be included on every submission, including draft versions of proposals or other documents.\nThis ensures positive and current assent at every stage of document creation. Without this requirement, a user could accept\nthe terms for the first draft, change their mind, and then submit a subsequent draft without the terms, meaning their\nassent is no longer positively asserted. It also ensures that rules, such as those against objectionable material, apply\nto the document at every stage of its creation.\n\n**Collaborators Exclusion**: The acceptance of terms is tied to the act of submission by an individual. The terms and conditions\napply only to the individual who signs and submits the document. Collaborators listed on the document are not required to\naccept the conditions. This mirrors how contracts typically work, where each party must sign individually. Only the document\nauthor (signer) must include the `conditions` field to indicate their acceptance.", + "format": "Document Reference", + "required": "optional", + "multiple": true, + "type": [ + "Conditions" + ], + "validation": "Must exactly match the union of all required conditions from the parameter hierarchy.\n\nValidation process:\n1. Extract the `parameters` reference from the user document\n2. Starting from the referenced parameters document, follow the parent chain upward to Brand:\n * If the document references Contest Parameters, determine its parent by examining the Contest Parameters document's `parameters` metadata field, then follow the appropriate path:\n - If Contest's parent is Brand: Contest → Brand\n - If Contest's parent is Campaign: Contest → Campaign → Brand\n - If Contest's parent is Category: Contest → Category → Campaign → Brand\n * If the document references Category Parameters, follow: Category → Campaign → Brand\n * If the document references Campaign Parameters, follow: Campaign → Brand\n * If the document references Brand Parameters, only Brand is included\n\n Note: Contest Parameters can anchor to Brand, Campaign, or Category (as specified in the Contest Parameters document's `parameters` field). The validation must examine the actual Contest Parameters document to determine which parent chain applies. This is not a fixed hierarchy - the path depends on where the specific Contest is anchored.\n3. Collect all `conditions` arrays from each parameter level encountered in the upward chain\n4. Union all condition references (removing duplicates based on document ID and version)\n5. Sort the unified list according to CBOR Deterministic Encoding\n6. Compare the user document's `conditions` array with this unified, sorted list\n7. Validation succeeds only if they match exactly\n\nImportant: The chain traversal always moves UPWARD from the document's referenced parameters document to Brand. Contest Parameters are only included if the document directly references them. The chain order depends on where the document is anchored in the hierarchy.\n\nAll referenced Conditions documents must exist, be valid, and not be revoked.\nThe array must be sorted (CBOR deterministic encoding order).\nAll array elements must be unique.\n\nValidation fails if:\n* Missing required conditions (conditions specified in parameter hierarchy but not in user document)\n* Includes extra conditions (conditions in user document not in parameter hierarchy)\n* Array is not sorted correctly\n* Any referenced condition document doesn't exist or is invalid\n* Any referenced condition document is revoked\n* Array contains duplicate references" + }, "ref": { "description": "Reference to a Linked Document or Documents.\nThis is the primary hierarchical reference to a related document.\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n\n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", "format": "Document Reference", @@ -2745,10 +2909,21 @@ "type": [ "Brand Parameters", "Campaign Parameters", - "Category Parameters" + "Category Parameters", + "Contest Parameters" ], "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, + "conditions": { + "description": "An array of references to all Conditions documents that the user has accepted.\n\nMust include ALL conditions required by the parameter hierarchy (Brand → Campaign → Category → Contest).\nThe act of listing these references and signing the document serves as the user's digital signature and acceptance.\n\n**Schema-level requirement**: This field is marked as optional in the schema, allowing documents to be created without it.\n\n**Validation-level requirement**: During validation, this field becomes required when the parameter hierarchy specifies conditions.\nIf conditions are required by any level in the parameter hierarchy (Brand, Campaign, Category, or Contest),\nthe field must be present and must exactly match all required conditions. If no conditions are specified\nin the parameter hierarchy, the field may be omitted.\n\n**Drafts Requirement**: Conditions must be included on every submission, including draft versions of proposals or other documents.\nThis ensures positive and current assent at every stage of document creation. Without this requirement, a user could accept\nthe terms for the first draft, change their mind, and then submit a subsequent draft without the terms, meaning their\nassent is no longer positively asserted. It also ensures that rules, such as those against objectionable material, apply\nto the document at every stage of its creation.\n\n**Collaborators Exclusion**: The acceptance of terms is tied to the act of submission by an individual. The terms and conditions\napply only to the individual who signs and submits the document. Collaborators listed on the document are not required to\naccept the conditions. This mirrors how contracts typically work, where each party must sign individually. Only the document\nauthor (signer) must include the `conditions` field to indicate their acceptance.", + "format": "Document Reference", + "required": "optional", + "multiple": true, + "type": [ + "Conditions" + ], + "validation": "Must exactly match the union of all required conditions from the parameter hierarchy.\n\nValidation process:\n1. Extract the `parameters` reference from the user document\n2. Starting from the referenced parameters document, follow the parent chain upward to Brand:\n * If the document references Contest Parameters, determine its parent by examining the Contest Parameters document's `parameters` metadata field, then follow the appropriate path:\n - If Contest's parent is Brand: Contest → Brand\n - If Contest's parent is Campaign: Contest → Campaign → Brand\n - If Contest's parent is Category: Contest → Category → Campaign → Brand\n * If the document references Category Parameters, follow: Category → Campaign → Brand\n * If the document references Campaign Parameters, follow: Campaign → Brand\n * If the document references Brand Parameters, only Brand is included\n\n Note: Contest Parameters can anchor to Brand, Campaign, or Category (as specified in the Contest Parameters document's `parameters` field). The validation must examine the actual Contest Parameters document to determine which parent chain applies. This is not a fixed hierarchy - the path depends on where the specific Contest is anchored.\n3. Collect all `conditions` arrays from each parameter level encountered in the upward chain\n4. Union all condition references (removing duplicates based on document ID and version)\n5. Sort the unified list according to CBOR Deterministic Encoding\n6. Compare the user document's `conditions` array with this unified, sorted list\n7. Validation succeeds only if they match exactly\n\nImportant: The chain traversal always moves UPWARD from the document's referenced parameters document to Brand. Contest Parameters are only included if the document directly references them. The chain order depends on where the document is anchored in the hierarchy.\n\nAll referenced Conditions documents must exist, be valid, and not be revoked.\nThe array must be sorted (CBOR deterministic encoding order).\nAll array elements must be unique.\n\nValidation fails if:\n* Missing required conditions (conditions specified in parameter hierarchy but not in user document)\n* Includes extra conditions (conditions in user document not in parameter hierarchy)\n* Array is not sorted correctly\n* Any referenced condition document doesn't exist or is invalid\n* Any referenced condition document is revoked\n* Array contains duplicate references" + }, "ref": { "description": "Reference to a Linked Document or Documents.\nThis is the primary hierarchical reference to a related document.\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n\n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", "format": "Document Reference", @@ -2882,7 +3057,8 @@ "type": [ "Brand Parameters", "Campaign Parameters", - "Category Parameters" + "Category Parameters", + "Contest Parameters" ], "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, @@ -3015,7 +3191,8 @@ "type": [ "Brand Parameters", "Campaign Parameters", - "Category Parameters" + "Category Parameters", + "Contest Parameters" ], "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, @@ -3272,7 +3449,8 @@ "type": [ "Brand Parameters", "Campaign Parameters", - "Category Parameters" + "Category Parameters", + "Contest Parameters" ], "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, @@ -3538,7 +3716,7 @@ } }, "type": "bf9abd97-5d1f-4429-8e80-740fea371a9c", - "validation": "* The signer MUST be a registered 'Representative'.\n* The 'ref' metadata field MUST point to a valid 'Representative Profile' document.\n* The 'parameters' metadata field MUST point to a valid 'Contest Parameters' document.\n* The 'template' metadata field MUST point to a valid 'Representative Nomination Form Template' document.\n* The payload MUST be valid against the JSON schema defined in the referenced template.\n* Other rules may apply as defined by the Contest or other parameters which can\n\tcontrol who may validly nominate as a representative in a Contest.\n\nNo Nomination is valid unless the latest Contest Delegation of the Delegate\nrefers to their own Nomination.\nThis requires that Nominating is a two step process:\n\n1. Post the Nomination Document.\n2. Post a Contest Delegation delegating to the new Nomination Document.\n\nUpdating the Nomination Document will invalidate all Nominations to the \nRepresentative.\n\nThis is because Delegation points to a *SPECIFIC* Nomination, and it\n*MUST* be the latest for the Representative on the Contest.\nAs the Nomination contains information that the User relies on\nwhen choosing to delegate, changing that information could have a \nreal and detrimental result in the Delegation choice.\nTherefore, for a Delegation to be valid, it *MUST* point to the\nlatest Nomination for a Representative.\n\nPublishing a newer version of the Nomination Document to a specific contest will\ninvalidate all pre-existing delegations, and all voters will need\nto re-delegate to affirm the delegates latest nomination.", + "validation": "* The signer MUST be a registered 'Representative' (the signature MUST use the Representative role from the Catalyst ID, not the normal Role0 signature) and MUST be the same as the author of the referenced Rep Profile document.\n* The 'ref' metadata field MUST point to a valid 'Representative Profile' document.\n* The 'parameters' metadata field MUST point to a valid 'Contest Parameters' document.\n* The 'template' metadata field MUST point to a valid 'Representative Nomination Form Template' document.\n* The payload MUST be valid against the JSON schema defined in the referenced template.\n* Other rules may apply as defined by the Contest or other parameters which can\n\tcontrol who may validly nominate as a representative in a Contest.\n\nNo Nomination is valid unless the latest Contest Delegation of the Delegate\nrefers to their own Nomination.\nThis requires that Nominating is a two step process:\n\n1. Post the Nomination Document.\n2. Post a Contest Delegation delegating to the new Nomination Document.\n\nUpdating the Nomination Document will invalidate all Nominations to the \nRepresentative.\n\nThis is because Delegation points to a *SPECIFIC* Nomination, and it\n*MUST* be the latest for the Representative on the Contest.\nAs the Nomination contains information that the User relies on\nwhen choosing to delegate, changing that information could have a \nreal and detrimental result in the Delegation choice.\nTherefore, for a Delegation to be valid, it *MUST* point to the\nlatest Nomination for a Representative.\n\nPublishing a newer version of the Nomination Document to a specific contest will\ninvalidate all pre-existing delegations, and all voters will need\nto re-delegate to affirm the delegates latest nomination.", "versions": [ { "changes": "* First Published Version",