Skip to content

Commit 9f080c3

Browse files
committed
fix(docs): Restore Conditions system enhancements after rebase
- Add conditions.cue definition file - Enhanced conditions metadata field documentation - Add Contest Parameters to System Parameters list - Support both Markdown and HTML content types with charset - Update validation process to clarify upward traversal - Add schema-level vs validation-level requirement distinction
1 parent 5f4638f commit 9f080c3

File tree

6 files changed

+264
-20
lines changed

6 files changed

+264
-20
lines changed

docs/src/architecture/08_concepts/signed_doc/metadata.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,10 @@ The `conditions` metadata field serves two distinct purposes depending on the do
442442
* References all condition documents that the user has accepted
443443
* Must include ALL conditions required by the parameter hierarchy (Brand → Campaign → Category → Contest)
444444
* The act of listing these references and signing the document serves as the user's digital signature and acceptance
445-
* The field is optional when no conditions are required by the parameter hierarchy, but required when conditions are specified
445+
* **Schema-level**: The field is marked as optional in the schema, allowing documents to be created without it
446+
* **Validation-level**: During validation, this field becomes required when the parameter hierarchy specifies conditions.
447+
If conditions are required by any level in the parameter hierarchy, the field must be present and must exactly
448+
match all required conditions. If no conditions are specified in the parameter hierarchy, the field may be omitted
446449

447450
#### `conditions` Validation
448451

@@ -456,17 +459,30 @@ The `conditions` metadata field serves two distinct purposes depending on the do
456459

457460
**For User-Submitted Documents:**
458461

462+
**Important**: While the `conditions` field is optional at the schema level, validation enforces conditional requirements
463+
based on the parameter hierarchy. This validation occurs at runtime, not during schema validation.
464+
459465
The validation process for user-submitted documents involves transitive collection of required conditions:
460466

461467
1. Extract the [`parameters`](metadata.md#parameters) reference from the user document
462-
2. Follow the parameter chain: Contest → Category → Campaign → Brand
463-
3. Collect all `conditions` arrays from each parameter level in the hierarchy
468+
2. Starting from the referenced parameters document, follow the parent chain upward to Brand:
469+
* If the document references **Contest Parameters**, follow: Contest → (its parent: Brand/Campaign/Category) → Campaign (if parent was Category) → Brand
470+
* If the document references **Category Parameters**, follow: Category → Campaign → Brand
471+
* If the document references **Campaign Parameters**, follow: Campaign → Brand
472+
* If the document references **Brand Parameters**, only Brand is included
473+
3. Collect all `conditions` arrays from each parameter level encountered in the upward chain
464474
4. Union all condition references (removing duplicates based on document ID and
465475
version)
466476
5. Sort the unified list according to [CBOR Deterministic Encoding][CBOR-LFD-ENCODING]
467477
6. Compare the user document's `conditions` array with this unified, sorted list
468478
7. Validation succeeds only if they match exactly
469479

480+
**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.
481+
482+
**If the unified list is non-empty** (conditions are required by the parameter hierarchy), the `conditions` field
483+
becomes required and must be present in the user document. **If the unified list is empty** (no conditions are
484+
required), the `conditions` field may be omitted.
485+
470486
**Validation Rules:**
471487

472488
* The user document's `conditions` array must exactly match the union of all required conditions from the parameter hierarchy
@@ -500,13 +516,14 @@ The document will be rejected if:
500516

501517
A user submitting a Proposal to a Category must accept:
502518

503-
* All conditions from the Contest Parameters (if any)
504519
* All conditions from the Category Parameters (if any)
505520
* All conditions from the Campaign Parameters (if any)
506521
* All conditions from the Brand Parameters (if any)
507522

508523
The Proposal's `conditions` array must contain the union of all these conditions, sorted and deduplicated.
509524

525+
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).
526+
510527
In the event there are **MULTIPLE** [`conditions`](metadata.md#conditions) listed, they **MUST** be sorted.
511528

512529
Sorting for each element of [`conditions`](metadata.md#conditions) follows the same sort order as specified for Map Keys,

specs/definitions/signed_doc_types/types.cue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ allDocTypes: {
3030
"Contest Delegation": "764f17fb-cc50-4979-b14a-b213dbac5994"
3131
"Contest Ballot": "de1284b8-8533-4f7a-81cc-ff4bde5ef8d0"
3232
"Contest Ballot Checkpoint": "58608925-bda3-47df-b39a-ae0d0a1dd6ed"
33+
"Conditions": "b664afc2-6472-4028-b90f-875bf6eefab8"
3334
//"Rep Profile Moderation Action": "0e20010b-eeaf-4938-a7ee-ceb3df9e8af6" // speculative
3435
//"Rep Nomination Moderation Action": "d27ecb44-bd4d-42bb-9273-5e5433cdfdb6" // speculative
3536
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package signed_docs
2+
3+
import (
4+
"github.com/input-output-hk/catalyst-libs/specs/signed_doc_types"
5+
)
6+
7+
// Conditions Document Definition
8+
9+
docs: #DocumentDefinitions & {
10+
Conditions: {
11+
description: """
12+
Conditions documents define terms and conditions that users must accept
13+
before submitting documents to the system.
14+
15+
Supports multiple condition types (TOU, license agreements, operational
16+
guidelines, regional restrictions).
17+
18+
The payload of a Conditions document contains the text of the terms and
19+
conditions, typically in Markdown or HTML format.
20+
This allows for rich formatting while maintaining human readability.
21+
22+
Conditions documents are versioned and can be revoked, enabling
23+
administrators to update terms over time while maintaining an auditable
24+
history of what terms were in effect at any given time.
25+
"""
26+
27+
validation: """
28+
The Conditions document *MUST* be a valid signed document according to
29+
the Signed Document Standard.
30+
31+
When a Conditions document is referenced in a parameter document's
32+
`conditions` metadata field, the referenced document *MUST* exist and be
33+
of type "Conditions".
34+
35+
When a Conditions document is referenced in a user-submitted document's
36+
`conditions` metadata field, the referenced document *MUST* exist, be of
37+
type "Conditions", and not be revoked.
38+
"""
39+
40+
business_logic: {
41+
front_end: """
42+
Front-end applications should:
43+
44+
* Display Conditions documents to users when they are required to
45+
accept them
46+
* Store user acceptance locally to minimize friction (users only need
47+
to explicitly accept conditions the first time they encounter them)
48+
* Gray out submission buttons until all required conditions have been
49+
accepted
50+
* Display a disclosure on submission listing all accepted conditions
51+
under which the document is being submitted
52+
* Provide clear error messages if required conditions are missing or
53+
invalid
54+
"""
55+
56+
back_end: """
57+
Back-end validation must:
58+
59+
* Verify that all Conditions documents referenced in user-submitted
60+
documents exist and are valid
61+
* Collect all required conditions from the parameter hierarchy
62+
(Brand → Campaign → Category → Contest)
63+
* Ensure user-submitted documents include exactly the union of all
64+
required conditions from their parameter hierarchy
65+
* Reject documents that reference revoked Conditions documents
66+
* Reject documents that are missing required conditions or include
67+
conditions not in the parameter hierarchy
68+
69+
The decentralized system (Hermes) will also reject documents without
70+
the required conditions, ensuring validation occurs at multiple layers.
71+
"""
72+
}
73+
74+
headers: "content type": value: [
75+
"text/markdown; charset=utf-8",
76+
"text/html; charset=utf-8",
77+
]
78+
79+
headers: "content-encoding": value: ["br"]
80+
81+
metadata: {
82+
ref: {
83+
required: "optional"
84+
type: signed_doc_types.allDocNames
85+
}
86+
87+
revocations: required: "optional"
88+
}
89+
90+
payload: description: """
91+
The Conditions document payload contains the text of the terms and
92+
conditions.
93+
94+
The payload *MUST* be valid according to the content type specified in
95+
the COSE header:
96+
97+
* If `content-type` is `text/markdown; charset=utf-8`, the payload must be
98+
valid Markdown
99+
* If `content-type` is `text/html; charset=utf-8`, the payload must be
100+
valid HTML5
101+
102+
The payload is compressed using Brotli compression (`br` encoding) as
103+
specified in the `content-encoding` header.
104+
105+
The payload content should be human-readable and clearly state:
106+
* The purpose of the conditions
107+
* What users are agreeing to
108+
* Any obligations or restrictions
109+
* Effective dates or version information
110+
* Contact information for questions
111+
"""
112+
113+
signers: {
114+
roles: admin: [
115+
"Brand Admin",
116+
"Campaign Admin",
117+
"Category Admin",
118+
"Contest Admin",
119+
]
120+
121+
update: type: "author"
122+
}
123+
124+
authors: {
125+
"Nathan Bogale": "[email protected]"
126+
"Steven Johnson": "[email protected]"
127+
}
128+
129+
versions: [
130+
{
131+
version: "0.01"
132+
modified: "2025-01-XX"
133+
changes: """
134+
* First Published Version (DRAFT)
135+
"""
136+
},
137+
]
138+
}
139+
}
140+

specs/definitions/signed_docs/docs/generic_parameters.cue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ _parameters_payload_description: """
4747
revocations: required: "optional"
4848

4949
parameters: required: _ | *"yes"
50+
51+
conditions: required: "optional"
5052
}
5153

5254
headers: "content type": value: "application/json"

specs/definitions/signed_docs/metadata.cue

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ _metadataNames: [
8787
"collaborators",
8888
"revocations",
8989
"parameters",
90+
"conditions",
9091
"chain",
9192
]
9293

@@ -275,6 +276,71 @@ _allMetadataNames: or([
275276
"""
276277
}
277278

279+
conditions: {
280+
format: "Document Reference"
281+
description: """
282+
An array of references to Conditions documents that define terms and conditions.
283+
284+
The `conditions` metadata field serves two distinct purposes depending on the document type:
285+
286+
1. **On Parameter Documents** (Brand Parameters, Campaign Parameters, Category Parameters, Contest Parameters):
287+
* Lists the required condition documents for that level of the system hierarchy
288+
* Specifies which terms users must accept when submitting documents at this level
289+
* The field is optional - if not present, no conditions are required at that level
290+
291+
2. **On User-Submitted Documents** (Proposals, Proposal Comments, etc.):
292+
* References all condition documents that the user has accepted
293+
* Must include ALL conditions required by the parameter hierarchy (Brand → Campaign → Category → Contest)
294+
* The act of listing these references and signing the document serves as the user's digital signature and acceptance
295+
* The field is optional when no conditions are required by the parameter hierarchy, but required when conditions are specified
296+
"""
297+
validation: """
298+
**For Parameter Documents:**
299+
300+
* The `conditions` field is optional
301+
* If present, must be an array of valid Conditions document references
302+
* All referenced documents must exist and be of type "Conditions"
303+
* The array must be sorted according to CBOR Deterministic Encoding (4.3.2 Length-First Map Key Ordering)
304+
* All array elements must be unique
305+
306+
**For User-Submitted Documents:**
307+
308+
The validation process for user-submitted documents involves transitive collection of required conditions:
309+
310+
1. Extract the `parameters` reference from the user document
311+
2. Starting from the referenced parameters document, follow the parent chain upward to Brand:
312+
* If the document references Contest Parameters, follow: Contest → (its parent: Brand/Campaign/Category) → Campaign (if parent was Category) → Brand
313+
* If the document references Category Parameters, follow: Category → Campaign → Brand
314+
* If the document references Campaign Parameters, follow: Campaign → Brand
315+
* If the document references Brand Parameters, only Brand is included
316+
3. Collect all `conditions` arrays from each parameter level encountered in the upward chain
317+
4. Union all condition references (removing duplicates based on document ID and version)
318+
5. Sort the unified list according to CBOR Deterministic Encoding
319+
6. Compare the user document's `conditions` array with this unified, sorted list
320+
7. Validation succeeds only if they match exactly
321+
322+
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.
323+
324+
**Validation Rules:**
325+
326+
* The user document's `conditions` array must exactly match the union of all required conditions from the parameter hierarchy
327+
* All referenced Conditions documents must exist and be valid
328+
* All referenced Conditions documents must not be revoked
329+
* The array must be sorted (CBOR deterministic encoding order)
330+
* All array elements must be unique
331+
332+
**Validation Failures:**
333+
334+
The document will be rejected if:
335+
* Missing required conditions (conditions specified in parameter hierarchy but not in user document)
336+
* Includes extra conditions (conditions in user document not in parameter hierarchy)
337+
* Array is not sorted correctly
338+
* Any referenced condition document doesn't exist or is invalid
339+
* Any referenced condition document is revoked
340+
* Array contains duplicate references
341+
"""
342+
}
343+
278344
}
279345

280346
// Note: we make all normally excluded fields optional at the global level, because they are globally optional
@@ -288,6 +354,12 @@ metadata: headers: {
288354
reply: type: signed_doc_types.commentDocNamesList
289355
section: required: "optional"
290356
collaborators: required: "optional"
357+
conditions: {
358+
required: "optional"
359+
format: "Document Reference"
360+
type: ["Conditions"]
361+
multiple: true
362+
}
291363
}
292364

293365
// Preferred display order

0 commit comments

Comments
 (0)