diff --git a/.gitignore b/.gitignore index 9f75a0f579..4950c2b065 100644 --- a/.gitignore +++ b/.gitignore @@ -81,6 +81,9 @@ $RECYCLE.BIN/ !/.vscode/settings.recommended.json !/.vscode/tasks.recommended.json +venv/ +# Python virtual environments + # Dart stuff /pubspec.lock /.dart_tool/**/* diff --git a/.vscode/settings.recommended.json b/.vscode/settings.recommended.json index c152c545fd..c63dff43ce 100644 --- a/.vscode/settings.recommended.json +++ b/.vscode/settings.recommended.json @@ -1,5 +1,5 @@ { - // Recommended `settings.json` configuration + "$comment": "Recommended `settings.json` configuration", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.organizeImports": true, @@ -37,12 +37,20 @@ "rust", "rust/c509-certificate", "rust/cardano-chain-follower", + "rust/catalyst-types", "rust/catalyst-voting", + "rust/immutable-ledger", + "rust/vote-tx-v1", + "rust/vote-tx-v2", + "rust/signed-doc", "rust/cbork", "rust/hermes-ipfs", + "rust/rbac-registration", + "rust/cardano-blockchain-types", "dart", "docs", - "general" + "general", + "deps" ], "conventionalCommits.gitmoji": false, "markdown.extension.toc.unorderedList.marker": "*", diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot index d22921c2f9..b810e40dbb 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot @@ -1,4 +1,4 @@ -digraph "None" { +digraph "All" { rankdir="LR" graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; @@ -121,16 +121,6 @@ digraph "None" { - - - - - - - -
parametersBrand Parameters
- - > @@ -186,16 +176,6 @@ digraph "None" { - - - - - - - -
parametersCampaign Parameters
- - > @@ -437,7 +417,7 @@ digraph "None" { - +
parametersBrand Parameters
Campaign Parameters
Category Parameters
Decision Parameters
@@ -963,10 +943,8 @@ digraph "None" { ]; - "Campaign Parameters":"parameters":e -> "Brand Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Category Parameters":"parameters":e -> "Campaign Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Comment Moderation Action":"ref":e -> "Proposal Comment":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Decision Parameters":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Decision Parameters":"parameters":e -> "Decision Parameters":"title":n [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Proposal":"template":e -> "Proposal Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Proposal":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Comment":"ref":e -> "Proposal":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters.dot index ec4702ddac..854ce68f55 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters.dot @@ -72,38 +72,8 @@ Relationships" > ]; - - "Campaign Parameters" [ - id="Campaign Parameters"; - label=< - - - - - -
- Campaign Parameters -
- > - ]; - } - "Decision Parameters" [ - id="Decision Parameters"; - label=< - - - - - -
- Decision Parameters -
- > - ]; - - "Proposal" [ id="Proposal"; label=< @@ -209,8 +179,6 @@ Relationships" ]; - "Campaign Parameters":"title":e -> "Brand Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Decision Parameters":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Comment":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Comment Meta Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters.dot index f21afdeadf..c6746ece95 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters.dot @@ -18,21 +18,6 @@ Relationships" color=blue penwidth=20 - "Brand Parameters" [ - id="Brand Parameters"; - label=< - - - - - -
- Brand Parameters -
- > - ]; - - "Campaign Parameters" [ id="Campaign Parameters"; label=< @@ -82,31 +67,6 @@ Relationships" - - - - - - - -
parametersBrand Parameters
- - - - - > - ]; - - - "Category Parameters" [ - id="Category Parameters"; - label=< - - - -
- Category Parameters -
> @@ -114,21 +74,6 @@ Relationships" } - "Decision Parameters" [ - id="Decision Parameters"; - label=< - - - - - -
- Decision Parameters -
- > - ]; - - "Proposal" [ id="Proposal"; label=< @@ -234,9 +179,6 @@ Relationships" ]; - "Campaign Parameters":"parameters":e -> "Brand Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Category Parameters":"title":e -> "Campaign Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Decision Parameters":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Comment":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Comment Meta Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters.dot index b6a2aa470a..ff1f5e4b40 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters.dot @@ -18,21 +18,6 @@ Relationships" color=blue penwidth=20 - "Campaign Parameters" [ - id="Campaign Parameters"; - label=< - - - - - -
- Campaign Parameters -
- > - ]; - - "Category Parameters" [ id="Category Parameters"; label=< @@ -82,16 +67,6 @@ Relationships" - - - - - - - -
parametersCampaign Parameters
- - > @@ -99,21 +74,6 @@ Relationships" } - "Decision Parameters" [ - id="Decision Parameters"; - label=< - - - - - -
- Decision Parameters -
- > - ]; - - "Proposal" [ id="Proposal"; label=< @@ -219,8 +179,6 @@ Relationships" ]; - "Category Parameters":"parameters":e -> "Campaign Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Decision Parameters":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Comment":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Comment Meta Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/decision_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/decision_parameters.dot index ff41dcf0f6..eb5faa35e0 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/decision_parameters.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/decision_parameters.dot @@ -13,57 +13,6 @@ Relationships" - subgraph cluster_system_parameters { - label = "System Parameters"; - color=blue - penwidth=20 - - "Brand Parameters" [ - id="Brand Parameters"; - label=< - - - - - -
- Brand Parameters -
- > - ]; - - - "Campaign Parameters" [ - id="Campaign Parameters"; - label=< - - - - - -
- Campaign Parameters -
- > - ]; - - - "Category Parameters" [ - id="Category Parameters"; - label=< - - - - - -
- Category Parameters -
- > - ]; - - } - "Decision Parameters" [ id="Decision Parameters"; label=< @@ -118,7 +67,7 @@ Relationships" - +
parametersBrand Parameters
Campaign Parameters
Category Parameters
Decision Parameters
@@ -129,5 +78,5 @@ Relationships" ]; - "Decision Parameters":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Decision Parameters":"parameters":e -> "Decision Parameters":"title":n [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters.md index 6e74a9b972..95cc328f55 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters.md @@ -2,7 +2,10 @@ ## Description -Parameters which define this brand within the system. +This specification outlines the required definitions for the current features. +The document will be incrementally improved in future iterations as more functionality +and features are added. +This section will be included and updated in future iterations. @@ -112,15 +115,19 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | ### Changelog -#### 0.01 (2025-04-04) +#### v1 (2024-06-07) + +Initial version. Structure aligned with global metadata requirements. + +#### v2 (2025-04-04) -* First Published Version +Updated to include common definitions and examples. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters.md index 40b40909c1..b86067891b 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters.md @@ -2,7 +2,10 @@ ## Description -Parameters which define a Campaign within a Brand in the system. +This specification outlines the required definitions for the current features. +The document will be incrementally improved in future iterations as more functionality +and features are added. +This section will be included and updated in future iterations. @@ -89,24 +92,6 @@ The first version of the document must set [`ver`](../metadata.md#ver) == [`id`] The document version must always be >= the document ID. -### [`parameters`](../metadata.md#parameters) - - -| Parameter | Value | -| --- | --- | -| Required | yes | -| Format | [Document Reference](../metadata.md#document-reference) | -| Valid References | [Brand Parameters](brand_parameters.md) | - -A reference to the Parameters Document this document lies under. - -#### [`parameters`](../metadata.md#parameters) Validation - -In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields: - -* Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the -[`parameters`](../metadata.md#parameters) of the referencing document. - ## Payload This specification outlines the required definitions for the current features. @@ -130,19 +115,15 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | ### Changelog -#### 0.01 (2025-04-04) - -* First Published Version - -#### 0.03 (2025-05-05) +#### v1 (2024-06-07) -* Use generalized parameters. +Initial version. Structure aligned with global metadata requirements. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters.md index 07f5156139..339da8e194 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters.md @@ -2,7 +2,10 @@ ## Description -Parameters which define a Category withing a Campaign under a Brand in the system. +This specification outlines the required definitions for the current features. +The document will be incrementally improved in future iterations as more functionality +and features are added. +This section will be included and updated in future iterations. @@ -89,24 +92,6 @@ The first version of the document must set [`ver`](../metadata.md#ver) == [`id`] The document version must always be >= the document ID. -### [`parameters`](../metadata.md#parameters) - - -| Parameter | Value | -| --- | --- | -| Required | yes | -| Format | [Document Reference](../metadata.md#document-reference) | -| Valid References | [Campaign Parameters](campaign_parameters.md) | - -A reference to the Parameters Document this document lies under. - -#### [`parameters`](../metadata.md#parameters) Validation - -In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields: - -* Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the -[`parameters`](../metadata.md#parameters) of the referencing document. - ## Payload This specification outlines the required definitions for the current features. @@ -130,19 +115,15 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | ### Changelog -#### 0.01 (2025-04-04) - -* First Published Version - -#### 0.03 (2025-05-05) +#### v1 (2024-06-07) -* Use generalized parameters. +Initial version. Structure aligned with global metadata requirements. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/comment_moderation_action.md b/docs/src/architecture/08_concepts/signed_doc/docs/comment_moderation_action.md index 5b9907ca1f..e8bd4caf85 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/comment_moderation_action.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/comment_moderation_action.md @@ -153,7 +153,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/decision_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/decision_parameters.md index 95e049ecf2..5e50e1dc92 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/decision_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/decision_parameters.md @@ -2,7 +2,7 @@ ## Description -Parameters which define an individual voting event. + Parameters which define an individual voting event. @@ -96,9 +96,7 @@ The document version must always be >= the document ID. | --- | --- | | Required | yes | | Format | [Document Reference](../metadata.md#document-reference) | -| Valid References | [Brand Parameters](brand_parameters.md) | -| | [Campaign Parameters](campaign_parameters.md) | -| | [Category Parameters](category_parameters.md) | +| Valid References | [Decision Parameters](decision_parameters.md) | A reference to the Parameters Document this document lies under. @@ -111,10 +109,32 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Payload -This specification outlines the required definitions for the current features. -The document will be incrementally improved in future iterations as more functionality -and features are added. -This section will be included and updated in future iterations. +Payload for Decision Parameters document. + +### Schema + + +??? abstract + + Payload for Decision Parameters document. + + ```json + {} + ``` + + + +### Example + +??? example "Example: Final Proposal Submission" + + This document indicates the linked proposal is final and requested to proceed for further consideration. + + ```json + {} + ``` + + ## Signers @@ -132,7 +152,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-06-06 | | Authors | Alex Pozhylenkov | | | Steven Johnson | @@ -140,11 +160,15 @@ New versions of this document may be published by: #### 0.01 (2025-04-04) -* First Published Version + * First Published Version #### 0.03 (2025-05-05) -* Use generalized parameters. + * Use generalized parameters. + +#### 0.04 (2025-06-06) + + * Added brand reference to decision parameters. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md index c11ad6354e..70bffb1365 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md @@ -226,7 +226,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment.md index 212b50e7b4..984dd48cf3 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment.md @@ -261,7 +261,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_meta_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_meta_template.md index 305e9d497f..73280ae4f7 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_meta_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_meta_template.md @@ -141,7 +141,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md index 91c7b241f9..ff64f26852 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md @@ -154,7 +154,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md index 9ff14e8810..dd91bf8185 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md @@ -141,7 +141,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_moderation_action.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_moderation_action.md index b8236d4597..8792ac4368 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_moderation_action.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_moderation_action.md @@ -153,7 +153,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_submission_action.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_submission_action.md index 68d7f89c2e..e15b76b4be 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_submission_action.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_submission_action.md @@ -199,49 +199,106 @@ States: `hide` is only actioned if sent by the author, for a collaborator it identified that they do not wish to be listed as a `collaborator`. -Schema : - -```json -{ - "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json", - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "definitions": { - "action": { - "description": "The action being performed on the Proposal.", - "enum": [ - "final", - "draft", - "hide" +### Schema + + +??? abstract + + The kind of action is controlled by this payload. + The Payload is a [JSON][RFC8259] Document, and must conform to this schema. + + States: + + * `final` : All collaborators must publish a `final` status for the proposal to be `final`. + * `draft` : Reverses the previous `final` state for a signer and accepts collaborator status to a document. + * `hide` : Requests the proposal be hidden (not final, but a hidden draft). + `hide` is only actioned if sent by the author, + for a collaborator it identified that they do not wish to be listed as a `collaborator`. + + ```json + { + "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "definitions": { + "action": { + "description": "The action being performed on the Proposal.", + "enum": [ + "final", + "draft", + "hide" + ], + "type": "string" + } + }, + "description": "Structure of the payload of a Proposal Submission Action.", + "maintainers": [ + { + "name": "Catalyst Team", + "url": "https://projectcatalyst.io/" + } ], - "type": "string" + "properties": { + "action": { + "$ref": "#/definitions/action" + } + }, + "required": [ + "action" + ], + "title": "Proposal Submission Action Payload Schema", + "type": "object", + "x-changelog": { + "2025-03-01": [ + "First Version Created." + ] + } + } + ``` + + + +### Examples + +??? example "Example: Final Proposal Submission" + + This document indicates the linked proposal is final and requested to proceed for further consideration. + + ```json + { + "action": "final" } - }, - "description": "Structure of the payload of a Proposal Submission Action.", - "maintainers": [ + ``` + + + +??? example "Example: Draft Proposal Submission" + + This document indicates the linked proposal is no longer final and should not proceed for further consideration. + It is also used by collaborators to accept that they are a collaborator on a document. + + ```json { - "name": "Catalyst Team", - "url": "https://projectcatalyst.io/" + "action": "draft" } - ], - "properties": { - "action": { - "$ref": "#/definitions/action" + ``` + + + +??? example "Example: Hidden Proposal Submission" + + If submitted by the proposal author the document is hidden, it is still public but not shown as + a proposal being drafted. + If submitted by a collaborator, that collaborator is declaring they do not wish to be listed as + a collaborator on the proposal. + + ```json + { + "action": "hide" } - }, - "required": [ - "action" - ], - "title": "Proposal Submission Action Payload Schema", - "type": "object", - "x-changelog": { - "2025-03-01": [ - "First Version Created." - ] - } -} -``` - + ``` + + ## Signers @@ -260,7 +317,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md index b01b6eb41c..53ac87aff1 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md @@ -158,7 +158,7 @@ New versions of this document may be published by: | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/metadata.md b/docs/src/architecture/08_concepts/signed_doc/metadata.md index 7b6fdc2e13..8daa80ac97 100644 --- a/docs/src/architecture/08_concepts/signed_doc/metadata.md +++ b/docs/src/architecture/08_concepts/signed_doc/metadata.md @@ -348,7 +348,7 @@ In addition to the validation performed for [Document Reference](metadata.md#doc | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/spec.md b/docs/src/architecture/08_concepts/signed_doc/spec.md index f2cc3a81bb..222eff96a0 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec.md +++ b/docs/src/architecture/08_concepts/signed_doc/spec.md @@ -25,6 +25,40 @@ Catalyst Signed Documents are based on [COSE][RFC9052]. Specifically, the [COSE Sign][RFC9052-CoseSign] format is used. This allows one or more signatures to be attached to the same document. +While every Catalyst Signed Document is a valid [COSE Sign][RFC9052-CoseSign] format document, +not every [COSE Sign][RFC9052-CoseSign] format document is a valid Catalyst Signed Document. +The following restrictions apply: + +### Unprotected Headers are not permitted + +It is a requirement that any document that contains exactly the same data, must produce the same +catalyst signed document. +This means that unprotected headers, which do not form part of the data protected by +the signature are not permitted. +Any document which contains any unprotected headers is not a valid Catalyst Signed Document, +even though it may be a valid [COSE Sign][RFC9052-CoseSign] formatted document. + +### Only defined metadata and [COSE][RFC9052] Headers are allowed + +Each document type, defines a set of metadata and the [COSE][RFC9052] Headers which are allowed in that document type. +Even if the Catalyst Signed document metadata exists in this specification, IF it is not defined as +a valid metadata or [COSE][RFC9052] Header field for that particular document it may not be present. +Unexpected but otherwise valid Metadata or [COSE][RFC9052] Header fields invalidate the Catalyst Signed Document. + +### No undefined metadata or unused [COSE][RFC9052] Headers may be present + +[COSE][RFC9052] Header Fields which are defined by the [COSE][RFC9052] Specification, but are NOT defined as part of a +Catalyst Signed Document may not be present. +Any such [COSE][RFC9052] Header Fields present in the document render it an invalid Catalyst Signed Document. + +Any metadata field that is not defined in this specification may not be present in any protected header. +Unrecognized metadata fields in a document render it an invalid Catalyst Signed Document. + +### [CBOR Deterministic Encoding][CBOR-LFD-ENCODING] MUST be used + +The Catalyst Signed Document **MUST** be encoded using [CBOR Deterministic Encoding][CBOR-LFD-ENCODING]. +The "length-first core deterministic encoding requirements" variant of deterministic encoding *MUST* be used. + ### Signed Document [CDDL][RFC8610] Definition @@ -120,7 +154,7 @@ used to sign the protected portion of the document. | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | @@ -138,6 +172,15 @@ used to sign the protected portion of the document. * Use generalized parameters. +#### 0.04 (2025-05-30) + +* Improve and make document serialization more repeatable, and stricter. +* TODO: Define Systems parameters +* TODO: Define DReps documents. +* TODO: Define Proposer Profiles. +* TODO: Define Role 0 Profile. + +[CBOR-LFD-ENCODING]: https://www.rfc-editor.org/rfc/rfc8949.html#section-4.2.3 [application/schema+json]: https://datatracker.ietf.org/doc/draft-bhutton-json-schema/ [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [application/cbor]: https://www.iana.org/assignments/media-types/application/cbor diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index c9b878b78e..35c823f1a5 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -55,7 +55,7 @@ All Defined Document Types | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-05-05 | +| Modified | 2025-05-30 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/gen/doc_generator.py b/specs/gen_docs/gen/doc_generator.py index f392378355..aebfc401ba 100644 --- a/specs/gen_docs/gen/doc_generator.py +++ b/specs/gen_docs/gen/doc_generator.py @@ -170,7 +170,7 @@ def add_reference_links(self) -> None: actual_link_names = self._spec.link_names() - actual_links_used = {} + actual_links_used: dict[str, str] = {} for link_name in actual_link_names: esc_link_name = re.escape(link_name) link_name_regex = f"(^|\\s)({esc_link_name})(\\.|\\s|$)" @@ -190,7 +190,7 @@ def add_reference_links(self) -> None: for link, actual in actual_links_used.items(): self._filedata += f"\n[{link}]: {actual}" - def remove_tabs(self, tabstop: int = 4) -> str: + def remove_tabs(self, tabstop: int = 4) -> None: """Replace tabs in the input text with spaces so that the text aligns on tab stops. Args: @@ -343,7 +343,7 @@ def file_name(self) -> str: """Return the files name.""" return self._filename - def file_path(self, relative_doc: typing.Self | None = None) -> Path: + def file_path(self, relative_doc: "DocGenerator | None" = None) -> Path: """Return a path to the file.""" if relative_doc is not None: relative_path = relative_doc.file_path().parent diff --git a/specs/gen_docs/gen/doc_relationship_diagrams.py b/specs/gen_docs/gen/doc_relationship_diagrams.py index b7a0d68b2b..7f3c74fc3e 100644 --- a/specs/gen_docs/gen/doc_relationship_diagrams.py +++ b/specs/gen_docs/gen/doc_relationship_diagrams.py @@ -51,7 +51,7 @@ def generate(self) -> bool: # noqa: C901 file_title = textwrap.fill(f"{file_id} Document Relationships", width=30) dot_file = DotFile( - self._document_name, file_title, depth=self._depth, title_size=150 if self._document_name is None else 50 + file_id, file_title, depth=self._depth, title_size=150 if self._document_name is None else 50 ) all_dst_refs: list[str] = [] @@ -66,7 +66,7 @@ def generate(self) -> bool: # noqa: C901 doc_data = self._spec.get_document(doc) # Add content type explicitely to table. - doc_table.add_row(TableRow(name="content type", value=doc_data.headers["content type"].value)) + doc_table.add_row(TableRow(name="content type", value=doc_data.content_type)) # Add all used Metadata to table. for meta in self._spec.all_headers(HeaderType.METADATA): diff --git a/specs/gen_docs/gen/docs_page_md.py b/specs/gen_docs/gen/docs_page_md.py index 970f2d4836..b07c17f440 100644 --- a/specs/gen_docs/gen/docs_page_md.py +++ b/specs/gen_docs/gen/docs_page_md.py @@ -1,11 +1,8 @@ """Generate the individual pages docs/.md file.""" import argparse -import json import typing -from pydantic import HttpUrl - from gen.doc_generator import DocGenerator from gen.doc_relationship_diagrams import DocRelationshipFile from spec.signed_doc import SignedDoc @@ -62,24 +59,7 @@ def document_payload(self) -> str: if self._doc.payload is None: return self.TODO_MSG - payload_docs = self._doc.payload.description + "\n" - - schema = self._doc.payload.doc_schema - if schema is not None: - if isinstance(schema, HttpUrl): - if schema == "https://json-schema.org/draft-07/schema": - payload_docs += "\n**Must be a valid JSON Schema Draft 7 document.**" - else: - payload_docs += f"\nMust be a valid according to <{schema}>." - else: - payload_docs += f"""\nSchema : - -```json -{json.dumps(schema, indent=2, sort_keys=True)} -``` - -""" - return payload_docs.strip() + return f"{self._doc.payload}" def document_signers(self) -> str: """Generate documentation about who may sign this documents.""" diff --git a/specs/gen_docs/gen/graphviz_doc_diagram.py b/specs/gen_docs/gen/graphviz_doc_diagram.py index 3c2ec65b70..2c1d78ce06 100644 --- a/specs/gen_docs/gen/graphviz_doc_diagram.py +++ b/specs/gen_docs/gen/graphviz_doc_diagram.py @@ -71,6 +71,11 @@ class TableRow(BaseModel): model_config = ConfigDict(extra="forbid") + @classmethod + def default_list(cls) -> list["TableRow"]: + """Return a default list of this class.""" + return [] + def generate(self, bgcolor: str) -> str: """Generate a single row of the table.""" value = self.value @@ -171,6 +176,7 @@ def from_doc_cluster(cls, cluster: DocCluster | None) -> "Cluster | None": return None return cls(name=cluster.name) + @property def label(self) -> str: """Transform the name into a label.""" return "cluster_" + self.name.lower().replace(" ", "_").replace("-", "_") @@ -178,7 +184,7 @@ def label(self) -> str: def start(self) -> str: """Start a new cluster.""" return f""" -subgraph {self.label()} {{ +subgraph {self.label} {{ label = "{self.name}"; color=blue penwidth=20 @@ -188,7 +194,7 @@ def end(self) -> str: """End the cluster.""" return "}\n" - def __eq__(self, other: "Cluster") -> bool: + def __eq__(self, other: object) -> bool: """Eq.""" if not isinstance(other, Cluster): # don't attempt to compare against unrelated types @@ -203,7 +209,7 @@ class DotSignedDoc(BaseModel): title_port: str = Field(default="title") title_href: str | None = Field(default=None) theme: TableTheme = Field(default_factory=TableTheme) - rows: list[TableRow] = Field(default_factory=list) + rows: list[TableRow] = Field(default_factory=TableRow.default_list) cluster: Cluster | None = Field(default=None) model_config = ConfigDict(extra="forbid") @@ -296,6 +302,11 @@ def is_cluster(self) -> bool: """Is the link to a cluster.""" return isinstance(self.port, Cluster) + @property + def port_label(self) -> str | None: + """Get label of the port.""" + return self.port.label if self.is_cluster else None # type: ignore # noqa: PGH003 + def __str__(self) -> str: """Str.""" name = f'"{self.id}"' @@ -305,7 +316,7 @@ def __str__(self) -> str: name += f":{self.dir}" return name - def __eq__(self, other: "DotLinkEnd") -> bool: + def __eq__(self, other: object) -> bool: """Eq.""" if not isinstance(other, DotLinkEnd): # don't attempt to compare against unrelated types @@ -335,12 +346,10 @@ def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 super().model_post_init(context) # Add cluster parameters to the theme. - if self.src.is_cluster: - self.theme.ltail = self.src.port.label() - if self.dst.is_cluster: - self.theme.lhead = self.dst.port.label() + self.theme.ltail = self.src.port_label + self.theme.lhead = self.dst.port_label - def __eq__(self, other: "DotLink") -> bool: + def __eq__(self, other: object) -> bool: """Eq.""" if not isinstance(other, DotLink): # don't attempt to compare against unrelated types @@ -367,20 +376,20 @@ def __init__(self, file_id: str, title: str, depth: int = 0, title_size: int = 1 self.title = title self.title_size = title_size self.rankdir = "LR" - self.graph = { + self.graph: dict[str, str | int] = { "fontname": DEFAULT_FONT_NAME, "fontsize": DEFAULT_FONT_SIZE, "fontcolor": DEFAULT_FONT_COLOR, "bgcolor": "white", } - self.node = { + self.node: dict[str, str | int] = { "penwidth": 0, "margin": 0, "fontname": DEFAULT_FONT_NAME, "fontsize": DEFAULT_FONT_SIZE, "fontcolor": DEFAULT_FONT_COLOR, } - self.edge = { + self.edge: dict[str, str | int] = { "fontname": DEFAULT_FONT_NAME, "fontsize": DEFAULT_FONT_SIZE, "fontcolor": "red", @@ -401,7 +410,7 @@ def add_table(self, table: DotSignedDoc) -> None: cluster_name = None if table.cluster is not None: cluster_name = table.cluster.name - if cluster_name is not None and cluster_name not in self.clusters: + if cluster_name is not None and cluster_name not in self.clusters and table.cluster is not None: self.clusters[cluster_name] = table.cluster if cluster_name not in self.tables: self.tables[cluster_name] = {} @@ -438,9 +447,9 @@ def clustered_tables(self) -> str: def __str__(self) -> str: """Generate the DOT file.""" - def defaults(name: str, settings: dict) -> str: + def defaults(name: str, settings: dict[str, str | int]) -> str: """Expand the defaults.""" - defaults = [] + defaults: list[str] = [] for default, value in settings.items(): defaults.append(f'{default}="{value}"') return f"{name} [{', '.join(defaults)}];" diff --git a/specs/gen_docs/gen/spec_md.py b/specs/gen_docs/gen/spec_md.py index bd8638c8db..f70b4345ac 100644 --- a/specs/gen_docs/gen/spec_md.py +++ b/specs/gen_docs/gen/spec_md.py @@ -23,7 +23,7 @@ def header_parameter_doc(self, header: str, header_type: HeaderType) -> str: if not isinstance(label, str): custom_header = "" header_format = options["format"] - header_value = options.get("value", None) + header_value: str | list[str] | None = options.get("value", None) header_format_display = f"{header_format}" if isinstance(header_value, list) and len(header_value) > 0: header_format_display += "\n * Supported Values:" @@ -93,6 +93,40 @@ def generate(self) -> bool: Specifically, the COSE Sign format is used. This allows one or more signatures to be attached to the same document. +While every Catalyst Signed Document is a valid COSE Sign format document, +not every COSE Sign format document is a valid Catalyst Signed Document. +The following restrictions apply: + +### Unprotected Headers are not permitted + +It is a requirement that any document that contains exactly the same data, must produce the same +catalyst signed document. +This means that unprotected headers, which do not form part of the data protected by +the signature are not permitted. +Any document which contains any unprotected headers is not a valid Catalyst Signed Document, +even though it may be a valid COSE Sign formatted document. + +### Only defined metadata and COSE Headers are allowed + +Each document type, defines a set of metadata and the COSE Headers which are allowed in that document type. +Even if the Catalyst Signed document metadata exists in this specification, IF it is not defined as +a valid metadata or COSE Header field for that particular document it may not be present. +Unexpected but otherwise valid Metadata or COSE Header fields invalidate the Catalyst Signed Document. + +### No undefined metadata or unused COSE Headers may be present + +COSE Header Fields which are defined by the COSE Specification, but are NOT defined as part of a +Catalyst Signed Document may not be present. +Any such COSE Header Fields present in the document render it an invalid Catalyst Signed Document. + +Any metadata field that is not defined in this specification may not be present in any protected header. +Unrecognized metadata fields in a document render it an invalid Catalyst Signed Document. + +### CBOR Deterministic Encoding MUST be used + +The Catalyst Signed Document **MUST** be encoded using CBOR Deterministic Encoding. +The "length-first core deterministic encoding requirements" variant of deterministic encoding *MUST* be used. + ### Signed Document CDDL Definition {signed_doc_cddl.markdown_reference(relative_doc=self)} diff --git a/specs/gen_docs/main.py b/specs/gen_docs/main.py index 521f49338f..eb344ccbde 100755 --- a/specs/gen_docs/main.py +++ b/specs/gen_docs/main.py @@ -1,4 +1,4 @@ -#!/usr/bin/env -S uv run +#!/usr/bin/env python3 """Autogenerate Documentation Pages from the specification.""" import argparse @@ -77,6 +77,10 @@ def main(args: argparse.Namespace) -> None: good &= MetadataMd(args, spec).save_or_validate() good &= IndividualDocMd.save_or_validate_all(args, spec) + # Add generation for Brand, Campaign, Category, and Decision documents + for doc_name in ["Brand Parameters", "Campaign Parameters", "Category Parameters", "Decision Parameters"]: + good &= IndividualDocMd(args, spec, doc_name).save_or_validate() + if not good: rich.print("File Comparisons Failed, Documentation is not current.") sys.exit(1) diff --git a/specs/gen_docs/pyproject.toml b/specs/gen_docs/pyproject.toml index 6626530ffb..4046227b91 100644 --- a/specs/gen_docs/pyproject.toml +++ b/specs/gen_docs/pyproject.toml @@ -3,8 +3,9 @@ name = "gen-docs" version = "0.1.0" description = "Generate Signed Document documentation files." readme = "README.md" -requires-python = ">=3.13" +requires-python = ">=3.10" dependencies = [ + "jsonschema[format]>=4.23.0", "pydantic>=2.11.4", "pydot>=3.0.4", "rich>=14.0.0", diff --git a/specs/gen_docs/spec/document.py b/specs/gen_docs/spec/document.py index 1f9e8a9d39..c9c5414347 100644 --- a/specs/gen_docs/spec/document.py +++ b/specs/gen_docs/spec/document.py @@ -20,6 +20,11 @@ class DocumentBusinessLogic(BaseModel): model_config = ConfigDict(extra="forbid") +def empty_string_list() -> list[str]: + """Get an empty string list.""" + return [] + + class Document(BaseModel): """Document Data Definition.""" @@ -38,8 +43,8 @@ class Document(BaseModel): versions: list[ChangeLogEntry] _name: str | None = PrivateAttr(default=None) - _all_refs: list[str] = PrivateAttr(default_factory=list) - _refed_by: list[str] = PrivateAttr(default_factory=list) + _all_refs: list[str] = PrivateAttr(default_factory=empty_string_list) + _refed_by: list[str] = PrivateAttr(default_factory=empty_string_list) doc_name: str | None = Field(default=None) # Set when wwe get a document @@ -74,11 +79,21 @@ def all_references(self) -> list[str]: return self._all_refs @property - def name(self) -> list[str]: + def name(self) -> str: """Get name of this document.""" - return self._name + return self._name if self._name is not None else "Unknown" @property def all_docs_referencing(self) -> list[str]: """Get name of all documents which reference this document.""" return self._refed_by + + @property + def content_type(self) -> str | list[str]: + """Get document content type.""" + content_type = self.headers.get("content type") + if content_type is not None: + content_type = content_type.value + if content_type is None: + content_type = "Undefined" + return content_type diff --git a/specs/gen_docs/spec/payload.py b/specs/gen_docs/spec/payload.py index 732682508c..3caa4efdc0 100644 --- a/specs/gen_docs/spec/payload.py +++ b/specs/gen_docs/spec/payload.py @@ -1,14 +1,122 @@ """Payload Specification.""" +import json +import textwrap +import urllib +import urllib.request from typing import Any +import jsonschema +import rich from pydantic import BaseModel, ConfigDict, Field, HttpUrl +class PayloadExample(BaseModel): + """An Example of the payload.""" + + title: str + description: str + example: dict[str, Any] + + model_config = ConfigDict(extra="forbid") + + @classmethod + def default(cls) -> list["PayloadExample"]: + """Return Default list.""" + return [] + + def __str__(self) -> str: + """Get the example properly formatted as markdown.""" + example = json.dumps(self.example, indent=2, sort_keys=True) + textwrap.indent(example, " ") + + return f""" + + +??? example "Example: {self.title}" + +{textwrap.indent(self.description, " ")} + + ```json +{textwrap.indent(example, " ")} + ``` + + +""".strip() + + +class SchemaValidationError(Exception): + """Something is wrong with payload schema validation.""" + + class Payload(BaseModel): """Payload Deserialized Specification.""" description: str doc_schema: HttpUrl | dict[str, Any] | None = Field(default=None, alias="schema") + examples: list[PayloadExample] = Field(default_factory=PayloadExample.default) model_config = ConfigDict(extra="forbid") + + def model_post_init(self, context: Any) -> None: # noqa: ANN401 + """Validate the examples against the schema.""" + schema = None + validator = None + if isinstance(self.doc_schema, HttpUrl): + if f"{self.doc_schema}" == "https://json-schema.org/draft-07/schema": + schema = jsonschema.Draft7Validator.META_SCHEMA + else: + rich.print(f"Downloading Schema from: {self.doc_schema}") + with urllib.request.urlopen(f"{self.doc_schema}") as response: # noqa: S310 + schema = json.loads(response.read()) + elif isinstance(self.doc_schema, dict): + schema = self.doc_schema + + if schema is not None: + # Check that its valid jsonschema Draft 7. + jsonschema.Draft7Validator.check_schema(schema) + validator = jsonschema.Draft7Validator(schema, format_checker=jsonschema.draft7_format_checker) + + for example in self.examples: + if validator is None: + msg = "No schema to validate payload examples." + raise SchemaValidationError(msg) + validator.validate(instance=example.example) # type: ignore # noqa: PGH003 + + return super().model_post_init(context) + + def __str__(self) -> str: + """Get the examples properly formatted as markdown.""" + docs = self.description + "\n" + + schema = self.doc_schema + if schema is not None: + if isinstance(schema, HttpUrl): + if schema == "https://json-schema.org/draft-07/schema": + docs += "\n**Must be a valid JSON Schema Draft 7 document.**" + else: + docs += f"\nMust be a valid according to <{schema}>." + else: + docs += f"""\n### Schema + + +??? abstract + +{textwrap.indent(self.description, " ")} + + ```json +{textwrap.indent(json.dumps(schema, indent=2, sort_keys=True), " ")} + ``` + + +""" + + if len(self.examples) > 0: + docs += "\n### Example" + if len(self.examples) >= 2: # noqa: PLR2004 + docs += "s" + docs += "\n" + for example in self.examples: + docs += f"{example}\n" + + return docs.strip() diff --git a/specs/gen_docs/spec/signed_doc.py b/specs/gen_docs/spec/signed_doc.py index e9f832b361..ad1ae1d771 100644 --- a/specs/gen_docs/spec/signed_doc.py +++ b/specs/gen_docs/spec/signed_doc.py @@ -32,17 +32,17 @@ class HeaderType(Enum): HEADERS: dict[str, dict[str, str]] = { - HeaderType.DOCUMENT: { + HeaderType.DOCUMENT.name: { "headers": "cose_headers", "order": "cose_headers_order", "format": "coseHeaderFormats", }, - HeaderType.SIGNATURE: { + HeaderType.SIGNATURE.name: { "headers": "cose_signature_headers", "order": "cose_signature_headers_order", "format": "coseHeaderFormats", }, - HeaderType.METADATA: { + HeaderType.METADATA.name: { "headers": "metadata", "order": "metadata_order", "format": "metadataFormats", @@ -80,7 +80,7 @@ class SignedDoc(BaseModel): def load(cls, spec_file: str) -> typing.Self: """Initialize the Signed Document Specification.""" with Path(spec_file).open("r") as f: - data: dict = json.load(f) + data: dict[str, typing.Any] = json.load(f) doc = cls(**data) doc._data = data doc._file = spec_file @@ -121,19 +121,19 @@ def doc_in_cluster_name(self, doc_name: str) -> str | None: return cluster.name return None - def data(self) -> dict: + def data(self) -> dict[str, typing.Any]: """Return the raw spec data.""" return self._data def document_names(self) -> list[str]: """Get all documents.""" - return self.docs.keys() + return list(self.docs.keys()) def format_names(self, header_type: HeaderType) -> list[str]: """Get a list of all metadata format names defined.""" _, _, formats = self.headers_and_order(header_type=header_type) - metadata_formats: dict = self._data[formats] - return metadata_formats.keys() + metadata_formats: dict[str, typing.Any] = self._data[formats] + return list(metadata_formats.keys()) def link_name_aka(self, link_name: str) -> str | None: """Get a Link AKA for a link name, or None if it doesn't exist.""" @@ -151,9 +151,9 @@ def link_names(self) -> list[str]: def link_for_link_name(self, link_name: str) -> str: """Get a link for a link name.""" - return self.documentation_links[link_name] + return f"{self.documentation_links[link_name]}" - def header(self, header: str, header_type: HeaderType = HeaderType.DOCUMENT) -> dict: + def header(self, header: str, header_type: HeaderType = HeaderType.DOCUMENT) -> dict[str, typing.Any]: """Get Cose header definition.""" headers, _, _ = self.headers_and_order(header_type) return headers[header] @@ -166,14 +166,14 @@ def encoding_type_description(self, encoding_type: str) -> str: """Get a description for a known content type.""" return self.encoding_types[encoding_type].description - def headers_and_order(self, header_type: HeaderType) -> tuple[dict, list[str], str]: + def headers_and_order(self, header_type: HeaderType) -> tuple[dict[str, typing.Any], list[str], str]: """Get headers and their ordering for a header_type.""" - headers = HEADERS[header_type]["headers"] - header_order = HEADERS[header_type]["order"] - formats = HEADERS[header_type]["format"] + headers_key = HEADERS[header_type.name]["headers"] + header_order_key = HEADERS[header_type.name]["order"] + formats = HEADERS[header_type.name]["format"] - headers: dict = self._data[headers] - header_order: list[str] = self._data.get(header_order, []) + headers: dict[str, typing.Any] = self._data[headers_key] + header_order: list[str] = self._data.get(header_order_key, []) # Make sure unordered headers get included in the documentation. for header in headers: @@ -187,7 +187,7 @@ def all_headers(self, header_type: HeaderType = HeaderType.DOCUMENT) -> list[str _, header_order, _ = self.headers_and_order(header_type) return header_order - def cddl_type_for_metadata(self, name: str | None, header_type: str) -> str: + def cddl_type_for_metadata(self, name: str, header_type: HeaderType) -> str: """Get the CDDL type for a given Metadata field.""" headers, _, formats = self.headers_and_order(header_type) @@ -198,19 +198,23 @@ def cddl_type_for_metadata(self, name: str | None, header_type: str) -> str: cddl_def = self._data[formats].get(cddl_def) if cddl_def is not None: cddl_def = cddl_def.get("cddl") + if cddl_def is None: + cddl_def = "Unknown" return cddl_def - def cddl_def(self, name: str) -> dict | None: # noqa: C901 + def cddl_def(self, name: str) -> dict[str, typing.Any] | None: # noqa: C901 """Get a cddl definition by name.""" - def synthetic_headers(defs: dict, header_type: HeaderType = HeaderType.METADATA) -> dict: + def synthetic_headers( # noqa: C901 + defs: dict[str, typing.Any], header_type: HeaderType = HeaderType.METADATA + ) -> dict[str, str]: """Generate a synthetic cddl def for this type. Needs to be generated from Metadata definitions. """ cddl_def = "" defs["requires"] = [] - exclusives = [] + exclusives: list[str] = [] headers, header_names, _ = self.headers_and_order(header_type) @@ -222,19 +226,22 @@ def synthetic_headers(defs: dict, header_type: HeaderType = HeaderType.METADATA) if exclusive is not None: exclusive.append(header) exclusive.sort() - if exclusive not in exclusives: - exclusives.append(exclusive) + for excl in exclusive: + if excl not in exclusives: + exclusives.append(excl) else: + requires: list[str] = defs["requires"] cddl_type = self.cddl_type_for_metadata(header, header_type) field_name = header_data.get("coseLabel", header) if isinstance(field_name, str): field_name = f'"{field_name}"' cddl_def += f"{optional}{field_name} => {cddl_type}\n" - if cddl_type not in defs["requires"]: - defs["requires"].append(cddl_type) + if cddl_type not in requires: + requires.append(cddl_type) + defs["requires"] = requires for exclusive_set in exclusives: # Exclusive sets are never required - exclusive_fields = [] + exclusive_fields: list[str] = [] for entry in exclusive_set: cddl_type = self.cddl_type_for_metadata(entry, header_type) field_name = headers[entry].get("coseLabel", entry) diff --git a/specs/gen_docs/uv.lock b/specs/gen_docs/uv.lock index 5a05c6644e..06aaec055a 100644 --- a/specs/gen_docs/uv.lock +++ b/specs/gen_docs/uv.lock @@ -6,9 +6,40 @@ requires-python = ">=3.13" name = "annotated-types" version = "0.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload_time = "2024-05-20T21:33:25.928Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload_time = "2024-05-20T21:33:24.1Z" }, + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "arrow" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "types-python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2e/00/0f6e8fcdb23ea632c866620cc872729ff43ed91d284c866b515c6342b173/arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85", size = 131960, upload-time = "2023-09-30T22:11:18.25Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/ed/e97229a566617f2ae958a6b13e7cc0f585470eac730a73e9e82c32a3cdd2/arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80", size = 66419, upload-time = "2023-09-30T22:11:16.072Z" }, +] + +[[package]] +name = "attrs" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, +] + +[[package]] +name = "fqdn" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, ] [[package]] @@ -16,6 +47,7 @@ name = "gen-docs" version = "0.1.0" source = { virtual = "." } dependencies = [ + { name = "jsonschema", extra = ["format"] }, { name = "pydantic" }, { name = "pydot" }, { name = "rich" }, @@ -24,12 +56,82 @@ dependencies = [ [package.metadata] requires-dist = [ + { name = "jsonschema", extras = ["format"], specifier = ">=4.23.0" }, { name = "pydantic", specifier = ">=2.11.4" }, { name = "pydot", specifier = ">=3.0.4" }, { name = "rich", specifier = ">=14.0.0" }, { name = "rich-argparse", specifier = ">=1.7.0" }, ] +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "isoduration" +version = "20.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "arrow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.23.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/2e/03362ee4034a4c917f697890ccd4aec0800ccf9ded7f511971c75451deec/jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", size = 325778, upload-time = "2024-07-08T18:40:05.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566", size = 88462, upload-time = "2024-07-08T18:40:00.165Z" }, +] + +[package.optional-dependencies] +format = [ + { name = "fqdn" }, + { name = "idna" }, + { name = "isoduration" }, + { name = "jsonpointer" }, + { name = "rfc3339-validator" }, + { name = "rfc3987" }, + { name = "uri-template" }, + { name = "webcolors" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bf/ce/46fbd9c8119cfc3581ee5643ea49464d168028cfb5caff5fc0596d0cf914/jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608", size = 15513, upload-time = "2025-04-23T12:34:07.418Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/0e/b27cdbaccf30b890c40ed1da9fd4a3593a5cf94dae54fb34f8a4b74fcd3f/jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", size = 18437, upload-time = "2025-04-23T12:34:05.422Z" }, +] + [[package]] name = "markdown-it-py" version = "3.0.0" @@ -37,18 +139,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload_time = "2023-06-03T06:41:14.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload_time = "2023-06-03T06:41:11.019Z" }, + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, ] [[package]] name = "mdurl" version = "0.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload_time = "2022-08-14T12:40:10.846Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload_time = "2022-08-14T12:40:09.779Z" }, + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] [[package]] @@ -61,9 +163,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload_time = "2025-04-29T20:38:55.02Z" } +sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload-time = "2025-04-29T20:38:55.02Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload_time = "2025-04-29T20:38:52.724Z" }, + { url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload-time = "2025-04-29T20:38:52.724Z" }, ] [[package]] @@ -73,25 +175,25 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload_time = "2025-04-23T18:33:52.104Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload_time = "2025-04-23T18:31:53.175Z" }, - { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload_time = "2025-04-23T18:31:54.79Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload_time = "2025-04-23T18:31:57.393Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload_time = "2025-04-23T18:31:59.065Z" }, - { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload_time = "2025-04-23T18:32:00.78Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload_time = "2025-04-23T18:32:02.418Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload_time = "2025-04-23T18:32:04.152Z" }, - { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload_time = "2025-04-23T18:32:06.129Z" }, - { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload_time = "2025-04-23T18:32:08.178Z" }, - { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload_time = "2025-04-23T18:32:10.242Z" }, - { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload_time = "2025-04-23T18:32:12.382Z" }, - { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload_time = "2025-04-23T18:32:14.034Z" }, - { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload_time = "2025-04-23T18:32:15.783Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload_time = "2025-04-23T18:32:18.473Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload_time = "2025-04-23T18:32:20.188Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload_time = "2025-04-23T18:32:22.354Z" }, - { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload_time = "2025-04-23T18:32:25.088Z" }, + { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, + { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, + { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, + { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, + { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, + { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, + { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, ] [[package]] @@ -101,27 +203,73 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyparsing" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/dd/e0e6a4fb84c22050f6a9701ad9fd6a67ef82faa7ba97b97eb6fdc6b49b34/pydot-3.0.4.tar.gz", hash = "sha256:3ce88b2558f3808b0376f22bfa6c263909e1c3981e2a7b629b65b451eee4a25d", size = 168167, upload_time = "2025-01-05T16:18:45.763Z" } +sdist = { url = "https://files.pythonhosted.org/packages/66/dd/e0e6a4fb84c22050f6a9701ad9fd6a67ef82faa7ba97b97eb6fdc6b49b34/pydot-3.0.4.tar.gz", hash = "sha256:3ce88b2558f3808b0376f22bfa6c263909e1c3981e2a7b629b65b451eee4a25d", size = 168167, upload-time = "2025-01-05T16:18:45.763Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/5f/1ebfd430df05c4f9e438dd3313c4456eab937d976f6ab8ce81a98f9fb381/pydot-3.0.4-py3-none-any.whl", hash = "sha256:bfa9c3fc0c44ba1d132adce131802d7df00429d1a79cc0346b0a5cd374dbe9c6", size = 35776, upload_time = "2025-01-05T16:18:42.836Z" }, + { url = "https://files.pythonhosted.org/packages/b0/5f/1ebfd430df05c4f9e438dd3313c4456eab937d976f6ab8ce81a98f9fb381/pydot-3.0.4-py3-none-any.whl", hash = "sha256:bfa9c3fc0c44ba1d132adce131802d7df00429d1a79cc0346b0a5cd374dbe9c6", size = 35776, upload-time = "2025-01-05T16:18:42.836Z" }, ] [[package]] name = "pygments" version = "2.19.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload_time = "2025-01-06T17:26:30.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload_time = "2025-01-06T17:26:25.553Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" }, ] [[package]] name = "pyparsing" version = "3.2.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bb/22/f1129e69d94ffff626bdb5c835506b3a5b4f3d070f17ea295e12c2c6f60f/pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be", size = 1088608, upload_time = "2025-03-25T05:01:28.114Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/22/f1129e69d94ffff626bdb5c835506b3a5b4f3d070f17ea295e12c2c6f60f/pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be", size = 1088608, upload-time = "2025-03-25T05:01:28.114Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/05/e7/df2285f3d08fee213f2d041540fa4fc9ca6c2d44cf36d3a035bf2a8d2bcc/pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", size = 111120, upload_time = "2025-03-25T05:01:24.908Z" }, + { url = "https://files.pythonhosted.org/packages/05/e7/df2285f3d08fee213f2d041540fa4fc9ca6c2d44cf36d3a035bf2a8d2bcc/pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", size = 111120, upload-time = "2025-03-25T05:01:24.908Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "referencing" +version = "0.36.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775, upload-time = "2025-01-25T08:48:14.241Z" }, +] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, +] + +[[package]] +name = "rfc3987" +version = "1.3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/14/bb/f1395c4b62f251a1cb503ff884500ebd248eed593f41b469f89caa3547bd/rfc3987-1.3.8.tar.gz", hash = "sha256:d3c4d257a560d544e9826b38bc81db676890c79ab9d7ac92b39c7a253d5ca733", size = 20700, upload-time = "2018-07-29T17:23:47.954Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/65/d4/f7407c3d15d5ac779c3dd34fbbc6ea2090f77bd7dd12f207ccf881551208/rfc3987-1.3.8-py2.py3-none-any.whl", hash = "sha256:10702b1e51e5658843460b189b185c0366d2cf4cff716f13111b0ea9fd2dce53", size = 13377, upload-time = "2018-07-29T17:23:45.313Z" }, ] [[package]] @@ -132,9 +280,9 @@ dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload_time = "2025-03-30T14:15:14.23Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload_time = "2025-03-30T14:15:12.283Z" }, + { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" }, ] [[package]] @@ -144,18 +292,70 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/aa/b9/ff53663ee7fa6a4195fa96d91da499f2e00ca067541e016d345cce1c9ad2/rich_argparse-1.7.0.tar.gz", hash = "sha256:f31d809c465ee43f367d599ccaf88b73bc2c4d75d74ed43f2d538838c53544ba", size = 38009, upload_time = "2025-02-08T19:00:20.755Z" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/b9/ff53663ee7fa6a4195fa96d91da499f2e00ca067541e016d345cce1c9ad2/rich_argparse-1.7.0.tar.gz", hash = "sha256:f31d809c465ee43f367d599ccaf88b73bc2c4d75d74ed43f2d538838c53544ba", size = 38009, upload-time = "2025-02-08T19:00:20.755Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bb/9c/dc7cbeb99a7b7422392ed7f327efdbb958bc0faf424aef5f130309320bda/rich_argparse-1.7.0-py3-none-any.whl", hash = "sha256:b8ec8943588e9731967f4f97b735b03dc127c416f480a083060433a97baf2fd3", size = 25339, upload_time = "2025-02-08T19:00:17.911Z" }, + { url = "https://files.pythonhosted.org/packages/bb/9c/dc7cbeb99a7b7422392ed7f327efdbb958bc0faf424aef5f130309320bda/rich_argparse-1.7.0-py3-none-any.whl", hash = "sha256:b8ec8943588e9731967f4f97b735b03dc127c416f480a083060433a97baf2fd3", size = 25339, upload-time = "2025-02-08T19:00:17.911Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/d2/7bed8453e53f6c9dea7ff4c19ee980fd87be607b2caf023d62c6579e6c30/rpds_py-0.25.0.tar.gz", hash = "sha256:4d97661bf5848dd9e5eb7ded480deccf9d32ce2cd500b88a26acbf7bd2864985", size = 26822, upload-time = "2025-05-15T13:42:03.815Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/d9/6534d5a9d00038261894551ee8043267f17c019e6c0df3c7d822fb5914f1/rpds_py-0.25.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:4e5fe366fa53bd6777cf5440245366705338587b2cf8d61348ddaad744eb591a", size = 364375, upload-time = "2025-05-15T13:39:25.878Z" }, + { url = "https://files.pythonhosted.org/packages/af/9d/f90c079635017cc50350cbbbf2c4fea7b2a75a24bea92211da1b0c52d55f/rpds_py-0.25.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:54f925ff8d4443b7cae23a5215954abbf4736a3404188bde53c4d744ac001d89", size = 350284, upload-time = "2025-05-15T13:39:27.336Z" }, + { url = "https://files.pythonhosted.org/packages/f9/04/b54c5b3abdccf03ca3ec3317bd68caaa7907a61fea063096ee08d128b6ed/rpds_py-0.25.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d58258a66255b2500ddaa4f33191ada5ec983a429c09eb151daf81efbb9aa115", size = 392107, upload-time = "2025-05-15T13:39:30.99Z" }, + { url = "https://files.pythonhosted.org/packages/aa/99/001bc3ab81c1798ee4c7bba7950134258d899e566d6839b6696b47248f71/rpds_py-0.25.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f3a57f08c558d0983a708bfe6d1265f47b5debff9b366b2f2091690fada055c", size = 398612, upload-time = "2025-05-15T13:39:32.505Z" }, + { url = "https://files.pythonhosted.org/packages/00/e1/e22893e1043938811a50c857a5780e0a4e2da02dd10ac041ecca1044906a/rpds_py-0.25.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7d60d42f1b9571341ad2322e748f7a60f9847546cd801a3a0eb72a1b54c6519", size = 452190, upload-time = "2025-05-15T13:39:34.024Z" }, + { url = "https://files.pythonhosted.org/packages/fb/6c/7071e6d27e784ac33ab4ca048eb550b5fc4f381b29e9ba33254bc6e7eaf6/rpds_py-0.25.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a54b94b0e4de95aa92618906fb631779d9fde29b4bf659f482c354a3a79fd025", size = 440634, upload-time = "2025-05-15T13:39:36.048Z" }, + { url = "https://files.pythonhosted.org/packages/57/17/7343ea3ec906ee8c2b64a956d702de5067e0058b5d2869fbfb4b11625112/rpds_py-0.25.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af1c2241919304cc2f90e7dcb3eb1c1df6fb4172dd338e629dd6410e48b3d1a0", size = 391000, upload-time = "2025-05-15T13:39:37.802Z" }, + { url = "https://files.pythonhosted.org/packages/2b/ad/9b3c3e950108073448834f0548077e598588efa413ba8dcc91e7ad6ff59d/rpds_py-0.25.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7d34547810bfd61acf8a441e8a3651e7a919e8e8aed29850be14a1b05cfc6f41", size = 424621, upload-time = "2025-05-15T13:39:39.409Z" }, + { url = "https://files.pythonhosted.org/packages/57/06/bd99ca30a6e539c18c6175501c1dd7f9ef0640f7b1dc0b14b094785b509a/rpds_py-0.25.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66568caacf18542f0cf213db7adf3de2da6ad58c7bf2c4fafec0d81ae557443b", size = 569529, upload-time = "2025-05-15T13:39:41.011Z" }, + { url = "https://files.pythonhosted.org/packages/c5/79/93381a25668466502adc082d3ce2a9ff35f8116e5e2711cedda0bfcfd699/rpds_py-0.25.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e49e4c3e899c32884d7828c91d6c3aff08d2f18857f50f86cc91187c31a4ca58", size = 594638, upload-time = "2025-05-15T13:39:43.15Z" }, + { url = "https://files.pythonhosted.org/packages/91/ee/371ecc045d65af518e2210ad018892b1f7a7a21cd64661156b4d29dfd839/rpds_py-0.25.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:20af08b0b2d5b196a2bcb70becf0b97ec5af579cee0ae6750b08a2eea3b6c77d", size = 561413, upload-time = "2025-05-15T13:39:45.3Z" }, + { url = "https://files.pythonhosted.org/packages/34/c4/85e9853312b7e5de3c98f100280fbfd903e63936f49f6f11e4cd4eb53299/rpds_py-0.25.0-cp313-cp313-win32.whl", hash = "sha256:d3dc8d6ce8f001c80919bdb49d8b0b815185933a0b8e9cdeaea42b0b6f27eeb0", size = 222326, upload-time = "2025-05-15T13:39:46.777Z" }, + { url = "https://files.pythonhosted.org/packages/65/c6/ac744cc5752b6f291b2cf13e19cd7ea3cafe68922239a3b95f05f39287b7/rpds_py-0.25.0-cp313-cp313-win_amd64.whl", hash = "sha256:113d134dc5a8d2503630ca2707b58a1bf5b1b3c69b35c7dab8690ee650c111b8", size = 234772, upload-time = "2025-05-15T13:39:48.804Z" }, + { url = "https://files.pythonhosted.org/packages/4b/aa/dabab50a2fb321a12ffe4668087e5d0f9b06286ccb260d345bf01c79b07c/rpds_py-0.25.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:6c72a4a8fab10bc96720ad40941bb471e3b1150fb8d62dab205d495511206cf1", size = 359693, upload-time = "2025-05-15T13:39:53.913Z" }, + { url = "https://files.pythonhosted.org/packages/11/3d/acda0095fe54ee6c553d222fb3d275506f8db4198b6a72a69eef826d63c1/rpds_py-0.25.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bb979162323f3534dce84b59f86e689a0761a2a300e0212bfaedfa80d4eb8100", size = 345911, upload-time = "2025-05-15T13:39:55.623Z" }, + { url = "https://files.pythonhosted.org/packages/db/f3/fba9b387077f9b305fce27fe22bdb731b75bfe208ae005fd09a127eced05/rpds_py-0.25.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35c8cb5dcf7d36d3adf2ae0730b60fb550a8feb6e432bee7ef84162a0d15714b", size = 387669, upload-time = "2025-05-15T13:39:57.103Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a7/b8dbcdc9a8f1e96b5abc58bdfc22f2845178279694a9294fe4feb66ae330/rpds_py-0.25.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:673ba018df5ae5e7b6c9a021d51ffe39c0ae1daa0041611ed27a0bca634b2d2e", size = 392202, upload-time = "2025-05-15T13:39:59.456Z" }, + { url = "https://files.pythonhosted.org/packages/60/60/2d46ad24207114cdb341490387d5a77c845827ac03f2a37182a19d072738/rpds_py-0.25.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16fb28d3a653f67c871a47c5ca0be17bce9fab8adb8bcf7bd09f3771b8c4d860", size = 450080, upload-time = "2025-05-15T13:40:01.131Z" }, + { url = "https://files.pythonhosted.org/packages/85/ae/b1966ca161942f2edf0b2c4fb448b88c19bdb37e982d0907c4b484eb0bbc/rpds_py-0.25.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12a84c3851f9e68633d883c01347db3cb87e6160120a489f9c47162cd276b0a5", size = 438189, upload-time = "2025-05-15T13:40:02.816Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b0/0a8bff40865e27fc8cd7bdf667958981794ccf5e7989890ae96c89112920/rpds_py-0.25.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b5f457afffb45d3804728a54083e31fbaf460e902e3f7d063e56d0d0814301e", size = 387925, upload-time = "2025-05-15T13:40:04.523Z" }, + { url = "https://files.pythonhosted.org/packages/a5/5d/62abbc77e18f9e67556ead54c84a7c662f39236b7a41cf1a39a24bf5e79f/rpds_py-0.25.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9442cbff21122e9a529b942811007d65eabe4182e7342d102caf119b229322c6", size = 417682, upload-time = "2025-05-15T13:40:06.879Z" }, + { url = "https://files.pythonhosted.org/packages/5d/eb/2f65e4332e3566d06c5ccad64441b1eaaf58a6c5999d533720f1f47d3118/rpds_py-0.25.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:383cf0d4288baf5a16812ed70d54ecb7f2064e255eb7fe42c38e926adeae4534", size = 565244, upload-time = "2025-05-15T13:40:08.598Z" }, + { url = "https://files.pythonhosted.org/packages/02/3a/ae5f68ab4879d6fbe3abec3139eab1664c3372d8b42864ab940a4940a61c/rpds_py-0.25.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0dcdee07ebf76223092666c72a9552db276fbe46b98830ecd1bb836cc98adc81", size = 590459, upload-time = "2025-05-15T13:40:10.375Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f6/ada6c3d9b803a9eb7bc9c8b3f3cebf7d779bbbb056cd7e3fc150e4c74c00/rpds_py-0.25.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5bbfbd9c74c4dd74815bd532bf29bedea6d27d38f35ef46f9754172a14e4c655", size = 558335, upload-time = "2025-05-15T13:40:13.695Z" }, + { url = "https://files.pythonhosted.org/packages/68/9a/7d269e8f1bfe3143e699334ca0b578e16b37e6505bf10dca8c02aa8addc8/rpds_py-0.25.0-cp313-cp313t-win32.whl", hash = "sha256:90dbd2c42cb6463c07020695800ae8f347e7dbeff09da2975a988e467b624539", size = 218761, upload-time = "2025-05-15T13:40:16.043Z" }, + { url = "https://files.pythonhosted.org/packages/16/16/f5843b19b7bfd16d63b960cf4c646953010886cc62dd41b00854d77b0eed/rpds_py-0.25.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8c2ad59c4342a176cb3e0d5753e1c911eabc95c210fc6d0e913c32bf560bf012", size = 232634, upload-time = "2025-05-15T13:40:17.633Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20250516" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ef/88/d65ed807393285204ab6e2801e5d11fbbea811adcaa979a2ed3b67a5ef41/types_python_dateutil-2.9.0.20250516.tar.gz", hash = "sha256:13e80d6c9c47df23ad773d54b2826bd52dbbb41be87c3f339381c1700ad21ee5", size = 13943, upload-time = "2025-05-16T03:06:58.385Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/3f/b0e8db149896005adc938a1e7f371d6d7e9eca4053a29b108978ed15e0c2/types_python_dateutil-2.9.0.20250516-py3-none-any.whl", hash = "sha256:2b2b3f57f9c6a61fba26a9c0ffb9ea5681c9b83e69cd897c6b5f668d9c0cab93", size = 14356, upload-time = "2025-05-16T03:06:57.249Z" }, ] [[package]] name = "typing-extensions" version = "4.13.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload_time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload_time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, ] [[package]] @@ -165,7 +365,25 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload_time = "2025-02-25T17:27:59.638Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload-time = "2025-02-25T17:27:59.638Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload-time = "2025-02-25T17:27:57.754Z" }, +] + +[[package]] +name = "uri-template" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, +] + +[[package]] +name = "webcolors" +version = "24.11.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/29/061ec845fb58521848f3739e466efd8250b4b7b98c1b6c5bf4d40b419b7e/webcolors-24.11.1.tar.gz", hash = "sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6", size = 45064, upload-time = "2024-11-11T07:43:24.224Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload_time = "2025-02-25T17:27:57.754Z" }, + { url = "https://files.pythonhosted.org/packages/60/e8/c0e05e4684d13459f93d312077a9a2efbe04d59c393bc2b8802248c908d4/webcolors-24.11.1-py3-none-any.whl", hash = "sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9", size = 14934, upload-time = "2024-11-11T07:43:22.529Z" }, ] diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 9706ba0d6b..786ce25514 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -253,6 +253,11 @@ "changes": "* Use generalized parameters.", "modified": "2025-05-05", "version": "0.03" + }, + { + "changes": "* Improve and make document serialization more repeatable, and stricter.\n* TODO: Define Systems parameters\n* TODO: Define DReps documents.\n* TODO: Define Proposer Profiles.\n* TODO: Define Role 0 Profile.", + "modified": "2025-05-30", + "version": "0.04" } ] }, @@ -317,7 +322,6 @@ "docs": { "Brand Parameters": { "authors": {}, - "description": "Parameters which define this brand within the system.", "headers": { "content type": { "coseLabel": 3, @@ -424,15 +428,19 @@ ], "versions": [ { - "changes": "* First Published Version", + "changes": "Initial version. Structure aligned with global metadata requirements.", + "modified": "2024-06-07", + "version": "v1" + }, + { + "changes": "Updated to include common definitions and examples.", "modified": "2025-04-04", - "version": "0.01" + "version": "v2" } ] }, "Campaign Parameters": { "authors": {}, - "description": "Parameters which define a Campaign within a Brand in the system.", "headers": { "content type": { "coseLabel": 3, @@ -470,10 +478,7 @@ "description": "A reference to the Parameters Document this document lies under.", "exclusive": null, "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "yes", - "type": "Brand Parameters", + "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." }, "ref": { @@ -542,20 +547,14 @@ ], "versions": [ { - "changes": "* First Published Version", - "modified": "2025-04-04", - "version": "0.01" - }, - { - "changes": "* Use generalized parameters.", - "modified": "2025-05-05", - "version": "0.03" + "changes": "Initial version. Structure aligned with global metadata requirements.", + "modified": "2024-06-07", + "version": "v1" } ] }, "Category Parameters": { "authors": {}, - "description": "Parameters which define a Category withing a Campaign under a Brand in the system.", "headers": { "content type": { "coseLabel": 3, @@ -593,10 +592,7 @@ "description": "A reference to the Parameters Document this document lies under.", "exclusive": null, "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "yes", - "type": "Campaign Parameters", + "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." }, "ref": { @@ -665,14 +661,9 @@ ], "versions": [ { - "changes": "* First Published Version", - "modified": "2025-04-04", - "version": "0.01" - }, - { - "changes": "* Use generalized parameters.", - "modified": "2025-05-05", - "version": "0.03" + "changes": "Initial version. Structure aligned with global metadata requirements.", + "modified": "2024-06-07", + "version": "v1" } ] }, @@ -800,7 +791,7 @@ }, "Decision Parameters": { "authors": {}, - "description": "Parameters which define an individual voting event.", + "description": "\tParameters which define an individual voting event.", "headers": { "content type": { "coseLabel": 3, @@ -841,11 +832,7 @@ "linked_refs": null, "multiple": false, "required": "yes", - "type": [ - "Brand Parameters", - "Campaign Parameters", - "Category Parameters" - ], + "type": "Decision 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." }, "ref": { @@ -899,6 +886,17 @@ } }, "notes": [], + "payload": { + "description": "Payload for Decision Parameters document.", + "examples": [ + { + "description": "This document indicates the linked proposal is final and requested to proceed for further consideration.", + "example": {}, + "title": "Final Proposal Submission" + } + ], + "schema": {} + }, "signers": { "roles": { "user": [ @@ -914,14 +912,19 @@ ], "versions": [ { - "changes": "* First Published Version", + "changes": "\t* First Published Version", "modified": "2025-04-04", "version": "0.01" }, { - "changes": "* Use generalized parameters.", + "changes": "\t* Use generalized parameters.", "modified": "2025-05-05", "version": "0.03" + }, + { + "changes": "\t* Added brand reference to decision parameters.", + "modified": "2025-06-06", + "version": "0.04" } ] }, @@ -1856,6 +1859,29 @@ "notes": [], "payload": { "description": "The kind of action is controlled by this payload.\nThe Payload is a JSON Document, and must conform to this schema.\n\nStates:\n\n* `final` : All collaborators must publish a `final` status for the proposal to be `final`.\n* `draft` : Reverses the previous `final` state for a signer and accepts collaborator status to a document. \n* `hide` : Requests the proposal be hidden (not final, but a hidden draft). \n\t\t\t`hide` is only actioned if sent by the author, \n\t\t\tfor a collaborator it identified that they do not wish to be listed as a `collaborator`.", + "examples": [ + { + "description": "This document indicates the linked proposal is final and requested to proceed for further consideration.", + "example": { + "action": "final" + }, + "title": "Final Proposal Submission" + }, + { + "description": "This document indicates the linked proposal is no longer final and should not proceed for further consideration.\nIt is also used by collaborators to accept that they are a collaborator on a document.", + "example": { + "action": "draft" + }, + "title": "Draft Proposal Submission" + }, + { + "description": "If submitted by the proposal author the document is hidden, it is still public but not shown as\na proposal being drafted.\nIf submitted by a collaborator, that collaborator is declaring they do not wish to be listed as\na collaborator on the proposal.", + "example": { + "action": "hide" + }, + "title": "Hidden Proposal Submission" + } + ], "schema": { "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", @@ -2066,6 +2092,7 @@ } }, "documentationLinks": { + "CBOR-LFD-ENCODING": "https://www.rfc-editor.org/rfc/rfc8949.html#section-4.2.3", "CBOR-TAG-37": "https://github.com/lucas-clemente/cbor-specs/blob/master/uuid.md", "CBOR-TAG-42": "https://github.com/ipld/cid-cbor/", "CC-BY-4.0": "https://creativecommons.org/licenses/by/4.0/legalcode", @@ -2097,6 +2124,7 @@ "linkAKA": { "BROTLI": "RFC7932", "CBOR": "RFC8949", + "CBOR Deterministic Encoding": "CBOR-LFD-ENCODING", "CBOR Encoded IPLD Content Identifier": "CBOR-TAG-42", "CDDL": "RFC8610", "COSE": "RFC9052", diff --git a/specs/signed_docs/authors_copyright.cue b/specs/signed_docs/authors_copyright.cue index c354a5b10e..2d9a8314d8 100644 --- a/specs/signed_docs/authors_copyright.cue +++ b/specs/signed_docs/authors_copyright.cue @@ -60,5 +60,16 @@ copyright: #copyrightNotice & { * Use generalized parameters. """ }, + { + version: "0.04" + modified: "2025-05-30" + changes: """ + * Improve and make document serialization more repeatable, and stricter. + * TODO: Define Systems parameters + * TODO: Define DReps documents. + * TODO: Define Proposer Profiles. + * TODO: Define Role 0 Profile. + """ + }, ] } diff --git a/specs/signed_docs/docs/brand_parameters.cue b/specs/signed_docs/docs/brand_parameters.cue index 75deb70f29..eff82abe57 100644 --- a/specs/signed_docs/docs/brand_parameters.cue +++ b/specs/signed_docs/docs/brand_parameters.cue @@ -1,21 +1,28 @@ package signed_docs -// Proposal Document Definition +_common_defs: {} @embed(file="./payload_schemas/common_definitions.schema.json") + +// Brand Parameters Document Definition docs: #DocumentDefinitions & { "Brand Parameters": { - - description: """ - Parameters which define this brand within the system. - """ - + metadata: { + ref: metadata.ref // Reference to the next highest document + template: metadata.template // Reference to a brand/campaign/etc template document + } versions: [ { - version: "0.01" + version: "v1" + modified: "2024-06-07" + changes: "Initial version. Structure aligned with global metadata requirements." + }, + { + version: "v2" modified: "2025-04-04" - changes: """ - * First Published Version - """ + changes: "Updated to include common definitions and examples." }, - ]} + ] + // Payload is fully templated and not defined here + } + } diff --git a/specs/signed_docs/docs/campaign_parameters.cue b/specs/signed_docs/docs/campaign_parameters.cue index 9cafb80ba5..6376c36af7 100644 --- a/specs/signed_docs/docs/campaign_parameters.cue +++ b/specs/signed_docs/docs/campaign_parameters.cue @@ -1,34 +1,22 @@ package signed_docs -// Proposal Document Definition +// Import common definitions JSON schema for use in embedded schemas +_common_defs: {} @embed(file="./payload_schemas/common_definitions.schema.json") +// Campaign Parameters Document Definition docs: #DocumentDefinitions & { "Campaign Parameters": { - description: """ - Parameters which define a Campaign within a Brand in the system. - """ - metadata: { - parameters: { - required: "yes" - type: "Brand Parameters" - } + ref: metadata.ref + template: metadata.template } - versions: [ { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - { - version: "0.03" - modified: "2025-05-05" - changes: """ - * Use generalized parameters. - """ + version: "v1" + modified: "2024-06-07" + changes: "Initial version. Structure aligned with global metadata requirements." }, - ]} + ] + // Payload is fully templated and not defined here + } } diff --git a/specs/signed_docs/docs/category_parameters.cue b/specs/signed_docs/docs/category_parameters.cue index 7d8904f7db..8fe82f891e 100644 --- a/specs/signed_docs/docs/category_parameters.cue +++ b/specs/signed_docs/docs/category_parameters.cue @@ -1,35 +1,22 @@ package signed_docs -// Proposal Document Definition +// Import common definitions JSON schema for use in embedded schemas +_common_defs: {} @embed(file="./payload_schemas/common_definitions.schema.json") +// Category Parameters Document Definition docs: #DocumentDefinitions & { "Category Parameters": { - - description: """ - Parameters which define a Category withing a Campaign under a Brand in the system. - """ - metadata: { - parameters: { - required: "yes" - type: "Campaign Parameters" - } + ref: metadata.ref + template: metadata.template } - versions: [ { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - { - version: "0.03" - modified: "2025-05-05" - changes: """ - * Use generalized parameters. - """ + version: "v1" + modified: "2024-06-07" + changes: "Initial version. Structure aligned with global metadata requirements." }, - ]} + ] + // Payload is fully templated and not defined here + } } diff --git a/specs/signed_docs/docs/decision_parameters.cue b/specs/signed_docs/docs/decision_parameters.cue index 133d908d5e..53e333f500 100644 --- a/specs/signed_docs/docs/decision_parameters.cue +++ b/specs/signed_docs/docs/decision_parameters.cue @@ -1,34 +1,54 @@ package signed_docs -// Proposal Document Definition +// Import common definitions JSON schema for use in embedded schemas +_common_defs: {} @embed(file="./payload_schemas/common_definitions.schema.json") +// Decision Parameters Document Definition docs: #DocumentDefinitions & { "Decision Parameters": { description: """ - Parameters which define an individual voting event. + Parameters which define an individual voting event. """ - metadata: { parameters: { required: "yes" - type: doc_clusters."System Parameters".docs + type: "Decision Parameters" } } - + payload: { + description: "Payload for Decision Parameters document." + schema: {} @embed(file="./payload_schemas/decision_parameters.schema.json") + examples: [ + { + title: "Final Proposal Submission" + description: """ + This document indicates the linked proposal is final and requested to proceed for further consideration. + """ + example: {} @embed(file="./payload_schemas/decision_parameter.example.json") + }, + ]} versions: [ { version: "0.01" modified: "2025-04-04" changes: """ - * First Published Version + * First Published Version """ }, { version: "0.03" modified: "2025-05-05" changes: """ - * Use generalized parameters. + * Use generalized parameters. + """ + }, + { + version: "0.04" + modified: "2025-06-06" + changes: """ + * Added brand reference to decision parameters. """ }, - ]} + ] + } } diff --git a/specs/signed_docs/docs/payload_schemas/brand_parameter.example.json b/specs/signed_docs/docs/payload_schemas/brand_parameter.example.json new file mode 100644 index 0000000000..a161fefafc --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/brand_parameter.example.json @@ -0,0 +1,11 @@ +{ + "directVotingPrivacyState": true, + "brandName": "Catalyst Foundation", + "minimumBudgetRequestPerProposal": 15000, + "maximumBudgetRequestPerProposal": "200000 (variable per challenge)", + "maximumProposalsPerProposer": 6, + "communityReviewerRegistration": "Open to all ADA holders", + "votingPowerThreshold": 1000000, + "tallyingOptimization": "majority", + "proposalAcceptanceThreshold": 60 +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/brand_parameters.schema.json b/specs/signed_docs/docs/payload_schemas/brand_parameters.schema.json new file mode 100644 index 0000000000..186efb70a9 --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/brand_parameters.schema.json @@ -0,0 +1,85 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/main/specs/signed_docs/docs/payload_schemas/brand_parameters.schema.json", + "title": "Brand Parameters", + "description": "Schema for defining Catalyst brand-level parameters, with UI/UX metadata and logical grouping.", + "type": "object", + "properties": { + "directVotingPrivacyState": { + "$ref": "#/definitions/booleanParameter", + "title": "Direct Voting Privacy State", + "description": "Whether direct voting privacy is enabled.", + "x-guidance": "Set to true if direct voting privacy is required." + }, + "brandName": { + "$ref": "#/definitions/stringParameter", + "title": "Brand Name", + "description": "The name of the brand.", + "x-guidance": "Enter the official brand name." + }, + "minimumBudgetRequestPerProposal": { + "$ref": "#/definitions/adaAmount", + "title": "Minimum Budget Request Per Proposal", + "description": "The minimum ADA amount that can be requested per proposal.", + "x-guidance": "Specify the minimum allowed budget per proposal in ADA." + }, + "maximumBudgetRequestPerProposal": { + "$ref": "#/definitions/stringParameter", + "title": "Maximum Budget Request Per Proposal", + "description": "The maximum ADA amount (variable per challenge/category) that can be requested per proposal.", + "x-guidance": "Specify the maximum allowed budget per proposal." + }, + "maximumProposalsPerProposer": { + "$ref": "#/definitions/integerParameter", + "title": "Maximum Proposals per Proposer/co-proposer", + "description": "The maximum number of proposals a proposer or co-proposer can submit.", + "x-guidance": "Set the limit for proposals per proposer/co-proposer." + }, + "communityReviewerRegistration": { + "$ref": "#/definitions/stringParameter", + "title": "Community Reviewer Registration", + "description": "Information or rules about community reviewer registration.", + "x-guidance": "Describe the process or requirements for community reviewer registration." + }, + "votingPowerThreshold": { + "$ref": "#/definitions/lovelaceAmount", + "title": "Voting Power Threshold", + "description": "The minimum Lovelace required to participate in voting.", + "x-guidance": "Specify the minimum voting power threshold in Lovelace." + }, + "tallyingOptimization": { + "$ref": "#/definitions/ratioFormula", + "title": "Tallying Optimization", + "description": "The ratio or formula used for tallying optimization.", + "x-guidance": "Provide the formula or ratio for tallying optimization." + }, + "proposalAcceptanceThreshold": { + "$ref": "#/definitions/percentageParameter", + "title": "Proposal Acceptance Threshold", + "description": "The percentage threshold for proposal acceptance.", + "x-guidance": "Set the acceptance threshold as a percentage." + } + }, + "required": [ + "directVotingPrivacyState", + "brandName", + "minimumBudgetRequestPerProposal", + "maximumBudgetRequestPerProposal", + "maximumProposalsPerProposer", + "communityReviewerRegistration", + "votingPowerThreshold", + "tallyingOptimization", + "proposalAcceptanceThreshold" + ], + "x-order": [ + "directVotingPrivacyState", + "brandName", + "minimumBudgetRequestPerProposal", + "maximumBudgetRequestPerProposal", + "maximumProposalsPerProposer", + "communityReviewerRegistration", + "votingPowerThreshold", + "tallyingOptimization", + "proposalAcceptanceThreshold" + ] +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/campaign_parameter.example.json b/specs/signed_docs/docs/payload_schemas/campaign_parameter.example.json new file mode 100644 index 0000000000..4407a3c620 --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/campaign_parameter.example.json @@ -0,0 +1,27 @@ +{ + "fundName": "Fund 14", + "fundSize": 5000000, + "campaignTitle": "Cardano Open Innovation", + "campaignBudget": 1000000, + "proposalSubmissionFee": 100, + "compensationsDistributionDate": "2025-07-01", + "proposalsRegistrationOnChain": "2025-06-15", + "drepDeadlineDate": "2025-06-10", + "registrationDeadlineDate": "2025-06-20T23:59:59Z", + "votingPeriodStart": "2025-07-05T00:00:00Z", + "votingPeriodEnd": "2025-07-12T23:59:59Z", + "startOfTallying": "2025-07-13", + "endOfTallying": "2025-07-15", + "proposalFundingLogic": "top N by votes", + "voterCompensations": 2.5, + "communityReviewCompensations": 1.5, + "communityModeratorCompensations": 1.0, + "onboardingCompensations": 0.5, + "projectAccountabilityManagementComp": 0.25, + "currentInsightSharingStart": "2025-05-01", + "currentProposalSubmissionStart": "2025-05-10", + "currentRefineProposalsStart": "2025-05-20", + "currentFinalizeProposalsStart": "2025-05-30", + "currentProposalAssessment": "2025-06-01", + "currentAssessmentQaStart": "2025-06-05" +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/campaign_parameters.schema.json b/specs/signed_docs/docs/payload_schemas/campaign_parameters.schema.json new file mode 100644 index 0000000000..e800be43d0 --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/campaign_parameters.schema.json @@ -0,0 +1,208 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/main/specs/signed_docs/docs/payload_schemas/campaign_parameters.schema.json", + "title": "Campaign Parameters", + "description": "Schema for defining Catalyst campaign-level parameters, with UI/UX metadata and logical grouping.", + "type": "object", + "properties": { + "fundName": { + "$ref": "#/definitions/stringParameter", + "title": "Fund/Campaign Name" + }, + "fundSize": { + "$ref": "#/definitions/adaAmount", + "title": "Fund/Campaign Size" + }, + "campaignTitle": { + "$ref": "#/definitions/stringParameter", + "title": "Campaign (Challenge) Title" + }, + "campaignBudget": { + "$ref": "#/definitions/adaAmount", + "title": "Campaign (Challenge) Budget" + }, + "proposalSubmissionFee": { + "$ref": "#/definitions/currencyAmount", + "title": "Proposal Submission Fee" + }, + "compensationsDistributionDate": { + "$ref": "#/definitions/dateParameter", + "title": "Compensations and funds distribution target date" + }, + "proposalsRegistrationOnChain": { + "$ref": "#/definitions/dateParameter", + "title": "Proposals registration on the blockchain" + }, + "drepDeadlineDate": { + "$ref": "#/definitions/dateParameter", + "title": "Drep deadline date" + }, + "registrationDeadlineDate": { + "$ref": "#/definitions/datetimeParameter", + "title": "Registration deadline date" + }, + "votingPeriodStart": { + "$ref": "#/definitions/datetimeParameter", + "title": "Voting period start time" + }, + "votingPeriodEnd": { + "$ref": "#/definitions/datetimeParameter", + "title": "Voting period end time" + }, + "startOfTallying": { + "$ref": "#/definitions/dateParameter", + "title": "Start of tallying" + }, + "endOfTallying": { + "$ref": "#/definitions/dateParameter", + "title": "End of tallying" + }, + "proposalFundingLogic": { + "$ref": "#/definitions/stringRule", + "title": "Proposal Funding logic (winner selection)" + }, + "voterCompensations": { + "$ref": "#/definitions/percentageOrAda", + "title": "Voter Compensations (Vrtotal)" + }, + "communityReviewCompensations": { + "$ref": "#/definitions/percentageOrAda", + "title": "Community Review Compensations" + }, + "communityModeratorCompensations": { + "$ref": "#/definitions/percentageOrAda", + "title": "Community Moderator Compensations (AArtotal)" + }, + "onboardingCompensations": { + "$ref": "#/definitions/percentageOrAda", + "title": "Onboarding compensations (Cttotal)" + }, + "projectAccountabilityManagementComp": { + "$ref": "#/definitions/percentageOrAda", + "title": "Project Accountability Management Comp." + }, + "currentInsightSharingStart": { + "$ref": "#/definitions/dateParameter", + "title": "current_insight_sharing_start" + }, + "currentProposalSubmissionStart": { + "$ref": "#/definitions/dateParameter", + "title": "current_proposal_submission_start" + }, + "currentRefineProposalsStart": { + "$ref": "#/definitions/dateParameter", + "title": "current_refine_proposals_start" + }, + "currentFinalizeProposalsStart": { + "$ref": "#/definitions/dateParameter", + "title": "current_finalize_proposals_start" + }, + "currentProposalAssessment": { + "$ref": "#/definitions/dateParameter", + "title": "current_proposal_assessment" + }, + "currentAssessmentQaStart": { + "$ref": "#/definitions/dateParameter", + "title": "current_assessment_qa_start" + } + }, + "required": ["fundName", "fundSize", "campaignTitle", "campaignBudget"], + "x-order": [ + "fundName", + "fundSize", + "campaignTitle", + "campaignBudget", + "proposalSubmissionFee", + "compensationsDistributionDate", + "proposalsRegistrationOnChain", + "drepDeadlineDate", + "registrationDeadlineDate", + "votingPeriodStart", + "votingPeriodEnd", + "startOfTallying", + "endOfTallying", + "proposalFundingLogic", + "voterCompensations", + "communityReviewCompensations", + "communityModeratorCompensations", + "onboardingCompensations", + "projectAccountabilityManagementComp", + "currentInsightSharingStart", + "currentProposalSubmissionStart", + "currentRefineProposalsStart", + "currentFinalizeProposalsStart", + "currentProposalAssessment", + "currentAssessmentQaStart" + ], + "definitions": { + "booleanParameter": { + "type": "boolean", + "title": "Boolean Parameter", + "x-note": "A true/false value." + }, + "stringParameter": { + "type": "string", + "title": "String Parameter", + "x-note": "A plain text value." + }, + "adaAmount": { + "type": "integer", + "title": "ADA Amount", + "x-note": "Amount in ADA." + }, + "lovelaceAmount": { + "type": "integer", + "title": "Lovelace Amount", + "x-note": "Amount in Lovelace." + }, + "integerParameter": { + "type": "integer", + "title": "Integer Parameter", + "x-note": "An integer value." + }, + "dateParameter": { + "type": "string", + "format": "date", + "title": "Date Parameter", + "x-note": "A date value (YYYY-MM-DD)." + }, + "datetimeParameter": { + "type": "string", + "format": "date-time", + "title": "Datetime Parameter", + "x-note": "A datetime value (ISO 8601)." + }, + "ratioFormula": { + "type": "string", + "title": "Ratio / Formula", + "x-note": "A ratio or formula expression." + }, + "percentageParameter": { + "type": "number", + "minimum": 0, + "maximum": 100, + "title": "Percentage Parameter", + "x-note": "A percentage value (0-100)." + }, + "currencyAmount": { + "type": ["string", "number"], + "title": "Currency Amount or String" + }, + "stringRule": { + "type": "string", + "title": "String / Rule" + }, + "percentageOrAda": { + "oneOf": [ + { "$ref": "#/definitions/percentageParameter" }, + { "$ref": "#/definitions/adaAmount" } + ], + "title": "Percentage or ADA Amount" + }, + "listParameter": { + "type": "array", + "items": { "type": "string" }, + "title": "List Parameter" + } + } +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/category_parameter.example.json b/specs/signed_docs/docs/payload_schemas/category_parameter.example.json new file mode 100644 index 0000000000..4aecdefd1d --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/category_parameter.example.json @@ -0,0 +1,8 @@ +{ + "campaignTitle": "Cardano Open Innovation", + "minimumBudgetRequestPerProposal": 15000, + "maximumBudgetRequestPerProposal": "200000 (variable per challenge)", + "proposalFundingLogic": "top N by votes", + "proposalAcceptanceThreshold": 60, + "votingOptions": ["Yes", "No", "Abstain"] +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/category_parameters.schema.json b/specs/signed_docs/docs/payload_schemas/category_parameters.schema.json new file mode 100644 index 0000000000..a193c96a64 --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/category_parameters.schema.json @@ -0,0 +1,117 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/main/specs/signed_docs/docs/payload_schemas/category_parameters.schema.json", + "title": "Category Parameters", + "description": "Schema for defining Catalyst category-level parameters, with UI/UX metadata and logical grouping.", + "type": "object", + "properties": { + "campaignTitle": { + "$ref": "#/definitions/stringParameter", + "title": "Campaign (Challenge) Title" + }, + "minimumBudgetRequestPerProposal": { + "$ref": "#/definitions/adaAmount", + "title": "Minimum Budget Request Per Proposal" + }, + "maximumBudgetRequestPerProposal": { + "$ref": "#/definitions/stringParameter", + "title": "Maximum Budget Request Per Proposal" + }, + "proposalFundingLogic": { + "$ref": "#/definitions/stringRule", + "title": "Proposal Funding logic (winner selection)" + }, + "proposalAcceptanceThreshold": { + "$ref": "#/definitions/percentageParameter", + "title": "Proposal acceptance threshold" + }, + "votingOptions": { + "$ref": "#/definitions/listParameter", + "title": "Voting options" + } + }, + "required": [ + "campaignTitle", + "minimumBudgetRequestPerProposal", + "maximumBudgetRequestPerProposal" + ], + "x-order": [ + "campaignTitle", + "minimumBudgetRequestPerProposal", + "maximumBudgetRequestPerProposal", + "proposalFundingLogic", + "proposalAcceptanceThreshold", + "votingOptions" + ], + "definitions": { + "booleanParameter": { + "type": "boolean", + "title": "Boolean Parameter", + "x-note": "A true/false value." + }, + "stringParameter": { + "type": "string", + "title": "String Parameter", + "x-note": "A plain text value." + }, + "adaAmount": { + "type": "integer", + "title": "ADA Amount", + "x-note": "Amount in ADA." + }, + "lovelaceAmount": { + "type": "integer", + "title": "Lovelace Amount", + "x-note": "Amount in Lovelace." + }, + "integerParameter": { + "type": "integer", + "title": "Integer Parameter", + "x-note": "An integer value." + }, + "dateParameter": { + "type": "string", + "format": "date", + "title": "Date Parameter", + "x-note": "A date value (YYYY-MM-DD)." + }, + "datetimeParameter": { + "type": "string", + "format": "date-time", + "title": "Datetime Parameter", + "x-note": "A datetime value (ISO 8601)." + }, + "ratioFormula": { + "type": "string", + "title": "Ratio / Formula", + "x-note": "A ratio or formula expression." + }, + "percentageParameter": { + "type": "number", + "minimum": 0, + "maximum": 100, + "title": "Percentage Parameter", + "x-note": "A percentage value (0-100)." + }, + "currencyAmount": { + "type": ["string", "number"], + "title": "Currency Amount or String" + }, + "stringRule": { + "type": "string", + "title": "String / Rule" + }, + "percentageOrAda": { + "oneOf": [ + { "$ref": "#/definitions/percentageParameter" }, + { "$ref": "#/definitions/adaAmount" } + ], + "title": "Percentage or ADA Amount" + }, + "listParameter": { + "type": "array", + "items": { "type": "string" }, + "title": "List Parameter" + } + } +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/common_definitions.schema.json b/specs/signed_docs/docs/payload_schemas/common_definitions.schema.json new file mode 100644 index 0000000000..e2b2ae1331 --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/common_definitions.schema.json @@ -0,0 +1,78 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/main/specs/signed_docs/docs/payload_schemas/common_definitions.schema.json", + "title": "Common Definitions for Catalyst Schemas", + "description": "Reusable definitions for all Catalyst parameter schemas.", + "type": "object", + "definitions": { + "booleanParameter": { + "type": "boolean", + "title": "Boolean Parameter", + "x-note": "A true/false value." + }, + "stringParameter": { + "type": "string", + "title": "String Parameter", + "x-note": "A plain text value." + }, + "adaAmount": { + "type": "integer", + "title": "ADA Amount", + "x-note": "Amount in ADA." + }, + "lovelaceAmount": { + "type": "integer", + "title": "Lovelace Amount", + "x-note": "Amount in Lovelace." + }, + "integerParameter": { + "type": "integer", + "title": "Integer Parameter", + "x-note": "An integer value." + }, + "dateParameter": { + "type": "string", + "format": "date", + "title": "Date Parameter", + "x-note": "A date value (YYYY-MM-DD)." + }, + "datetimeParameter": { + "type": "string", + "format": "date-time", + "title": "Datetime Parameter", + "x-note": "A datetime value (ISO 8601)." + }, + "ratioFormula": { + "type": "string", + "title": "Ratio / Formula", + "x-note": "A ratio or formula expression." + }, + "percentageParameter": { + "type": "number", + "minimum": 0, + "maximum": 100, + "title": "Percentage Parameter", + "x-note": "A percentage value (0-100)." + }, + "currencyAmount": { + "type": ["string", "number"], + "title": "Currency Amount or String" + }, + "stringRule": { + "type": "string", + "title": "String / Rule" + }, + "percentageOrAda": { + "oneOf": [ + { "$ref": "#/definitions/percentageParameter" }, + { "$ref": "#/definitions/adaAmount" } + ], + "title": "Percentage or ADA Amount" + }, + "listParameter": { + "type": "array", + "items": { "type": "string" }, + "title": "List Parameter" + } + } +} diff --git a/specs/signed_docs/docs/payload_schemas/decision_parameter.example.json b/specs/signed_docs/docs/payload_schemas/decision_parameter.example.json new file mode 100644 index 0000000000..08f3548d3f --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/decision_parameter.example.json @@ -0,0 +1,4 @@ +{ + "votingPeriodStart": "2025-07-05T00:00:00Z", + "votingOptions": ["Yes", "No", "Abstain"] +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/decision_parameters.schema.json b/specs/signed_docs/docs/payload_schemas/decision_parameters.schema.json new file mode 100644 index 0000000000..bb12f3d07a --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/decision_parameters.schema.json @@ -0,0 +1,112 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/main/specs/signed_docs/docs/payload_schemas/decision_parameters.schema.json", + "title": "Decision Parameters", + "description": "Schema for defining Catalyst decision-level parameters, with UI/UX metadata and logical grouping.", + "type": "object", + "properties": { + "decisionTitle": { + "$ref": "#/definitions/stringParameter", + "title": "Decision Title" + }, + "decisionType": { + "$ref": "#/definitions/stringParameter", + "title": "Decision Type" + }, + "decisionDate": { + "$ref": "#/definitions/dateParameter", + "title": "Decision Date" + }, + "votingOptions": { + "$ref": "#/definitions/listParameter", + "title": "Voting Options" + }, + "acceptanceThreshold": { + "$ref": "#/definitions/percentageParameter", + "title": "Acceptance Threshold" + } + }, + "required": [ + "decisionTitle", + "decisionType", + "decisionDate" + ], + "x-order": [ + "decisionTitle", + "decisionType", + "decisionDate", + "votingOptions", + "acceptanceThreshold" + ], + "definitions": { + "booleanParameter": { + "type": "boolean", + "title": "Boolean Parameter", + "x-note": "A true/false value." + }, + "stringParameter": { + "type": "string", + "title": "String Parameter", + "x-note": "A plain text value." + }, + "adaAmount": { + "type": "integer", + "title": "ADA Amount", + "x-note": "Amount in ADA." + }, + "lovelaceAmount": { + "type": "integer", + "title": "Lovelace Amount", + "x-note": "Amount in Lovelace." + }, + "integerParameter": { + "type": "integer", + "title": "Integer Parameter", + "x-note": "An integer value." + }, + "dateParameter": { + "type": "string", + "format": "date", + "title": "Date Parameter", + "x-note": "A date value (YYYY-MM-DD)." + }, + "datetimeParameter": { + "type": "string", + "format": "date-time", + "title": "Datetime Parameter", + "x-note": "A datetime value (ISO 8601)." + }, + "ratioFormula": { + "type": "string", + "title": "Ratio / Formula", + "x-note": "A ratio or formula expression." + }, + "percentageParameter": { + "type": "number", + "minimum": 0, + "maximum": 100, + "title": "Percentage Parameter", + "x-note": "A percentage value (0-100)." + }, + "currencyAmount": { + "type": ["string", "number"], + "title": "Currency Amount or String" + }, + "stringRule": { + "type": "string", + "title": "String / Rule" + }, + "percentageOrAda": { + "oneOf": [ + { "$ref": "#/definitions/percentageParameter" }, + { "$ref": "#/definitions/adaAmount" } + ], + "title": "Percentage or ADA Amount" + }, + "listParameter": { + "type": "array", + "items": { "type": "string" }, + "title": "List Parameter" + } + } +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/parameters.md b/specs/signed_docs/docs/payload_schemas/parameters.md new file mode 100644 index 0000000000..f631497861 --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/parameters.md @@ -0,0 +1,55 @@ +# Catalyst Signed Document Parameters + +## Brand Parameters + +- directVotingPrivacyState +- brandName +- minimumBudgetRequestPerProposal +- maximumBudgetRequestPerProposal +- maximumProposalsPerProposer +- communityReviewerRegistration +- votingPowerThreshold +- tallyingOptimization +- proposalAcceptanceThreshold + +## Campaign Parameters + +- fundName +- fundSize +- campaignTitle +- campaignBudget +- proposalSubmissionFee +- compensationsDistributionDate +- proposalsRegistrationOnChain +- drepDeadlineDate +- registrationDeadlineDate +- votingPeriodStart +- votingPeriodEnd +- startOfTallying +- endOfTallying +- proposalFundingLogic +- voterCompensations +- communityReviewCompensations +- communityModeratorCompensations +- onboardingCompensations +- projectAccountabilityManagementComp +- currentInsightSharingStart +- currentProposalSubmissionStart +- currentRefineProposalsStart +- currentFinalizeProposalsStart +- currentProposalAssessment +- currentAssessmentQaStart + +## Category Parameters + +- campaignTitle +- minimumBudgetRequestPerProposal +- maximumBudgetRequestPerProposal +- proposalFundingLogic +- proposalAcceptanceThreshold +- votingOptions + +## Contest Parameters + +- votingPeriodStart +- votingOptions diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.draft.example.json b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.draft.example.json new file mode 100644 index 0000000000..747d3b6ec7 --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.draft.example.json @@ -0,0 +1,3 @@ +{ + "action": "draft" +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.final.example.json b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.final.example.json new file mode 100644 index 0000000000..bfbf15e59d --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.final.example.json @@ -0,0 +1,3 @@ +{ + "action": "final" +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.hide.example.json b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.hide.example.json new file mode 100644 index 0000000000..e6f023094f --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.hide.example.json @@ -0,0 +1,3 @@ +{ + "action": "hide" +} \ No newline at end of file diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json index 965b66f37a..f7c7494c20 100644 --- a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json +++ b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json @@ -3,12 +3,10 @@ "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json", "title": "Proposal Submission Action Payload Schema", "description": "Structure of the payload of a Proposal Submission Action.", - "maintainers": [ - { - "name": "Catalyst Team", - "url": "https://projectcatalyst.io/" - } - ], + "maintainers": [{ + "name": "Catalyst Team", + "url": "https://projectcatalyst.io/" + }], "x-changelog": { "2025-03-01": [ "First Version Created." diff --git a/specs/signed_docs/docs/proposal_submission_action.cue b/specs/signed_docs/docs/proposal_submission_action.cue index 1db5557848..6d09f9a7fd 100644 --- a/specs/signed_docs/docs/proposal_submission_action.cue +++ b/specs/signed_docs/docs/proposal_submission_action.cue @@ -92,6 +92,33 @@ docs: #DocumentDefinitions & { for a collaborator it identified that they do not wish to be listed as a `collaborator`. """ schema: _ @embed(file="payload_schemas/proposal_submission_action.schema.json") + examples: [ + { + title: "Final Proposal Submission" + description: """ + This document indicates the linked proposal is final and requested to proceed for further consideration. + """ + example: _ @embed(file="payload_schemas/proposal_submission_action.final.example.json") + }, + { + title: "Draft Proposal Submission" + description: """ + This document indicates the linked proposal is no longer final and should not proceed for further consideration. + It is also used by collaborators to accept that they are a collaborator on a document. + """ + example: _ @embed(file="payload_schemas/proposal_submission_action.draft.example.json") + }, + { + title: "Hidden Proposal Submission" + description: """ + If submitted by the proposal author the document is hidden, it is still public but not shown as + a proposal being drafted. + If submitted by a collaborator, that collaborator is declaring they do not wish to be listed as + a collaborator on the proposal. + """ + example: _ @embed(file="payload_schemas/proposal_submission_action.hide.example.json") + }, + ] } "signers": { diff --git a/specs/signed_docs/documentation_links.cue b/specs/signed_docs/documentation_links.cue index 4083dd2d34..ff9f1bc98d 100644 --- a/specs/signed_docs/documentation_links.cue +++ b/specs/signed_docs/documentation_links.cue @@ -24,15 +24,16 @@ import ( documentationLinks: #namedLink documentationLinks: { - "RFC3629": "https://datatracker.ietf.org/doc/html/rfc3629" // UTF-8 - "RFC3986": "https://datatracker.ietf.org/doc/html/rfc3986" // URI - "RFC9562": "https://www.rfc-editor.org/rfc/rfc9562.html" // UUID - "RFC9562-V4": "https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-4" // UUID V4 - "RFC9562-V7": "https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7" // UUID V7 - "CC-BY-4.0": "https://creativecommons.org/licenses/by/4.0/legalcode" // CC BY 4.0 - "IPFS-CID": "https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid" // IPFS Content Identifier - "CBOR-TAG-42": "https://github.com/ipld/cid-cbor/" - "CBOR-TAG-37": "https://github.com/lucas-clemente/cbor-specs/blob/master/uuid.md" // IPLD content identifiers (CIDs) in CBOR + "RFC3629": "https://datatracker.ietf.org/doc/html/rfc3629" // UTF-8 + "RFC3986": "https://datatracker.ietf.org/doc/html/rfc3986" // URI + "RFC9562": "https://www.rfc-editor.org/rfc/rfc9562.html" // UUID + "RFC9562-V4": "https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-4" // UUID V4 + "RFC9562-V7": "https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7" // UUID V7 + "CC-BY-4.0": "https://creativecommons.org/licenses/by/4.0/legalcode" // CC BY 4.0 + "IPFS-CID": "https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid" // IPFS Content Identifier + "CBOR-TAG-42": "https://github.com/ipld/cid-cbor/" // IPLD content identifiers (CIDs) in CBOR + "CBOR-TAG-37": "https://github.com/lucas-clemente/cbor-specs/blob/master/uuid.md" // UUID Tag for CBOR + "CBOR-LFD-ENCODING": "https://www.rfc-editor.org/rfc/rfc8949.html#section-4.2.3" // CBOR length-first core deterministic encoding requirements } #allLinkNames: or([ @@ -52,4 +53,5 @@ linkAKA: { "UTF-8": "RFC3629" "CBOR Encoded IPLD Content Identifier": "CBOR-TAG-42" "IPFS CID": "IPFS-CID" + "CBOR Deterministic Encoding": "CBOR-LFD-ENCODING" } diff --git a/specs/signed_docs/payload.cue b/specs/signed_docs/payload.cue index f2dcbec41c..b7e1a379df 100644 --- a/specs/signed_docs/payload.cue +++ b/specs/signed_docs/payload.cue @@ -1,5 +1,19 @@ package signed_docs +import ( + "list" +) + +// Individual Payload Example +#payloadExample: { + // Title of the example + title: string + // Expanded description of what the example shows. + description: string + // Example data that matches the payload schema. + example: _ +} + // Payload definition _payload: { // Description of the payload @@ -7,4 +21,7 @@ _payload: { // Optional fixed schema for the payload. // A URI or inline JSON Schema that the payload must validate against. schema?: _ + // Examples of the schema. + examples?: list.UniqueItems + examples?: [...#payloadExample] | *[] }