From f47890bfca127f988249d6f3e0b4eb0929b14993 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 15 May 2025 17:46:32 +0700 Subject: [PATCH 01/42] fix(docs): correct python type annotations in documentation generator (#325) * feat(docs): Consolidate all parameters types into a single parameters reference. * fix(docs): Fix linked references * feat(docs): Start of adding capability to cluster like documents to simplify relationship diagrams. * fix(docs): wip fix of clustered documents * feat(docs): Add document clusters to help with autogenerated diagrams. * fix(docs): fix spelling * fix(Python): fix type * fix(docs): Inter doc links in diagrams * fix(docs): Neils Eyesight Soother * fix(docs): Rename Election Parameters to Decision parameters * fix(docs): python types * fix(docs): add missing doc generator type definitions * fix(general): Updater recommended vscode settings --- .vscode/settings.recommended.json | 12 +++- .../08_concepts/signed_doc/diagrams/all.dot | 2 +- specs/gen_docs/gen/doc_generator.py | 6 +- .../gen_docs/gen/doc_relationship_diagrams.py | 4 +- specs/gen_docs/gen/graphviz_doc_diagram.py | 39 ++++++++----- specs/gen_docs/spec/document.py | 23 ++++++-- specs/gen_docs/spec/signed_doc.py | 57 +++++++++++-------- 7 files changed, 91 insertions(+), 52 deletions(-) diff --git a/.vscode/settings.recommended.json b/.vscode/settings.recommended.json index c152c545fde..c63dff43ce8 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 d22921c2f9d..af9f30cf9e3 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"]; diff --git a/specs/gen_docs/gen/doc_generator.py b/specs/gen_docs/gen/doc_generator.py index f392378355b..aebfc401ba6 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 b7a0d68b2b0..7f3c74fc3ed 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/graphviz_doc_diagram.py b/specs/gen_docs/gen/graphviz_doc_diagram.py index 3c2ec65b704..2c1d78ce068 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/spec/document.py b/specs/gen_docs/spec/document.py index 1f9e8a9d396..c9c54143470 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/signed_doc.py b/specs/gen_docs/spec/signed_doc.py index e9f832b3619..ad1ae1d7714 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) From 3ffc8e56273f132d9a4f80407cc9d53f5efdb9a6 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Fri, 16 May 2025 16:15:57 +0700 Subject: [PATCH 02/42] docs(docs): Better define the document encoding restrictions. (#326) --- .../signed_doc/docs/brand_parameters.md | 2 +- .../signed_doc/docs/campaign_parameters.md | 2 +- .../signed_doc/docs/category_parameters.md | 2 +- .../docs/comment_moderation_action.md | 2 +- .../signed_doc/docs/decision_parameters.md | 2 +- .../08_concepts/signed_doc/docs/proposal.md | 2 +- .../signed_doc/docs/proposal_comment.md | 2 +- .../docs/proposal_comment_meta_template.md | 2 +- .../docs/proposal_comment_template.md | 2 +- .../signed_doc/docs/proposal_meta_template.md | 2 +- .../docs/proposal_moderation_action.md | 2 +- .../docs/proposal_submission_action.md | 2 +- .../signed_doc/docs/proposal_template.md | 2 +- .../08_concepts/signed_doc/metadata.md | 2 +- .../08_concepts/signed_doc/spec.md | 45 ++++++++++++++++++- .../08_concepts/signed_doc/types.md | 2 +- specs/gen_docs/gen/spec_md.py | 36 ++++++++++++++- specs/signed_doc.json | 7 +++ specs/signed_docs/authors_copyright.cue | 11 +++++ specs/signed_docs/documentation_links.cue | 20 +++++---- 20 files changed, 123 insertions(+), 26 deletions(-) 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 6e74a9b972a..8f2571f9e8d 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 @@ -112,7 +112,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/campaign_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters.md index 40b40909c13..8836c1999aa 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 @@ -130,7 +130,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/category_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters.md index 07f51561392..7f123e98fcf 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 @@ -130,7 +130,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/comment_moderation_action.md b/docs/src/architecture/08_concepts/signed_doc/docs/comment_moderation_action.md index 5b9907ca1fc..e8bd4caf859 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 95e049ecf24..dc128901baf 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 @@ -132,7 +132,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.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md index c11ad6354e9..70bffb13653 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 212b50e7b49..984dd48cf34 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 305e9d497f8..73280ae4f79 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 91c7b241f96..ff64f268527 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 9ff14e88107..dd91bf81851 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 b8236d45972..8792ac43684 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 68d7f89c2e0..c6647234c2b 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 @@ -260,7 +260,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 b01b6eb41cd..53ac87aff1b 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 7b6fdc2e130..8daa80ac974 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 f2cc3a81bbb..222eff96a07 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 c9b878b78e1..35c823f1a52 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/spec_md.py b/specs/gen_docs/gen/spec_md.py index bd8638c8dbe..f70b4345ac6 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/signed_doc.json b/specs/signed_doc.json index 9706ba0d6b0..0f99c89676b 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" } ] }, @@ -2066,6 +2071,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 +2103,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 c354a5b10ee..2d9a8314d85 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/documentation_links.cue b/specs/signed_docs/documentation_links.cue index 4083dd2d34b..ff9f1bc98df 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" } From e4d08195f48554270a92241d9e12a12a0b4fdbef Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 21 May 2025 11:18:43 +0700 Subject: [PATCH 03/42] feat(docs): Add examples for predefined document schemas (#342) --- .../docs/proposal_submission_action.md | 133 +++++--- specs/gen_docs/gen/docs_page_md.py | 22 +- specs/gen_docs/pyproject.toml | 1 + specs/gen_docs/spec/payload.py | 108 +++++++ specs/gen_docs/uv.lock | 298 +++++++++++++++--- specs/signed_doc.json | 23 ++ ...posal_submission_action.draft.example.json | 3 + ...posal_submission_action.final.example.json | 3 + ...oposal_submission_action.hide.example.json | 3 + .../docs/proposal_submission_action.cue | 27 ++ specs/signed_docs/payload.cue | 17 + 11 files changed, 539 insertions(+), 99 deletions(-) create mode 100644 specs/signed_docs/docs/payload_schemas/proposal_submission_action.draft.example.json create mode 100644 specs/signed_docs/docs/payload_schemas/proposal_submission_action.final.example.json create mode 100644 specs/signed_docs/docs/payload_schemas/proposal_submission_action.hide.example.json 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 c6647234c2b..e15b76b4be6 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 diff --git a/specs/gen_docs/gen/docs_page_md.py b/specs/gen_docs/gen/docs_page_md.py index 970f2d48369..b07c17f4401 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/pyproject.toml b/specs/gen_docs/pyproject.toml index 6626530ffbd..5ac71cbe38c 100644 --- a/specs/gen_docs/pyproject.toml +++ b/specs/gen_docs/pyproject.toml @@ -5,6 +5,7 @@ description = "Generate Signed Document documentation files." readme = "README.md" requires-python = ">=3.13" 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/payload.py b/specs/gen_docs/spec/payload.py index 732682508cc..3caa4efdc04 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/uv.lock b/specs/gen_docs/uv.lock index 5a05c6644e6..06aaec055aa 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 0f99c89676b..a5064f6d38e 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -1861,6 +1861,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#", 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 00000000000..747d3b6ec76 --- /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 00000000000..bfbf15e59d6 --- /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 00000000000..e6f023094f8 --- /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/proposal_submission_action.cue b/specs/signed_docs/docs/proposal_submission_action.cue index 1db55578483..6d09f9a7fd1 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/payload.cue b/specs/signed_docs/payload.cue index f2dcbec41c4..b7e1a379dfe 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] | *[] } From 384b49e4c27b156cf77229e47e1a940a4ded9329 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 7 Jun 2025 00:04:38 +0700 Subject: [PATCH 04/42] format the blueprint.cue --- blueprint.cue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blueprint.cue b/blueprint.cue index 9e7e947060e..df7a47a1e1b 100644 --- a/blueprint.cue +++ b/blueprint.cue @@ -12,9 +12,9 @@ global: { ] providers: { aws: { - region: "eu-central-1" + region: "eu-central-1" ecr: registry: "332405224602.dkr.ecr.eu-central-1.amazonaws.com" - role: "arn:aws:iam::332405224602:role/ci" + role: "arn:aws:iam::332405224602:role/ci" } docker: credentials: { From 39940597c1a7da6b438aad62b7b61eaea740930e Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 7 Jun 2025 00:05:10 +0700 Subject: [PATCH 05/42] fix(docs): Update module to latest cue version --- specs/cue.mod/module.cue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/cue.mod/module.cue b/specs/cue.mod/module.cue index aad96b47e77..c882948267f 100644 --- a/specs/cue.mod/module.cue +++ b/specs/cue.mod/module.cue @@ -1,4 +1,4 @@ -module: "github.com/input-output-hk/catalyst-libs/specs" +module: "github.com/input-output-hk/catalyst-libs/specs@v0" language: { - version: "v0.11.2" + version: "v0.13.0" } From 15ee554298144be877591bc6fd318912b9b97145 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 7 Jun 2025 00:06:11 +0700 Subject: [PATCH 06/42] feat(docs): WIP formalized definitions of field definitions for json schema templates --- specs/signed_doc.json | 211 +++++++++++++- specs/signed_docs/metadata.cue | 1 - .../template_schema_defs_dictionary.cue | 267 ++++++++++++++++++ 3 files changed, 477 insertions(+), 2 deletions(-) create mode 100644 specs/signed_docs/template_schema_defs_dictionary.cue diff --git a/specs/signed_doc.json b/specs/signed_doc.json index a5064f6d38e..106f312825e 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -2300,5 +2300,214 @@ "collaborators", "revocations", "parameters" - ] + ], + "templateJsonSchemaDefs": { + "schemaReferenceNonUI": { + "definition": { + "$comment": "Enforces the json document having a proper reference to the schema.", + "readOnly": true, + "type": "string" + }, + "description": "Enforces the json document having a proper reference to the schema.", + "parameters": { + "const": { + "description": "The path must always be this value. **MUST** match `default`.", + "required": "yes", + "type": "string" + }, + "default": { + "description": "The path that is defined to find the matching json schema.", + "required": "yes", + "type": "string" + } + } + }, + "section": { + "definition": { + "$comment": "UI - Logical Document Sub-Section Break.", + "additionalProperties": false, + "type": "object", + "x-note": "Subsections containing specific details about the proposal." + }, + "description": "UI - Logical Document Sub-Section Break.", + "parameters": { + "description": { + "description": "The displayable description attached to the section. Markdown formatted contents.", + "required": "optional", + "type": "string" + }, + "properties": { + "description": "The sub fields of the section.", + "required": "yes", + "type": "string" + }, + "required": { + "description": "Which fields MUST appear in the segment.", + "required": "optional", + "type": "string" + }, + "title": { + "description": "The title of the section.", + "required": "yes", + "type": "string" + }, + "x-icon": { + "choices": [ + "light-bulb", + "view-grid", + "top-bar", + "tag", + "chart-pie", + "flag", + "presentation-chart-line", + "double_check" + ], + "description": "The name of the Icon to display with the field.", + "required": "optional", + "type": "string" + }, + "x-order": { + "description": "The ordering of the properties to be enforced when displayed.\nAny field not listed here will get displayed in an arbitrary order.", + "required": "yes", + "type": "string" + } + }, + "parent": "segment" + }, + "segment": { + "definition": { + "$comment": "Logical Document Section - Grouping Only - Highest Level Group", + "additionalProperties": false, + "type": "object", + "x-note": "Major sections of the proposal. Each segment contains sections of information grouped together." + }, + "description": "Logical Document Section - Grouping Only - Highest Level Group", + "parameters": { + "description": { + "description": "The displayable description attached to the segment. Markdown formatted contents.", + "required": "optional", + "type": "string" + }, + "properties": { + "description": "The sub fields of the segment.", + "required": "yes", + "type": "string" + }, + "required": { + "description": "Which fields MUST appear in the segment.", + "required": "optional", + "type": "string" + }, + "title": { + "description": "The title of the segment.", + "required": "yes", + "type": "string" + }, + "x-icon": { + "choices": [ + "light-bulb", + "view-grid", + "top-bar", + "tag", + "chart-pie", + "flag", + "presentation-chart-line", + "double_check" + ], + "description": "The name of the Icon to display with the field.", + "required": "optional", + "type": "string" + }, + "x-order": { + "description": "The ordering of the properties to be enforced when displayed.\nAny field not listed here will get displayed in an arbitrary order.", + "required": "yes", + "type": "string" + } + } + }, + "singleLineHttpsURLEntry": { + "definition": { + "$comment": "UI - Single Line text entry for HTTPS Urls.", + "format": "uri", + "pattern": "^https://[^\\s]+$", + "type": "string", + "x-note": "Must start with 'https://' and is followed by one or more \nnon-whitespace characters, ending at the end of the string." + }, + "description": "UI - Single Line text entry for HTTPS Urls.", + "parameters": { + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "maxLength": { + "description": "Maximum number of characters allowed in the field.", + "required": "yes", + "type": "integer" + }, + "minLength": { + "description": "Minimum number of characters allowed in the field.", + "required": "yes", + "type": "integer" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + }, + "x-placeholder": { + "description": "Placeholder text to display inside the field if it is empty.", + "required": "optional", + "type": "string" + } + } + }, + "singleLineTextEntry": { + "definition": { + "$comment": "UI - Single Line text entry without any markup or rich text capability.", + "contentMediaType": "text/plain", + "pattern": "^.*$", + "type": "string", + "x-note": "Enter a single line of text.\nNo formatting, line breaks, or special characters are allowed." + }, + "description": "UI - Single Line text entry without any markup or rich text capability.", + "parameters": { + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "maxLength": { + "description": "Maximum number of characters allowed in the field.", + "required": "yes", + "type": "integer" + }, + "minLength": { + "description": "Minimum number of characters allowed in the field.", + "required": "yes", + "type": "integer" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + }, + "x-placeholder": { + "description": "Placeholder text to display inside the field if it is empty.", + "required": "optional", + "type": "string" + } + } + } + } } diff --git a/specs/signed_docs/metadata.cue b/specs/signed_docs/metadata.cue index d814c80b063..b1952e70f61 100644 --- a/specs/signed_docs/metadata.cue +++ b/specs/signed_docs/metadata.cue @@ -6,7 +6,6 @@ package signed_docs import ( "list" "github.com/input-output-hk/catalyst-libs/specs/generic:optional" - ) // Metadata Formats. diff --git a/specs/signed_docs/template_schema_defs_dictionary.cue b/specs/signed_docs/template_schema_defs_dictionary.cue new file mode 100644 index 00000000000..7e90a27b61c --- /dev/null +++ b/specs/signed_docs/template_schema_defs_dictionary.cue @@ -0,0 +1,267 @@ +// Template Json Schema Definitions Dictionary +// +// All known and supported Json Schema definitions, +// and their parameters and documentation so that +// a dictionary document and the definitions themselves +// can be generated. +package signed_docs + +import ( + "list" + "regexp" + "github.com/input-output-hk/catalyst-libs/specs/generic:optional" +) + +#fieldType: *"string" | + "object" | + "array" | + "integer" | + "boolean" + +_x_icon_choices: list.UniqueItems +_x_icon_choices: [ + "light-bulb", + "view-grid", + "top-bar", + "tag", + "chart-pie", + "flag", + "presentation-chart-line", + "double_check", +] + +#xIconChoices: or(_x_icon_choices) + +_format_choices: list.Sort([ + "uri", + "path", +], list.Ascending) + +_content_choices: list.Sort([ + "text/plain", + "text/markdown", +], list.Ascending) + +_jsonParameter: { + description: string + required: optional.#field + type: #fieldType + choices?: [...string] +} + +_regexTextPlain: "^.*$" +_regexHTTPSUrl: "^https://[^\\s]+$" + +// A JSON Schema field definition +#jsonSchemaFieldDefinition: { + // Documentation + description: string + + // MAPS to the `definitions` section within JSON Schema draft 7. + definition: { + "$comment": description + type: #fieldType + readOnly?: bool & true // IF true, is not a data entry field, but can be used for presentation and formatting. + format?: string & or(_format_choices) + contentMediaType?: string & or(_content_choices) + pattern?: regexp.Valid + + if type == "object" { + additionalProperties: bool & false // IF false, can not define extra fields. + } + + "x-note"?: string + } + + parent?: #templateJsonSchemaDefNames + + // The parameters supported by a particular field definition + parameters: { + title?: _jsonParameter & { + description: _ | *"The label attached to the field." + required: "yes" + } + description?: _jsonParameter & { + description: _ | *"The description of the field presented during data entry." + required: "optional" + } + required?: _jsonParameter & { + required: _ | *"optional" + } + default?: _jsonParameter & { + required: _ | *"yes" + } + const?: _jsonParameter & { + required: _ | *"yes" + } + properties?: _jsonParameter & { + required: _ | *"yes" + description: _ | *"All sub fields contained in the object." + required: "yes" + } + minLength?: _jsonParameter & { + type: "integer" + description: _ | *"Minimum number of characters allowed in the field." + required: "yes" + } + maxLength?: _jsonParameter & { + type: "integer" + description: _ | *"Maximum number of characters allowed in the field." + required: "yes" + } + "x-guidance"?: _jsonParameter & { + description: _ | *"Long form Markdown formatted description to give guidance about how the field is to be completed." + required: "optional" + } + "x-placeholder"?: _jsonParameter & { + description: _ | *"Placeholder text to display inside the field if it is empty." + required: "optional" + } + "x-icon"?: _jsonParameter & { + description: _ | *"The name of the Icon to display with the field." + required: "optional" + choices: _x_icon_choices + } + "x-order"?: _jsonParameter & { + required: "yes" + description: """ + The ordering of the properties to be enforced when displayed. + Any field not listed here will get displayed in an arbitrary order. + """ + } + } +} + +#jsonSchemaFields: { + [string]: #jsonSchemaFieldDefinition +} + +// Types of a Metadata Fields +#templateJsonSchemaDefNames: or([ + for k, _ in templateJsonSchemaDefs {k}, +]) + +// Definitions for all defined template schema field types. +templateJsonSchemaDefs: #jsonSchemaFields & { + "schemaReferenceNonUI": { + description: """ + Enforces the json document having a proper reference to the schema. + """ + definition: { + type: "string" + readOnly: true + } + + parameters: { + default: { + description: "The path that is defined to find the matching json schema." + required: "yes" + } + const: { + description: "The path must always be this value. **MUST** match `default`." + required: "yes" + } + } + } + + "segment": { + description: """ + Logical Document Section - Grouping Only - Highest Level Group + """ + definition: { + type: "object" + "x-note": """ + Major sections of the proposal. Each segment contains sections of information grouped together. + """ + } + parameters: { + title: { + description: "The title of the segment." + } + description: { + description: "The displayable description attached to the segment. Markdown formatted contents." + } + properties: { + description: "The sub fields of the segment." + } + required: { + description: "Which fields MUST appear in the segment." + required: "optional" + } + "x-icon": {} + "x-order": {} + } + } + + "section": { + description: "UI - Logical Document Sub-Section Break." + parent: "segment" + definition: { + type: "object" + "x-note": """ + Subsections containing specific details about the proposal. + """ + } + parameters: { + title: { + description: "The title of the section." + required: "yes" + } + description: { + description: "The displayable description attached to the section. Markdown formatted contents." + } + properties: { + description: "The sub fields of the section." + } + required: { + description: "Which fields MUST appear in the segment." + required: "optional" + } + "x-icon": {} + "x-order": {} + } + } + + "singleLineTextEntry": { + description: "UI - Single Line text entry without any markup or rich text capability." + definition: { + type: "string" + contentMediaType: "text/plain" + pattern: _regexTextPlain + "x-note": """ + Enter a single line of text. + No formatting, line breaks, or special characters are allowed. + """ + } + parameters: { + title: {} + description: {} + minLength: {} + maxLength: {} + "x-guidance": {} + "x-placeholder": {} + } + } + + "singleLineHttpsURLEntry": { + description: "UI - Single Line text entry for HTTPS Urls." + definition: { + type: "string" + format: "uri" + pattern: _regexHTTPSUrl + "x-note": """ + Must start with 'https://' and is followed by one or more + non-whitespace characters, ending at the end of the string. + """ + } + parameters: { + title: {} + description: {} + minLength: {} + maxLength: {} + "x-guidance": {} + "x-placeholder": {} + } + } + +} From 3ae720a69e0d3360c86272cbb15ddfb4ea2d4170 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 8 Jun 2025 17:55:06 +0700 Subject: [PATCH 07/42] feat(docs): WIP --- .config/dictionaries/project.dic | 1 + specs/Justfile | 4 +- specs/signed_doc.json | 775 +++++++++++++++++- specs/signed_docs/signed_doc.cue | 3 + .../template_schema_defs_dictionary.cue | 267 ------ specs/template_field_definitions/choices.cue | 27 + .../template_field_definitions/dictionary.cue | 20 + specs/template_field_definitions/field.cue | 45 + .../fields/drop_down_single_select.cue | 26 + .../fields/multi_line_text_entry.cue | 26 + .../fields/multi_line_text_entry_markdown.cue | 29 + .../fields/multi_select.cue | 28 + .../fields/radio_button_select.cue | 26 + .../fields/schema_reference.cue | 25 + .../fields/section.cue | 31 + .../fields/segment.cue | 29 + .../fields/single_line_https_url_entry.cue | 27 + .../fields/single_line_text_entry.cue | 25 + .../icon_choices.cue | 283 +++++++ .../template_field_definitions/parameters.cue | 109 +++ specs/template_field_definitions/patterns.cue | 6 + 21 files changed, 1515 insertions(+), 297 deletions(-) delete mode 100644 specs/signed_docs/template_schema_defs_dictionary.cue create mode 100644 specs/template_field_definitions/choices.cue create mode 100644 specs/template_field_definitions/dictionary.cue create mode 100644 specs/template_field_definitions/field.cue create mode 100644 specs/template_field_definitions/fields/drop_down_single_select.cue create mode 100644 specs/template_field_definitions/fields/multi_line_text_entry.cue create mode 100644 specs/template_field_definitions/fields/multi_line_text_entry_markdown.cue create mode 100644 specs/template_field_definitions/fields/multi_select.cue create mode 100644 specs/template_field_definitions/fields/radio_button_select.cue create mode 100644 specs/template_field_definitions/fields/schema_reference.cue create mode 100644 specs/template_field_definitions/fields/section.cue create mode 100644 specs/template_field_definitions/fields/segment.cue create mode 100644 specs/template_field_definitions/fields/single_line_https_url_entry.cue create mode 100644 specs/template_field_definitions/fields/single_line_text_entry.cue create mode 100644 specs/template_field_definitions/icon_choices.cue create mode 100644 specs/template_field_definitions/parameters.cue create mode 100644 specs/template_field_definitions/patterns.cue diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index 79bec3d5024..b92e54d10ba 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -230,6 +230,7 @@ pypackages pytest pytype qpsg +qrcode quic rankdir rapidoc diff --git a/specs/Justfile b/specs/Justfile index 1733cf995d8..5e2d5af2b0b 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -11,14 +11,16 @@ default: # So it should only be run when required. fix: cue fix ./signed_docs/docs:signed_docs + cue fix ./template_field_definitions/fields:template_field_definitions # Fix the format of cue files format: - cue fmt --files . + cue fmt -s --files . # Check the signed document cue files are valid. check: format cue vet ./signed_docs/docs:signed_docs -c + cue vet ./template_field_definitions/fields:template_field_definitions -c # Regenerate the full signed document specification json file. regenerate-signed-doc-json: diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 106f312825e..e758e66669c 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -2302,9 +2302,216 @@ "parameters" ], "templateJsonSchemaDefs": { + "dropDownSingleSelect": { + "definition": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "contentMediaType": "text/plain", + "format": "dropDownSingleSelect", + "pattern": "^.*$", + "type": "string" + }, + "description": "UI - Drop Down Selection of a single entry from the defined enum.\n\nSelect one option from a selector styled as a dropdown menu.\nOnly one choice is allowed.", + "parameters": { + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "enum": { + "description": "An array of string to select from.", + "items": { + "description": "An element of the Enum.", + "required": "excluded", + "type": "string" + }, + "required": "yes", + "type": "array" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + } + } + }, + "multiLineTextEntry": { + "definition": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "contentMediaType": "text/plain", + "pattern": "^[\\S\\s]*$", + "type": "string" + }, + "description": "UI - One or more Lines of text entry.\nLine breaks, and special characters are allowed.\nSpecial formatted markup, such as Markdown are not allowed.\nEnter multiple lines of plain text. You can use line breaks but no special formatting.", + "parameters": { + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "maxLength": { + "description": "Maximum number of characters allowed in the field.", + "required": "yes", + "type": "integer" + }, + "minLength": { + "description": "Minimum number of characters allowed in the field.", + "required": "optional", + "type": "integer" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + }, + "x-placeholder": { + "description": "Placeholder text to display inside the field if it is empty.", + "required": "optional", + "type": "string" + } + } + }, + "multiLineTextEntryMarkdown": { + "definition": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "contentMediaType": "text/markdown", + "pattern": "^[\\S\\s]*$", + "type": "string" + }, + "description": "UI - Multiline text entry with Markdown content.\nUse Markdown formatting for rich text. \nMarkdown formatting is as defined by \n\nThe following Markdown Extensions are also supported:\n\n* None", + "parameters": { + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "maxLength": { + "description": "Maximum number of characters allowed in the field.", + "required": "yes", + "type": "integer" + }, + "minLength": { + "description": "Minimum number of characters allowed in the field.", + "required": "optional", + "type": "integer" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + }, + "x-placeholder": { + "description": "Placeholder text to display inside the field if it is empty.", + "required": "optional", + "type": "string" + } + } + }, + "multiSelect": { + "definition": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "items": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "contentMediaType": "text/plain", + "pattern": "^.*$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "description": "UI - Multiselect from the given items.\n\nSelect multiple options from the dropdown menu.\nMultiple choices are allowed.\nAll choices MUST be unique.", + "parameters": { + "contains": { + "description": "The choices the multi select can contain.", + "items": { + "description": "An individual Choice.", + "required": "excluded", + "type": "string" + }, + "required": "yes", + "type": "array" + }, + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "maxItems": { + "description": "An array instance is valid against \"maxItems\" if its size is less than, or equal to, the value of this keyword.", + "required": "yes", + "type": "integer" + }, + "minItems": { + "description": "An array instance is valid against \"minItems\" if its size is greater than, or equal to, the value of this keyword.", + "required": "optional", + "type": "integer" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + } + } + }, + "radioButtonSelect": { + "definition": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "contentMediaType": "text/plain", + "format": "radioButtonSelect", + "pattern": "^.*$", + "type": "string" + }, + "description": "UI - Radio Button Selection.\n\nSelect one option from a list of text options.\nSelector is styled as a set of Radio Buttons.", + "parameters": { + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "enum": { + "description": "An array of string to select from.", + "items": { + "description": "An element of the Enum.", + "required": "excluded", + "type": "string" + }, + "required": "yes", + "type": "array" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + } + } + }, "schemaReferenceNonUI": { "definition": { - "$comment": "Enforces the json document having a proper reference to the schema.", + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "readOnly": true, "type": "string" }, @@ -2324,12 +2531,11 @@ }, "section": { "definition": { - "$comment": "UI - Logical Document Sub-Section Break.", + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "additionalProperties": false, - "type": "object", - "x-note": "Subsections containing specific details about the proposal." + "type": "object" }, - "description": "UI - Logical Document Sub-Section Break.", + "description": "UI - Logical Document Sub-Section Break.\nSubsections containing specific details about the proposal.", "parameters": { "description": { "description": "The displayable description attached to the section. Markdown formatted contents.", @@ -2353,14 +2559,271 @@ }, "x-icon": { "choices": [ - "light-bulb", - "view-grid", - "top-bar", - "tag", + "'all spaces menu'", + "'all spaces menu-1'", + "academic-cap", + "ada", + "adjustments", + "annotation", + "archive", + "arrow-circle-down", + "arrow-circle-left", + "arrow-circle-right", + "arrow-circle-up", + "arrow-down", + "arrow-left", + "arrow-narrow-down", + "arrow-narrow-left", + "arrow-narrow-right", + "arrow-narrow-up", + "arrow-right", + "arrow-triangle-down", + "arrow-triangle-up", + "arrow-up", + "arrows-expand", + "at-symbol", + "avatar_placeholder", + "backspace", + "badge-check", + "ban", + "beaker", + "bell", + "book-open", + "bookmark", + "bookmark-alt", + "bottom-main-content", + "bottom-rail-toggle", + "bottom-rail-toggle-1", + "briefcase", + "cake", + "calculator", + "calendar", + "camera", + "cash", + "chart-bar", "chart-pie", + "chart-square-bar", + "chat", + "chat-alt", + "chat-alt-2", + "check", + "check-circle", + "chevron-double-down", + "chevron-double-left", + "chevron-double-right", + "chevron-double-up", + "chevron-down", + "chevron-down-1", + "chevron-left", + "chevron-right", + "chevron-up", + "chip", + "clipboard", + "clipboard-check", + "clipboard-copy", + "clipboard-list", + "clock", + "cloud", + "cloud-download", + "cloud-upload", + "code", + "cog-gear", + "collection", + "color-swatch", + "credit-card", + "cube", + "cube-transparent", + "currency-bangladeshi", + "currency-dollar", + "currency-euro", + "currency-pound", + "currency-rupee", + "currency-yen", + "cursor-click", + "curved-arrow-right", + "database", + "desktop-computer", + "device-mobile", + "device-tablet", + "document", + "document-add", + "document-remove", + "document-report", + "document-search", + "document-text", + "dots-circle-horizontal", + "dots-horizontal", + "dots-vertical", + "double_check", + "download", + "duplicate", + "emoji-happy", + "emoji-sad", + "exclamation", + "exclamation-circle", + "external-link", + "eye", + "eye-off", + "facebook", + "fast-forward", + "film", + "filter", + "finger-print", + "fire", "flag", + "folder", + "folder-add", + "folder-download", + "folder-open", + "folder-remove", + "fund", + "gift", + "globe", + "globe-alt", + "hand", + "hashtag", + "heart", + "home", + "icon-user-remove", + "identification", + "inbox", + "inbox-in", + "information-circle", + "key", + "left-rail-toggle", + "library", + "light-bulb", + "lightning-bolt", + "link", + "linkedin", + "location-marker", + "lock-closed", + "lock-open", + "logout", + "logout-1", + "mail", + "mail-open", + "map", + "maximize-toggle", + "menu", + "menu-alt-1", + "menu-alt-2", + "menu-alt-3", + "menu-alt-4", + "microphone", + "minimize-toggle", + "minus", + "minus-circle", + "moon", + "move-item", + "music-note", + "newspaper", + "node-closed", + "node-line", + "node-line-end", + "node-open", + "office-building", + "paper-airplane", + "paper-clip", + "pause", + "pencil", + "pencil-alt", + "phone", + "phone-incoming", + "phone-missed-call", + "phone-outgoing", + "photograph", + "play", + "plus", + "plus_circle_filled", + "plus_circle_outlined", + "presentation-chart-bar", "presentation-chart-line", - "double_check" + "printer", + "progress-track-warning", + "puzzle", + "qrcode", + "question-mark-circle", + "receipt-refund", + "receipt-tax", + "reddit", + "refresh", + "reply", + "rewind", + "right-rail-toggle", + "rss", + "rt_bold", + "rt_decrease_indent", + "rt_heading", + "rt_increase_indent", + "rt_italic", + "rt_ordered_list", + "rt_unordered_list", + "save", + "save-as", + "scale", + "scissors", + "search", + "search-circle", + "selector", + "send-airplane", + "server", + "share", + "shield-check", + "shield-exclamation", + "shopping-bag", + "shopping-cart", + "sm-view-grid-add", + "sort-ascending", + "sort-descending", + "sparkles", + "speakerphone", + "star_filled", + "star_outlined", + "status-offline", + "status-online", + "stop", + "summary", + "sun", + "support", + "switch-horizontal", + "switch-vertical", + "table", + "tag", + "template", + "terminal", + "thumb-down", + "thumb-up", + "ticket", + "top-bar", + "top-bar-filled", + "translate", + "trash", + "trending-down", + "trending-up", + "truck", + "unlink", + "upload", + "user", + "user-add", + "user-circle", + "user-group", + "users", + "variable", + "video-camera", + "view-boards", + "view-grid", + "view-list", + "volume-off", + "volume-up", + "vote", + "wallet", + "wifi", + "x", + "x-circle", + "xTwitter", + "zoom-in", + "zoom-out" ], "description": "The name of the Icon to display with the field.", "required": "optional", @@ -2376,12 +2839,11 @@ }, "segment": { "definition": { - "$comment": "Logical Document Section - Grouping Only - Highest Level Group", + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "additionalProperties": false, - "type": "object", - "x-note": "Major sections of the proposal. Each segment contains sections of information grouped together." + "type": "object" }, - "description": "Logical Document Section - Grouping Only - Highest Level Group", + "description": "Logical Document Section - Grouping Only - Highest Level Group\n\"x-note\": \"\n\tMajor sections of the proposal. Each segment contains sections of information grouped together.\n\t\"", "parameters": { "description": { "description": "The displayable description attached to the segment. Markdown formatted contents.", @@ -2405,14 +2867,271 @@ }, "x-icon": { "choices": [ - "light-bulb", - "view-grid", - "top-bar", - "tag", + "'all spaces menu'", + "'all spaces menu-1'", + "academic-cap", + "ada", + "adjustments", + "annotation", + "archive", + "arrow-circle-down", + "arrow-circle-left", + "arrow-circle-right", + "arrow-circle-up", + "arrow-down", + "arrow-left", + "arrow-narrow-down", + "arrow-narrow-left", + "arrow-narrow-right", + "arrow-narrow-up", + "arrow-right", + "arrow-triangle-down", + "arrow-triangle-up", + "arrow-up", + "arrows-expand", + "at-symbol", + "avatar_placeholder", + "backspace", + "badge-check", + "ban", + "beaker", + "bell", + "book-open", + "bookmark", + "bookmark-alt", + "bottom-main-content", + "bottom-rail-toggle", + "bottom-rail-toggle-1", + "briefcase", + "cake", + "calculator", + "calendar", + "camera", + "cash", + "chart-bar", "chart-pie", + "chart-square-bar", + "chat", + "chat-alt", + "chat-alt-2", + "check", + "check-circle", + "chevron-double-down", + "chevron-double-left", + "chevron-double-right", + "chevron-double-up", + "chevron-down", + "chevron-down-1", + "chevron-left", + "chevron-right", + "chevron-up", + "chip", + "clipboard", + "clipboard-check", + "clipboard-copy", + "clipboard-list", + "clock", + "cloud", + "cloud-download", + "cloud-upload", + "code", + "cog-gear", + "collection", + "color-swatch", + "credit-card", + "cube", + "cube-transparent", + "currency-bangladeshi", + "currency-dollar", + "currency-euro", + "currency-pound", + "currency-rupee", + "currency-yen", + "cursor-click", + "curved-arrow-right", + "database", + "desktop-computer", + "device-mobile", + "device-tablet", + "document", + "document-add", + "document-remove", + "document-report", + "document-search", + "document-text", + "dots-circle-horizontal", + "dots-horizontal", + "dots-vertical", + "double_check", + "download", + "duplicate", + "emoji-happy", + "emoji-sad", + "exclamation", + "exclamation-circle", + "external-link", + "eye", + "eye-off", + "facebook", + "fast-forward", + "film", + "filter", + "finger-print", + "fire", "flag", + "folder", + "folder-add", + "folder-download", + "folder-open", + "folder-remove", + "fund", + "gift", + "globe", + "globe-alt", + "hand", + "hashtag", + "heart", + "home", + "icon-user-remove", + "identification", + "inbox", + "inbox-in", + "information-circle", + "key", + "left-rail-toggle", + "library", + "light-bulb", + "lightning-bolt", + "link", + "linkedin", + "location-marker", + "lock-closed", + "lock-open", + "logout", + "logout-1", + "mail", + "mail-open", + "map", + "maximize-toggle", + "menu", + "menu-alt-1", + "menu-alt-2", + "menu-alt-3", + "menu-alt-4", + "microphone", + "minimize-toggle", + "minus", + "minus-circle", + "moon", + "move-item", + "music-note", + "newspaper", + "node-closed", + "node-line", + "node-line-end", + "node-open", + "office-building", + "paper-airplane", + "paper-clip", + "pause", + "pencil", + "pencil-alt", + "phone", + "phone-incoming", + "phone-missed-call", + "phone-outgoing", + "photograph", + "play", + "plus", + "plus_circle_filled", + "plus_circle_outlined", + "presentation-chart-bar", "presentation-chart-line", - "double_check" + "printer", + "progress-track-warning", + "puzzle", + "qrcode", + "question-mark-circle", + "receipt-refund", + "receipt-tax", + "reddit", + "refresh", + "reply", + "rewind", + "right-rail-toggle", + "rss", + "rt_bold", + "rt_decrease_indent", + "rt_heading", + "rt_increase_indent", + "rt_italic", + "rt_ordered_list", + "rt_unordered_list", + "save", + "save-as", + "scale", + "scissors", + "search", + "search-circle", + "selector", + "send-airplane", + "server", + "share", + "shield-check", + "shield-exclamation", + "shopping-bag", + "shopping-cart", + "sm-view-grid-add", + "sort-ascending", + "sort-descending", + "sparkles", + "speakerphone", + "star_filled", + "star_outlined", + "status-offline", + "status-online", + "stop", + "summary", + "sun", + "support", + "switch-horizontal", + "switch-vertical", + "table", + "tag", + "template", + "terminal", + "thumb-down", + "thumb-up", + "ticket", + "top-bar", + "top-bar-filled", + "translate", + "trash", + "trending-down", + "trending-up", + "truck", + "unlink", + "upload", + "user", + "user-add", + "user-circle", + "user-group", + "users", + "variable", + "video-camera", + "view-boards", + "view-grid", + "view-list", + "volume-off", + "volume-up", + "vote", + "wallet", + "wifi", + "x", + "x-circle", + "xTwitter", + "zoom-in", + "zoom-out" ], "description": "The name of the Icon to display with the field.", "required": "optional", @@ -2427,13 +3146,12 @@ }, "singleLineHttpsURLEntry": { "definition": { - "$comment": "UI - Single Line text entry for HTTPS Urls.", + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "format": "uri", "pattern": "^https://[^\\s]+$", - "type": "string", - "x-note": "Must start with 'https://' and is followed by one or more \nnon-whitespace characters, ending at the end of the string." + "type": "string" }, - "description": "UI - Single Line text entry for HTTPS Urls.", + "description": "UI - Single Line text entry for HTTPS Urls.\n\"x-note\": \n\tMust start with 'https://' and is followed by one or more \n\tnon-whitespace characters, ending at the end of the string.\n\t", "parameters": { "description": { "description": "The description of the field presented during data entry.", @@ -2447,7 +3165,7 @@ }, "minLength": { "description": "Minimum number of characters allowed in the field.", - "required": "yes", + "required": "optional", "type": "integer" }, "title": { @@ -2469,13 +3187,12 @@ }, "singleLineTextEntry": { "definition": { - "$comment": "UI - Single Line text entry without any markup or rich text capability.", + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "contentMediaType": "text/plain", "pattern": "^.*$", - "type": "string", - "x-note": "Enter a single line of text.\nNo formatting, line breaks, or special characters are allowed." + "type": "string" }, - "description": "UI - Single Line text entry without any markup or rich text capability.", + "description": "UI - Single Line text entry without any markup or rich text capability.\nA single line of text.\nNo formatting, markup, line breaks, or special characters are allowed.", "parameters": { "description": { "description": "The description of the field presented during data entry.", @@ -2489,7 +3206,7 @@ }, "minLength": { "description": "Minimum number of characters allowed in the field.", - "required": "yes", + "required": "optional", "type": "integer" }, "title": { diff --git a/specs/signed_docs/signed_doc.cue b/specs/signed_docs/signed_doc.cue index 04872387246..796da6b1079 100644 --- a/specs/signed_docs/signed_doc.cue +++ b/specs/signed_docs/signed_doc.cue @@ -7,6 +7,7 @@ import ( "list" "strings" "github.com/input-output-hk/catalyst-libs/specs/generic:uuid" + "github.com/input-output-hk/catalyst-libs/specs/template_field_definitions/fields:template_field_definitions" ) // Document Type must be a valid UUIDv4 @@ -118,3 +119,5 @@ _allDocNames: or(_allDocNamesList) // Individual Valid Document Name constraint. #DocumentName: _allDocNames + +templateJsonSchemaDefs: template_field_definitions.dictionary diff --git a/specs/signed_docs/template_schema_defs_dictionary.cue b/specs/signed_docs/template_schema_defs_dictionary.cue deleted file mode 100644 index 7e90a27b61c..00000000000 --- a/specs/signed_docs/template_schema_defs_dictionary.cue +++ /dev/null @@ -1,267 +0,0 @@ -// Template Json Schema Definitions Dictionary -// -// All known and supported Json Schema definitions, -// and their parameters and documentation so that -// a dictionary document and the definitions themselves -// can be generated. -package signed_docs - -import ( - "list" - "regexp" - "github.com/input-output-hk/catalyst-libs/specs/generic:optional" -) - -#fieldType: *"string" | - "object" | - "array" | - "integer" | - "boolean" - -_x_icon_choices: list.UniqueItems -_x_icon_choices: [ - "light-bulb", - "view-grid", - "top-bar", - "tag", - "chart-pie", - "flag", - "presentation-chart-line", - "double_check", -] - -#xIconChoices: or(_x_icon_choices) - -_format_choices: list.Sort([ - "uri", - "path", -], list.Ascending) - -_content_choices: list.Sort([ - "text/plain", - "text/markdown", -], list.Ascending) - -_jsonParameter: { - description: string - required: optional.#field - type: #fieldType - choices?: [...string] -} - -_regexTextPlain: "^.*$" -_regexHTTPSUrl: "^https://[^\\s]+$" - -// A JSON Schema field definition -#jsonSchemaFieldDefinition: { - // Documentation - description: string - - // MAPS to the `definitions` section within JSON Schema draft 7. - definition: { - "$comment": description - type: #fieldType - readOnly?: bool & true // IF true, is not a data entry field, but can be used for presentation and formatting. - format?: string & or(_format_choices) - contentMediaType?: string & or(_content_choices) - pattern?: regexp.Valid - - if type == "object" { - additionalProperties: bool & false // IF false, can not define extra fields. - } - - "x-note"?: string - } - - parent?: #templateJsonSchemaDefNames - - // The parameters supported by a particular field definition - parameters: { - title?: _jsonParameter & { - description: _ | *"The label attached to the field." - required: "yes" - } - description?: _jsonParameter & { - description: _ | *"The description of the field presented during data entry." - required: "optional" - } - required?: _jsonParameter & { - required: _ | *"optional" - } - default?: _jsonParameter & { - required: _ | *"yes" - } - const?: _jsonParameter & { - required: _ | *"yes" - } - properties?: _jsonParameter & { - required: _ | *"yes" - description: _ | *"All sub fields contained in the object." - required: "yes" - } - minLength?: _jsonParameter & { - type: "integer" - description: _ | *"Minimum number of characters allowed in the field." - required: "yes" - } - maxLength?: _jsonParameter & { - type: "integer" - description: _ | *"Maximum number of characters allowed in the field." - required: "yes" - } - "x-guidance"?: _jsonParameter & { - description: _ | *"Long form Markdown formatted description to give guidance about how the field is to be completed." - required: "optional" - } - "x-placeholder"?: _jsonParameter & { - description: _ | *"Placeholder text to display inside the field if it is empty." - required: "optional" - } - "x-icon"?: _jsonParameter & { - description: _ | *"The name of the Icon to display with the field." - required: "optional" - choices: _x_icon_choices - } - "x-order"?: _jsonParameter & { - required: "yes" - description: """ - The ordering of the properties to be enforced when displayed. - Any field not listed here will get displayed in an arbitrary order. - """ - } - } -} - -#jsonSchemaFields: { - [string]: #jsonSchemaFieldDefinition -} - -// Types of a Metadata Fields -#templateJsonSchemaDefNames: or([ - for k, _ in templateJsonSchemaDefs {k}, -]) - -// Definitions for all defined template schema field types. -templateJsonSchemaDefs: #jsonSchemaFields & { - "schemaReferenceNonUI": { - description: """ - Enforces the json document having a proper reference to the schema. - """ - definition: { - type: "string" - readOnly: true - } - - parameters: { - default: { - description: "The path that is defined to find the matching json schema." - required: "yes" - } - const: { - description: "The path must always be this value. **MUST** match `default`." - required: "yes" - } - } - } - - "segment": { - description: """ - Logical Document Section - Grouping Only - Highest Level Group - """ - definition: { - type: "object" - "x-note": """ - Major sections of the proposal. Each segment contains sections of information grouped together. - """ - } - parameters: { - title: { - description: "The title of the segment." - } - description: { - description: "The displayable description attached to the segment. Markdown formatted contents." - } - properties: { - description: "The sub fields of the segment." - } - required: { - description: "Which fields MUST appear in the segment." - required: "optional" - } - "x-icon": {} - "x-order": {} - } - } - - "section": { - description: "UI - Logical Document Sub-Section Break." - parent: "segment" - definition: { - type: "object" - "x-note": """ - Subsections containing specific details about the proposal. - """ - } - parameters: { - title: { - description: "The title of the section." - required: "yes" - } - description: { - description: "The displayable description attached to the section. Markdown formatted contents." - } - properties: { - description: "The sub fields of the section." - } - required: { - description: "Which fields MUST appear in the segment." - required: "optional" - } - "x-icon": {} - "x-order": {} - } - } - - "singleLineTextEntry": { - description: "UI - Single Line text entry without any markup or rich text capability." - definition: { - type: "string" - contentMediaType: "text/plain" - pattern: _regexTextPlain - "x-note": """ - Enter a single line of text. - No formatting, line breaks, or special characters are allowed. - """ - } - parameters: { - title: {} - description: {} - minLength: {} - maxLength: {} - "x-guidance": {} - "x-placeholder": {} - } - } - - "singleLineHttpsURLEntry": { - description: "UI - Single Line text entry for HTTPS Urls." - definition: { - type: "string" - format: "uri" - pattern: _regexHTTPSUrl - "x-note": """ - Must start with 'https://' and is followed by one or more - non-whitespace characters, ending at the end of the string. - """ - } - parameters: { - title: {} - description: {} - minLength: {} - maxLength: {} - "x-guidance": {} - "x-placeholder": {} - } - } - -} diff --git a/specs/template_field_definitions/choices.cue b/specs/template_field_definitions/choices.cue new file mode 100644 index 00000000000..8c4d6cad873 --- /dev/null +++ b/specs/template_field_definitions/choices.cue @@ -0,0 +1,27 @@ +// Choices that can be made for a string field. +package template_field_definitions + +import ( + "list" +) + +// Valid values for `format` +_allFormats: list.UniqueItems +_allFormats: list.Sort([ + "uri", + "path", + "radioButtonSelect", + "dropDownSingleSelect", + "multiSelect", +], list.Ascending) + +#formatChoices: or(_allFormats) + +// Valid values for `contentMediaType` +_allContentMediaTypes: list.UniqueItems +_allContentMediaTypes: list.Sort([ + "text/plain", + "text/markdown", +], list.Ascending) + +#contentMediaTypeChoices: or(_allContentMediaTypes) diff --git a/specs/template_field_definitions/dictionary.cue b/specs/template_field_definitions/dictionary.cue new file mode 100644 index 00000000000..cb623e6d5d3 --- /dev/null +++ b/specs/template_field_definitions/dictionary.cue @@ -0,0 +1,20 @@ +// Template Json Schema Definitions Dictionary +// +// All known and supported Json Schema definitions, +// and their parameters and documentation so that +// a dictionary document and the definitions themselves +// can be generated. +package template_field_definitions + +// Types of a Metadata Fields +#templateJsonSchemaDefNames: or([ + for k, _ in dictionary {k}, +]) + +// Definitions for all defined template schema field types. +dictionary: #jsonSchemaFields & {} + +// Types of a Metadata Fields +#templateJsonSchemaDefNames: or([ + for k, _ in dictionary {k}, +]) diff --git a/specs/template_field_definitions/field.cue b/specs/template_field_definitions/field.cue new file mode 100644 index 00000000000..6ead7081e44 --- /dev/null +++ b/specs/template_field_definitions/field.cue @@ -0,0 +1,45 @@ +// Individual Field Definition. +package template_field_definitions + +import ( + "regexp" +) + +#fieldDefinition: { + $comment: "See the Template Schema Definition Dictionary for detailed documentation." + type: #fieldType + readOnly?: true // IF true, is not a data entry field, but can be used for presentation and formatting. + + if type == "object" { + additionalProperties: false // IF false, can not define extra fields. + } + + if type == "array" { + items: #fieldDefinition + uniqueItems?: true + } + + if type == "string" { + format?: #formatChoices + contentMediaType?: #contentMediaTypeChoices + pattern?: regexp.Valid + } + +} + +// A JSON Schema field definition +#jsonSchemaFieldDefinition: { + // Documentation + description: string + + // MAPS 1:1 to the `definitions` section within JSON Schema draft 7. + definition: #fieldDefinition + + // If this field type must appear only as a child of another field type. + parent?: #templateJsonSchemaDefNames + + // The parameters supported by a particular field definition + parameters: _allParameters +} + +#jsonSchemaFields: [string]: #jsonSchemaFieldDefinition diff --git a/specs/template_field_definitions/fields/drop_down_single_select.cue b/specs/template_field_definitions/fields/drop_down_single_select.cue new file mode 100644 index 00000000000..2495a25f7a4 --- /dev/null +++ b/specs/template_field_definitions/fields/drop_down_single_select.cue @@ -0,0 +1,26 @@ +// Radio Button selection from a list of text options. + +package template_field_definitions + +dictionary: #jsonSchemaFields & { + dropDownSingleSelect: { + description: """ + UI - Drop Down Selection of a single entry from the defined enum. + + Select one option from a selector styled as a dropdown menu. + Only one choice is allowed. + """ + definition: { + type: "string" + format: "dropDownSingleSelect" + contentMediaType: "text/plain" + pattern: _regexTextSingleLine + } + parameters: { + title: {} + description: {} + enum: {} + "x-guidance": {} + } + } +} diff --git a/specs/template_field_definitions/fields/multi_line_text_entry.cue b/specs/template_field_definitions/fields/multi_line_text_entry.cue new file mode 100644 index 00000000000..7f0c35ebd66 --- /dev/null +++ b/specs/template_field_definitions/fields/multi_line_text_entry.cue @@ -0,0 +1,26 @@ +// Single Line Text Entry +package template_field_definitions + +dictionary: #jsonSchemaFields & { + multiLineTextEntry: { + description: """ + UI - One or more Lines of text entry. + Line breaks, and special characters are allowed. + Special formatted markup, such as Markdown are not allowed. + Enter multiple lines of plain text. You can use line breaks but no special formatting. + """ + definition: { + type: "string" + contentMediaType: "text/plain" + pattern: _regexTextMultiLine + } + parameters: { + title: {} + description: {} + minLength: {} + maxLength: {} + "x-guidance": {} + "x-placeholder": {} + } + } +} diff --git a/specs/template_field_definitions/fields/multi_line_text_entry_markdown.cue b/specs/template_field_definitions/fields/multi_line_text_entry_markdown.cue new file mode 100644 index 00000000000..659681574e8 --- /dev/null +++ b/specs/template_field_definitions/fields/multi_line_text_entry_markdown.cue @@ -0,0 +1,29 @@ +// Single Line Text Entry +package template_field_definitions + +dictionary: #jsonSchemaFields & { + multiLineTextEntryMarkdown: { + description: """ + UI - Multiline text entry with Markdown content. + Use Markdown formatting for rich text. + Markdown formatting is as defined by + + The following Markdown Extensions are also supported: + + * None + """ + definition: { + type: "string" + contentMediaType: "text/markdown" + pattern: _regexTextMultiLine + } + parameters: { + title: {} + description: {} + minLength: {} + maxLength: {} + "x-guidance": {} + "x-placeholder": {} + } + } +} diff --git a/specs/template_field_definitions/fields/multi_select.cue b/specs/template_field_definitions/fields/multi_select.cue new file mode 100644 index 00000000000..4bf532d2b1d --- /dev/null +++ b/specs/template_field_definitions/fields/multi_select.cue @@ -0,0 +1,28 @@ +// Radio Button selection from a list of text options. + +package template_field_definitions + +dictionary: #jsonSchemaFields & { + multiSelect: { + description: """ + UI - Multiselect from the given items. + + Select multiple options from the dropdown menu. + Multiple choices are allowed. + All choices MUST be unique. + """ + definition: { + type: "array" + uniqueItems: true + items: dictionary.singleLineTextEntry.definition + } + parameters: { + title: {} + description: {} + minItems: {} + maxItems: {} + contains: {} + "x-guidance": {} + } + } +} diff --git a/specs/template_field_definitions/fields/radio_button_select.cue b/specs/template_field_definitions/fields/radio_button_select.cue new file mode 100644 index 00000000000..e378aa6fc91 --- /dev/null +++ b/specs/template_field_definitions/fields/radio_button_select.cue @@ -0,0 +1,26 @@ +// Radio Button selection from a list of text options. + +package template_field_definitions + +dictionary: #jsonSchemaFields & { + radioButtonSelect: { + description: """ + UI - Radio Button Selection. + + Select one option from a list of text options. + Selector is styled as a set of Radio Buttons. + """ + definition: { + type: "string" + format: "radioButtonSelect" + contentMediaType: "text/plain" + pattern: _regexTextSingleLine + } + parameters: { + title: {} + description: {} + enum: {} + "x-guidance": {} + } + } +} diff --git a/specs/template_field_definitions/fields/schema_reference.cue b/specs/template_field_definitions/fields/schema_reference.cue new file mode 100644 index 00000000000..406da9ced4b --- /dev/null +++ b/specs/template_field_definitions/fields/schema_reference.cue @@ -0,0 +1,25 @@ +// Schema Reference - Not used in any UI +package template_field_definitions + +dictionary: #jsonSchemaFields & { + schemaReferenceNonUI: { + description: """ + Enforces the json document having a proper reference to the schema. + """ + definition: { + type: "string" + readOnly: true + } + + parameters: { + default: { + description: "The path that is defined to find the matching json schema." + required: "yes" + } + const: { + description: "The path must always be this value. **MUST** match `default`." + required: "yes" + } + } + } +} diff --git a/specs/template_field_definitions/fields/section.cue b/specs/template_field_definitions/fields/section.cue new file mode 100644 index 00000000000..bcaa3be6242 --- /dev/null +++ b/specs/template_field_definitions/fields/section.cue @@ -0,0 +1,31 @@ +// Document Segment +// +// Segment - +// Section - +// Topic - +package template_field_definitions + +dictionary: #jsonSchemaFields & { + section: { + description: """ + UI - Logical Document Sub-Section Break. + Subsections containing specific details about the proposal. + """ + parent: "segment" + definition: type: "object" + parameters: { + title: { + description: "The title of the section." + required: "yes" + } + description: description: "The displayable description attached to the section. Markdown formatted contents." + properties: description: "The sub fields of the section." + required: { + description: "Which fields MUST appear in the segment." + required: "optional" + } + "x-icon": {} + "x-order": {} + } + } +} diff --git a/specs/template_field_definitions/fields/segment.cue b/specs/template_field_definitions/fields/segment.cue new file mode 100644 index 00000000000..b0a1de68d08 --- /dev/null +++ b/specs/template_field_definitions/fields/segment.cue @@ -0,0 +1,29 @@ +// Document Segment +// +// Segment - +// Section - +// Topic - +package template_field_definitions + +dictionary: #jsonSchemaFields & { + segment: { + description: """ + Logical Document Section - Grouping Only - Highest Level Group + "x-note": " + Major sections of the proposal. Each segment contains sections of information grouped together. + " + """ + definition: type: "object" + parameters: { + title: description: "The title of the segment." + description: description: "The displayable description attached to the segment. Markdown formatted contents." + properties: description: "The sub fields of the segment." + required: { + description: "Which fields MUST appear in the segment." + required: "optional" + } + "x-icon": {} + "x-order": {} + } + } +} diff --git a/specs/template_field_definitions/fields/single_line_https_url_entry.cue b/specs/template_field_definitions/fields/single_line_https_url_entry.cue new file mode 100644 index 00000000000..5f1b65cc216 --- /dev/null +++ b/specs/template_field_definitions/fields/single_line_https_url_entry.cue @@ -0,0 +1,27 @@ +// Single Line HTTPS URL Text Entry +package template_field_definitions + +dictionary: #jsonSchemaFields & { + singleLineHttpsURLEntry: { + description: """ + UI - Single Line text entry for HTTPS Urls. + "x-note": + Must start with 'https://' and is followed by one or more + non-whitespace characters, ending at the end of the string. + + """ + definition: { + type: "string" + format: "uri" + pattern: _regexHTTPSUrl + } + parameters: { + title: {} + description: {} + minLength: {} + maxLength: {} + "x-guidance": {} + "x-placeholder": {} + } + } +} diff --git a/specs/template_field_definitions/fields/single_line_text_entry.cue b/specs/template_field_definitions/fields/single_line_text_entry.cue new file mode 100644 index 00000000000..03d70bd8530 --- /dev/null +++ b/specs/template_field_definitions/fields/single_line_text_entry.cue @@ -0,0 +1,25 @@ +// Single Line Text Entry +package template_field_definitions + +dictionary: #jsonSchemaFields & { + singleLineTextEntry: { + description: """ + UI - Single Line text entry without any markup or rich text capability. + A single line of text. + No formatting, markup, line breaks, or special characters are allowed. + """ + definition: { + type: "string" + contentMediaType: "text/plain" + pattern: _regexTextSingleLine + } + parameters: { + title: {} + description: {} + minLength: {} + maxLength: {} + "x-guidance": {} + "x-placeholder": {} + } + } +} diff --git a/specs/template_field_definitions/icon_choices.cue b/specs/template_field_definitions/icon_choices.cue new file mode 100644 index 00000000000..bb1d438814b --- /dev/null +++ b/specs/template_field_definitions/icon_choices.cue @@ -0,0 +1,283 @@ +// List of all valid ICON choices. +// The UI is free to render Icons or not and render them in its own style. +// However, Icons not listed here are not supported. +package template_field_definitions + +import ( + "list" +) + +_allIcons: list.UniqueItems +_allIcons: list.Sort([ + "academic-cap", + "ada", + "adjustments", + "'all spaces menu-1'", + "'all spaces menu'", + "annotation", + "archive", + "arrow-circle-down", + "arrow-circle-left", + "arrow-circle-right", + "arrow-circle-up", + "arrow-down", + "arrow-left", + "arrow-narrow-down", + "arrow-narrow-left", + "arrow-narrow-right", + "arrow-narrow-up", + "arrow-right", + "arrow-triangle-down", + "arrow-triangle-up", + "arrow-up", + "arrows-expand", + "at-symbol", + "avatar_placeholder", + "backspace", + "badge-check", + "ban", + "beaker", + "bell", + "book-open", + "bookmark-alt", + "bookmark", + "bottom-main-content", + "bottom-rail-toggle-1", + "bottom-rail-toggle", + "briefcase", + "cake", + "calculator", + "calendar", + "camera", + "cash", + "chart-bar", + "chart-pie", + "chart-square-bar", + "chat-alt-2", + "chat-alt", + "chat", + "check-circle", + "check", + "chevron-double-down", + "chevron-double-left", + "chevron-double-right", + "chevron-double-up", + "chevron-down-1", + "chevron-down", + "chevron-left", + "chevron-right", + "chevron-up", + "chip", + "clipboard-check", + "clipboard-copy", + "clipboard-list", + "clipboard", + "clock", + "cloud-download", + "cloud-upload", + "cloud", + "code", + "cog-gear", + "collection", + "color-swatch", + "credit-card", + "cube-transparent", + "cube", + "currency-bangladeshi", + "currency-dollar", + "currency-euro", + "currency-pound", + "currency-rupee", + "currency-yen", + "cursor-click", + "curved-arrow-right", + "database", + "desktop-computer", + "device-mobile", + "device-tablet", + "document-add", + "document-remove", + "document-report", + "document-search", + "document-text", + "document", + "dots-circle-horizontal", + "dots-horizontal", + "dots-vertical", + "double_check", + "download", + "duplicate", + "emoji-happy", + "emoji-sad", + "exclamation-circle", + "exclamation", + "external-link", + "eye-off", + "eye", + "facebook", + "fast-forward", + "film", + "filter", + "finger-print", + "fire", + "flag", + "folder-add", + "folder-download", + "folder-open", + "folder-remove", + "folder", + "fund", + "gift", + "globe-alt", + "globe", + "hand", + "hashtag", + "heart", + "home", + "icon-user-remove", + "identification", + "inbox-in", + "inbox", + "information-circle", + "key", + "left-rail-toggle", + "library", + "light-bulb", + "lightning-bolt", + "link", + "linkedin", + "location-marker", + "lock-closed", + "lock-open", + "logout-1", + "logout", + "mail-open", + "mail", + "map", + "maximize-toggle", + "menu-alt-1", + "menu-alt-2", + "menu-alt-3", + "menu-alt-4", + "menu", + "microphone", + "minimize-toggle", + "minus-circle", + "minus", + "moon", + "move-item", + "music-note", + "newspaper", + "node-closed", + "node-line-end", + "node-line", + "node-open", + "office-building", + "paper-airplane", + "paper-clip", + "pause", + "pencil-alt", + "pencil", + "phone-incoming", + "phone-missed-call", + "phone-outgoing", + "phone", + "photograph", + "play", + "plus", + "plus_circle_filled", + "plus_circle_outlined", + "presentation-chart-bar", + "presentation-chart-line", + "printer", + "progress-track-warning", + "puzzle", + "qrcode", + "question-mark-circle", + "receipt-refund", + "receipt-tax", + "reddit", + "refresh", + "reply", + "rewind", + "right-rail-toggle", + "rss", + "rt_bold", + "rt_decrease_indent", + "rt_heading", + "rt_increase_indent", + "rt_italic", + "rt_ordered_list", + "rt_unordered_list", + "save-as", + "save", + "scale", + "scissors", + "search-circle", + "search", + "selector", + "send-airplane", + "server", + "share", + "shield-check", + "shield-exclamation", + "shopping-bag", + "shopping-cart", + "sm-view-grid-add", + "sort-ascending", + "sort-descending", + "sparkles", + "speakerphone", + "star_filled", + "star_outlined", + "status-offline", + "status-online", + "stop", + "summary", + "sun", + "support", + "switch-horizontal", + "switch-vertical", + "table", + "tag", + "template", + "terminal", + "thumb-down", + "thumb-up", + "ticket", + "top-bar-filled", + "top-bar", + "translate", + "trash", + "trending-down", + "trending-up", + "truck", + "unlink", + "upload", + "user-add", + "user-circle", + "user-group", + "user", + "users", + "variable", + "video-camera", + "view-boards", + "view-grid", + "view-list", + "volume-off", + "volume-up", + "vote", + "wallet", + "wifi", + "x-circle", + "x", + "xTwitter", + "zoom-in", + "zoom-out", +], list.Ascending) + +#iconChoices: or(_allIcons) + +// test +// good_icon: #iconChoices & "tag" +// bad_icon: #iconChoices & "tags" diff --git a/specs/template_field_definitions/parameters.cue b/specs/template_field_definitions/parameters.cue new file mode 100644 index 00000000000..a9a5721387c --- /dev/null +++ b/specs/template_field_definitions/parameters.cue @@ -0,0 +1,109 @@ +// Definitions of the field parameters within a template. +package template_field_definitions + +import ( + "list" + "github.com/input-output-hk/catalyst-libs/specs/generic:optional" +) + +// Supported field `type` +// Same as Json Schema minus `null` +#fieldType: "array" | + "array" | + "boolean" | + "integer" | + "number" | + "object" | + *"string" + +#jsonParameter: { + description: string + required: optional.#field + type: #fieldType + items?: #jsonParameter + choices?: list.UniqueItems +} + +// The parameters supported by a particular field definition +_allParameters: { + title?: #jsonParameter & { + description: _ | *"The label attached to the field." + required: "yes" + } + description?: #jsonParameter & { + description: _ | *"The description of the field presented during data entry." + required: "optional" + } + required?: #jsonParameter & { + required: _ | *"optional" + } + default?: #jsonParameter & { + required: _ | *"yes" + } + const?: #jsonParameter & { + required: _ | *"yes" + } + properties?: #jsonParameter & { + required: _ | *"yes" + description: _ | *"All sub fields contained in the object." + required: "yes" + } + minLength?: #jsonParameter & { + type: "integer" + description: _ | *"Minimum number of characters allowed in the field." + required: "optional" + } + maxLength?: #jsonParameter & { + type: "integer" + description: _ | *"Maximum number of characters allowed in the field." + required: "yes" + } + enum?: #jsonParameter & { + type: "array" + items: { + description: "An element of the Enum." + type: "string" + } + description: _ | *"An array of string to select from." + required: "yes" + } + minItems?: #jsonParameter & { + type: "integer" + description: _ | *#"An array instance is valid against "minItems" if its size is greater than, or equal to, the value of this keyword."# + required: "optional" + } + maxItems?: #jsonParameter & { + type: "integer" + description: _ | *#"An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword."# + required: "yes" + } + contains?: #jsonParameter & { + type: "array" + items: { + description: "An individual Choice." + type: "string" + } + description: _ | *"The choices the multi select can contain." + required: "yes" + } + "x-guidance"?: #jsonParameter & { + description: _ | *"Long form Markdown formatted description to give guidance about how the field is to be completed." + required: "optional" + } + "x-placeholder"?: #jsonParameter & { + description: _ | *"Placeholder text to display inside the field if it is empty." + required: "optional" + } + "x-icon"?: #jsonParameter & { + description: _ | *"The name of the Icon to display with the field." + required: "optional" + choices: _allIcons + } + "x-order"?: #jsonParameter & { + required: "yes" + description: """ + The ordering of the properties to be enforced when displayed. + Any field not listed here will get displayed in an arbitrary order. + """ + } +} diff --git a/specs/template_field_definitions/patterns.cue b/specs/template_field_definitions/patterns.cue new file mode 100644 index 00000000000..645d512570a --- /dev/null +++ b/specs/template_field_definitions/patterns.cue @@ -0,0 +1,6 @@ +// Regex patterns that are defined. +package template_field_definitions + +_regexTextSingleLine: #"^.*$"# +_regexTextMultiLine: #"^[\S\s]*$"# +_regexHTTPSUrl: #"^https://[^\s]+$"# From b181fa6385c7a87600c2f5f1d3ee88c7422f6d8c Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 8 Jun 2025 17:58:40 +0700 Subject: [PATCH 08/42] fix(docs): simplify schema with cue format --- specs/signed_docs/cddl_defs.cue | 34 +++++----- specs/signed_docs/cose_headers.cue | 66 ++++++++----------- .../signed_docs/cose_signed_doc_cddl_defs.cue | 26 ++++---- specs/signed_docs/docs/all.cue | 26 ++++---- .../signed_docs/docs/campaign_parameters.cue | 8 +-- .../signed_docs/docs/category_parameters.cue | 8 +-- .../docs/comment_moderation_action.cue | 9 +-- .../signed_docs/docs/decision_parameters.cue | 8 +-- specs/signed_docs/docs/proposal.cue | 38 ++++------- specs/signed_docs/docs/proposal_comment.cue | 16 ++--- .../docs/proposal_comment_meta_template.cue | 35 ++++------ .../docs/proposal_comment_template.cue | 32 ++++----- .../docs/proposal_meta_template.cue | 35 ++++------ .../docs/proposal_moderation_action.cue | 9 ++- .../docs/proposal_submission_action.cue | 7 +- specs/signed_docs/docs/proposal_template.cue | 32 ++++----- specs/signed_docs/documentation_links.cue | 22 +++---- specs/signed_docs/metadata.cue | 4 +- specs/signed_docs/signed_doc.cue | 4 +- 19 files changed, 168 insertions(+), 251 deletions(-) diff --git a/specs/signed_docs/cddl_defs.cue b/specs/signed_docs/cddl_defs.cue index 77915ed5295..79300ed7c85 100644 --- a/specs/signed_docs/cddl_defs.cue +++ b/specs/signed_docs/cddl_defs.cue @@ -14,7 +14,7 @@ package signed_docs } cddlDefinitions: #cddlDefinitions & { - "uuid_v7": { + uuid_v7: { def: "#6.37(bytes .size 16)" description: """ Version 7 UUID @@ -23,7 +23,7 @@ cddlDefinitions: #cddlDefinitions & { """ comment: "UUIDv7" } - "uuid_v4": { + uuid_v4: { def: "#6.37(bytes .size 16)" description: """ Version 4 UUID @@ -32,30 +32,30 @@ cddlDefinitions: #cddlDefinitions & { """ comment: "UUIDv4" } - "document_type": { + document_type: { def: "[ 1* \(requires[0]) ]" requires: ["uuid_v4"] description: "Unique Document Type Identifier" comment: "Document Type" } - "blake2b_256": { + blake2b_256: { def: "bytes .size 32" description: "Blake2b Hash (256 bits)" comment: "Blake2B-256" } - "document_id": { + document_id: { def: "\(requires[0])" requires: ["uuid_v7"] description: "Unique Document Identifier" comment: "Document ID" } - "document_ver": { + document_ver: { def: "\(requires[0])" requires: ["uuid_v7"] description: "Unique Chronological Document Version Identifier" comment: "Document Version" } - "cid": { + cid: { def: "#6.42(bytes)" description: """ IPLD content identifier. @@ -68,7 +68,7 @@ cddlDefinitions: #cddlDefinitions & { TODO: add size limits if possible """ } - "document_locator": { + document_locator: { def: """ { \"cid\" => \(requires[0]) @@ -77,7 +77,7 @@ cddlDefinitions: #cddlDefinitions & { requires: ["cid"] comment: "Where a document can be located, must be a unique identifier." } - "document_ref": { + document_ref: { def: """ [ 1* [ \(requires[0]), @@ -92,26 +92,26 @@ cddlDefinitions: #cddlDefinitions & { ] comment: "Reference to another Signed Document" } - "json_pointer": { + json_pointer: { def: "text" comment: "RFC6901 Standard JSON Pointer" } - "section_ref": { + section_ref: { def: "\(requires[0])" requires: ["json_pointer"] comment: "Reference to a section in a referenced document." } - "collaborators": { + collaborators: { def: "[ * \(requires[0]) ]" requires: ["catalyst_id_kid"] comment: "Allowed Collaborators on the next subsequent version of a document." } - "revocations": { + revocations: { def: "[ * \(requires[0]) ] / true " requires: ["document_ver"] comment: "List of revoked versions of this document." } - "media_type": { + media_type: { def: """ ( (uint .eq (\(_cddlCoapTypes))) / @@ -125,17 +125,17 @@ cddlDefinitions: #cddlDefinitions & { If uint is used, only CoAP Content Formats that match the string format are allowed. """ } - "http_content_encoding": { + http_content_encoding: { def: """ tstr .eq "br" """ comment: "Supported Content Encoding Types" } - "catalyst_id_kid": { + catalyst_id_kid: { def: "bytes" comment: "UTF8 Catalyst ID URI encoded as a bytes string." } - "revocations": { + revocations: { def: "[ * document_ver ] / true " requires: ["document_ver"] } diff --git a/specs/signed_docs/cose_headers.cue b/specs/signed_docs/cose_headers.cue index 7c809138aa4..9631edebb97 100644 --- a/specs/signed_docs/cose_headers.cue +++ b/specs/signed_docs/cose_headers.cue @@ -20,25 +20,21 @@ _contentTypes: { description: "JSON Document" coap_type: 50 } - "application/schema+json": { - description: """ - JSON Schema Draft 7 Document; Note: - * This is currently an unofficial media type. - * Draft 7 is used because of its wide support by tooling. - """ - } + "application/schema+json": description: """ + JSON Schema Draft 7 Document; Note: + * This is currently an unofficial media type. + * Draft 7 is used because of its wide support by tooling. + """ "application/cbor": { description: "RFC8949 Binary CBOR Encoded Document" coap_type: 60 } - "application/cddl": { - description: """ - CDDL Document; Note: - * This is an unofficial media type - * RFC9165 Additional Control Operators for CDDL are supported. - * Must not have Modules, schema must be self-contained. - """ - } + "application/cddl": description: """ + CDDL Document; Note: + * This is an unofficial media type + * RFC9165 Additional Control Operators for CDDL are supported. + * Must not have Modules, schema must be self-contained. + """ } contentTypes: _contentTypes @@ -49,11 +45,7 @@ _encodingTypes: { description: string // description of the content type } } -_encodingTypes: { - "br": { - description: "BROTLI Compression" - } -} +_encodingTypes: br: description: "BROTLI Compression" encodingTypes: _encodingTypes @@ -61,25 +53,25 @@ documentationLinks: { "application/json": "https://www.iana.org/assignments/media-types/application/json" "application/schema+json": "https://datatracker.ietf.org/doc/draft-bhutton-json-schema/" "application/cbor": "https://www.iana.org/assignments/media-types/application/cbor" - "br": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br" + br: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br" "JSON Schema": "https://json-schema.org/draft-07" - "RFC7932": "https://www.rfc-editor.org/rfc/rfc7932" // Brotli - "RFC8259": "https://www.rfc-editor.org/rfc/rfc8259.html" // JSON - "RFC8610": "https://www.rfc-editor.org/rfc/rfc8610" // CDDL - "RFC8949": "https://www.rfc-editor.org/rfc/rfc8949.html" // CBOR - "RFC9052": "https://datatracker.ietf.org/doc/html/rfc9052" // COSE + RFC7932: "https://www.rfc-editor.org/rfc/rfc7932" // Brotli + RFC8259: "https://www.rfc-editor.org/rfc/rfc8259.html" // JSON + RFC8610: "https://www.rfc-editor.org/rfc/rfc8610" // CDDL + RFC8949: "https://www.rfc-editor.org/rfc/rfc8949.html" // CBOR + RFC9052: "https://datatracker.ietf.org/doc/html/rfc9052" // COSE "RFC9052-CoseSign": "https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si" // COSE Multiple Signers "RFC9052-HeaderParameters": "https://www.rfc-editor.org/rfc/rfc8152#section-3.1" // COSE Header Parameters - "RFC9165": "https://www.rfc-editor.org/rfc/rfc9165" // CDDL Additional Controls + RFC9165: "https://www.rfc-editor.org/rfc/rfc9165" // CDDL Additional Controls } // Known aliases for links. Lets us automatically create [Named Link][Reference Link] linkAKA: { - "BROTLI": "RFC7932" - "JSON": "RFC8259" - "CDDL": "RFC8610" - "CBOR": "RFC8949" - "COSE": "RFC9052" + BROTLI: "RFC7932" + JSON: "RFC8259" + CDDL: "RFC8610" + CBOR: "RFC8949" + COSE: "RFC9052" "COSE Sign": "RFC9052-CoseSign" "COSE Header Parameters": "RFC9052-HeaderParameters" "RFC9165 - CDDL Additional Controls": "RFC9165" @@ -158,11 +150,11 @@ coseHeaderFormats: #metadataFormats & { required: optional.#field | *"yes" format: #coseHeaderTypesConstraint if format == "Media Type" { - "value": #contentType | [...#contentType] + value: #contentType | [...#contentType] } if format == "HTTP Content Encoding" { - "value": #contentEncoding + value: #contentEncoding } } @@ -191,7 +183,7 @@ _coseHeaders: #coseHeaders & { _coseSignatureHeaders: #coseHeaders & { // Key identifier - "kid": #coseField & { + kid: #coseField & { coseLabel: 4 format: "Catalyst ID" description: """ @@ -206,9 +198,7 @@ _coseSignatureHeaders: #coseHeaders & { } cose_headers: _coseHeaders -cose_headers: - "content type": - value: #allContentTypes +cose_headers: "content type": value: #allContentTypes // Preferred display order of cose header fields. // if header not listed, display after the listed fields, in alphabetical order. diff --git a/specs/signed_docs/cose_signed_doc_cddl_defs.cue b/specs/signed_docs/cose_signed_doc_cddl_defs.cue index ef9091d1d5e..c68d4ccf04a 100644 --- a/specs/signed_docs/cose_signed_doc_cddl_defs.cue +++ b/specs/signed_docs/cose_signed_doc_cddl_defs.cue @@ -14,7 +14,7 @@ _cddlContentTypes: "\"\(strings.Join(cose_headers."content type".value, "\" /\n _cddlCoapTypes: "\(strings.Join(_allCoapTypesStr, " / "))" cddlDefinitions: #cddlDefinitions & { - "signed_document": { + signed_document: { requires: ["COSE_Sign"] def: "\(requires[0])" description: """ @@ -30,7 +30,7 @@ cddlDefinitions: #cddlDefinitions & { Catalyst Signed Document data object. """ } - "COSE_Sign": { + COSE_Sign: { requires: [ "COSE_Document_Headers", "COSE_Signature", @@ -44,7 +44,7 @@ cddlDefinitions: #cddlDefinitions & { """ comment: "COSE-SIGN data object" } - "COSE_Document_Headers": { + COSE_Document_Headers: { requires: [ "COSE_Document_Header_Map", "COSE_Generic_Headers", @@ -57,7 +57,7 @@ cddlDefinitions: #cddlDefinitions & { """ comment: "COSE Document headers (only protected headers are used)" } - "COSE_Document_Header_Map": { + COSE_Document_Header_Map: { requires: [ "COSE_Document_Standard_Headers", "Signed_Document_Metadata_Headers", @@ -72,7 +72,7 @@ cddlDefinitions: #cddlDefinitions & { """ comment: "COSE Document Header Map" } - "COSE_Document_Standard_Headers": { + COSE_Document_Standard_Headers: { def: """ ( ? 1 => int / tstr, ; algorithm identifier @@ -88,14 +88,14 @@ cddlDefinitions: #cddlDefinitions & { "COSE_label", ] } - "Signed_Document_Metadata_Headers": { + Signed_Document_Metadata_Headers: { def: "\(requires[0])" comment: "Generic definition (does not include metadata constraints)" requires: [ "COSE_Generic_Headers", ] } - "COSE_Signature_Headers": { + COSE_Signature_Headers: { requires: [ "COSE_Signature_Header_Map", "COSE_Generic_Headers", @@ -108,7 +108,7 @@ cddlDefinitions: #cddlDefinitions & { """ comment: "COSE Signature headers (only protected headers are used)" } - "COSE_Signature": { + COSE_Signature: { def: """ [ \(requires[0]), @@ -118,7 +118,7 @@ cddlDefinitions: #cddlDefinitions & { requires: ["COSE_Signature_Headers"] comment: "An Individual Document Signature" } - "COSE_Signature_Header_Map": { + COSE_Signature_Header_Map: { requires: [ "COSE_Signature_Standard_Headers", "COSE_Generic_Headers", @@ -131,7 +131,7 @@ cddlDefinitions: #cddlDefinitions & { """ comment: "COSE Signature Header Map" } - "COSE_Signature_Standard_Headers": { + COSE_Signature_Standard_Headers: { def: """ ( ? 1 => int / tstr, ; algorithm identifier @@ -150,7 +150,7 @@ cddlDefinitions: #cddlDefinitions & { "COSE_Generic_Headers", ] } - "COSE_Generic_Headers": { + COSE_Generic_Headers: { def: "( * \(requires[0]) => \(requires[1]) )" comment: "Generic Header definition" requires: [ @@ -158,11 +158,11 @@ cddlDefinitions: #cddlDefinitions & { "COSE_values", ] } - "COSE_label": { + COSE_label: { def: "int / tstr" comment: "COSE Map Generic Label" } - "COSE_values": { + COSE_values: { def: "any" comment: "COSE Map Generic Value" } diff --git a/specs/signed_docs/docs/all.cue b/specs/signed_docs/docs/all.cue index a0859b3102b..c5ffb2294d3 100644 --- a/specs/signed_docs/docs/all.cue +++ b/specs/signed_docs/docs/all.cue @@ -7,16 +7,16 @@ import ( // Named Type UUIDs for easier definitions/references _allDocTypes: { - "Template": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" - "Proposal": "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea" - "Action": "5e60e623-ad02-4a1b-a1ac-406db978ee48" - "SubmissionAction": "78927329-cfd9-4ea1-9c71-0e019b126a65" - "ModerationAction": "a5d232b8-5e03-4117-9afd-be32b878fcdd" - "Brand": "ebcabeeb-5bc5-4f95-91e8-cab8ca724172" - "Campaign": "5ef32d5d-f240-462c-a7a4-ba4af221fa23" - "Category": "818938c3-3139-4daa-afe6-974c78488e95" - "Decision": "788ff4c6-d65a-451f-bb33-575fe056b411" + Template: "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + Proposal: "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + Comment: "b679ded3-0e7c-41ba-89f8-da62a17898ea" + Action: "5e60e623-ad02-4a1b-a1ac-406db978ee48" + SubmissionAction: "78927329-cfd9-4ea1-9c71-0e019b126a65" + ModerationAction: "a5d232b8-5e03-4117-9afd-be32b878fcdd" + Brand: "ebcabeeb-5bc5-4f95-91e8-cab8ca724172" + Campaign: "5ef32d5d-f240-462c-a7a4-ba4af221fa23" + Category: "818938c3-3139-4daa-afe6-974c78488e95" + Decision: "788ff4c6-d65a-451f-bb33-575fe056b411" } // Source of truth for ALL Document Types and their matching UUID's. @@ -31,7 +31,7 @@ _allDocs: { _allDocTypes["Template"], // Template _allDocTypes["Proposal"], // For Proposals ] - "Proposal": [ + Proposal: [ _allDocTypes["Proposal"], ] "Proposal Comment Meta Template": [ @@ -86,9 +86,7 @@ _allDocs: { docs: [..._allDocNames] } -#DocClusters: { - [string]: #DocumentCluster -} +#DocClusters: [string]: #DocumentCluster doc_clusters: #DocClusters & { // System parameters define the system, excludes Decisions. diff --git a/specs/signed_docs/docs/campaign_parameters.cue b/specs/signed_docs/docs/campaign_parameters.cue index 9cafb80ba59..d63f14e943c 100644 --- a/specs/signed_docs/docs/campaign_parameters.cue +++ b/specs/signed_docs/docs/campaign_parameters.cue @@ -8,11 +8,9 @@ docs: #DocumentDefinitions & { Parameters which define a Campaign within a Brand in the system. """ - metadata: { - parameters: { - required: "yes" - type: "Brand Parameters" - } + metadata: parameters: { + required: "yes" + type: "Brand Parameters" } versions: [ diff --git a/specs/signed_docs/docs/category_parameters.cue b/specs/signed_docs/docs/category_parameters.cue index 7d8904f7db2..b1dd3099597 100644 --- a/specs/signed_docs/docs/category_parameters.cue +++ b/specs/signed_docs/docs/category_parameters.cue @@ -9,11 +9,9 @@ docs: #DocumentDefinitions & { Parameters which define a Category withing a Campaign under a Brand in the system. """ - metadata: { - parameters: { - required: "yes" - type: "Campaign Parameters" - } + metadata: parameters: { + required: "yes" + type: "Campaign Parameters" } versions: [ diff --git a/specs/signed_docs/docs/comment_moderation_action.cue b/specs/signed_docs/docs/comment_moderation_action.cue index e30bdc90cff..6e1fb9764c0 100644 --- a/specs/signed_docs/docs/comment_moderation_action.cue +++ b/specs/signed_docs/docs/comment_moderation_action.cue @@ -8,12 +8,9 @@ docs: #DocumentDefinitions & { A Moderation Action performed on any Comment. """ - metadata: { - ref: { - required: "yes" - type: ["Proposal Comment"] - } - + metadata: ref: { + required: "yes" + type: ["Proposal Comment"] } versions: [ diff --git a/specs/signed_docs/docs/decision_parameters.cue b/specs/signed_docs/docs/decision_parameters.cue index 133d908d5e0..5edf8a813a3 100644 --- a/specs/signed_docs/docs/decision_parameters.cue +++ b/specs/signed_docs/docs/decision_parameters.cue @@ -8,11 +8,9 @@ docs: #DocumentDefinitions & { Parameters which define an individual voting event. """ - metadata: { - parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - } + metadata: parameters: { + required: "yes" + type: doc_clusters."System Parameters".docs } versions: [ diff --git a/specs/signed_docs/docs/proposal.cue b/specs/signed_docs/docs/proposal.cue index 776fe17cf6f..c6c4c2ee3f5 100644 --- a/specs/signed_docs/docs/proposal.cue +++ b/specs/signed_docs/docs/proposal.cue @@ -3,7 +3,7 @@ package signed_docs // Proposal Document Definition docs: #DocumentDefinitions & { - "Proposal": { + Proposal: { description: """ A Proposal is a document which describes a proposed solution or project to address the criteria of a category within a campaign. @@ -61,13 +61,9 @@ docs: #DocumentDefinitions & { type: "Proposal Template" } - collaborators: { - required: "optional" - } + collaborators: required: "optional" - revocations: { - required: "optional" - } + revocations: required: "optional" parameters: { required: "yes" @@ -78,30 +74,22 @@ docs: #DocumentDefinitions & { } } - payload: { - description: """ - Proposal Document drafted for submission to a category of a campaign. + payload: description: """ + Proposal Document drafted for submission to a category of a campaign. - Must be valid according to the schema contained within the - `Document Reference` from the `template` metadata. - """ - } + Must be valid according to the schema contained within the + `Document Reference` from the `template` metadata. + """ signers: { - roles: { - user: [ - "Proposer", - ] - } + roles: user: [ + "Proposer", + ] - update: { - "collaborators": true - } + update: collaborators: true } - authors: { - "Steven Johnson": "steven.johnson@iohk.io" - } + authors: "Steven Johnson": "steven.johnson@iohk.io" versions: [ { diff --git a/specs/signed_docs/docs/proposal_comment.cue b/specs/signed_docs/docs/proposal_comment.cue index 95a2f30d2a4..335147324d0 100644 --- a/specs/signed_docs/docs/proposal_comment.cue +++ b/specs/signed_docs/docs/proposal_comment.cue @@ -49,18 +49,14 @@ docs: #DocumentDefinitions & { type: "Proposal Comment" } - section: { - required: "optional" - } + section: required: "optional" template: { required: "yes" type: "Proposal Comment Template" } - revocations: { - required: "optional" - } + revocations: required: "optional" parameters: { required: "yes" @@ -72,11 +68,9 @@ docs: #DocumentDefinitions & { } } - payload: { - description: """ - JSON Document which must validate against the referenced template. - """ - } + payload: description: """ + JSON Document which must validate against the referenced template. + """ versions: [ { diff --git a/specs/signed_docs/docs/proposal_comment_meta_template.cue b/specs/signed_docs/docs/proposal_comment_meta_template.cue index f335f592c8e..05947a4c9fa 100644 --- a/specs/signed_docs/docs/proposal_comment_meta_template.cue +++ b/specs/signed_docs/docs/proposal_comment_meta_template.cue @@ -13,17 +13,11 @@ docs: #DocumentDefinitions & { The payload of a proposal comment template is controlled by its meta template. """ - headers: { - "content type": { - value: "application/schema+json" - } - } + headers: "content type": value: "application/schema+json" - metadata: { - parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - } + metadata: parameters: { + required: "yes" + type: doc_clusters."System Parameters".docs } payload: { @@ -37,18 +31,15 @@ docs: #DocumentDefinitions & { schema: "https://json-schema.org/draft-07/schema" } - - "signers": { - roles: { - // No User Role may publish this document. - user: [] - - // Root Admin and brand Admin may publish this document. - admin: [ - "Root Admin", - "Brand Admin", - ] - } + signers: roles: { + // No User Role may publish this document. + user: [] + + // Root Admin and brand Admin may publish this document. + admin: [ + "Root Admin", + "Brand Admin", + ] } versions: [ diff --git a/specs/signed_docs/docs/proposal_comment_template.cue b/specs/signed_docs/docs/proposal_comment_template.cue index b64d401d56d..ba12fab5ad9 100644 --- a/specs/signed_docs/docs/proposal_comment_template.cue +++ b/specs/signed_docs/docs/proposal_comment_template.cue @@ -16,11 +16,7 @@ docs: #DocumentDefinitions & { The payload of a proposal comment is controlled by its template. """ - headers: { - "content type": { - value: "application/schema+json" - } - } + headers: "content type": value: "application/schema+json" metadata: { template: { @@ -34,23 +30,19 @@ docs: #DocumentDefinitions & { } } - payload: { - description: """ - JSON Schema document which defines the content of the Proposal Comments. - """ - } + payload: description: """ + JSON Schema document which defines the content of the Proposal Comments. + """ - signers: { - roles: { - // No User Role may publish this document. - user: [] + signers: roles: { + // No User Role may publish this document. + user: [] - // Brand Admin and Lower may publish this document. - admin: [ - "Brand Admin", - "Campaign Admin", - ] - } + // Brand Admin and Lower may publish this document. + admin: [ + "Brand Admin", + "Campaign Admin", + ] } versions: [ diff --git a/specs/signed_docs/docs/proposal_meta_template.cue b/specs/signed_docs/docs/proposal_meta_template.cue index 6fd78e38144..6b0ea8a7e69 100644 --- a/specs/signed_docs/docs/proposal_meta_template.cue +++ b/specs/signed_docs/docs/proposal_meta_template.cue @@ -13,17 +13,11 @@ docs: #DocumentDefinitions & { The payload of a proposal template is controlled by its meta template. """ - headers: { - "content type": { - value: "application/schema+json" - } - } + headers: "content type": value: "application/schema+json" - metadata: { - parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - } + metadata: parameters: { + required: "yes" + type: doc_clusters."System Parameters".docs } payload: { @@ -37,18 +31,15 @@ docs: #DocumentDefinitions & { schema: "https://json-schema.org/draft-07/schema" } - - "signers": { - roles: { - // No User Role may publish this document. - user: [] - - // Root Admin and brand Admin may publish this document. - admin: [ - "Root Admin", - "Brand Admin", - ] - } + signers: roles: { + // No User Role may publish this document. + user: [] + + // Root Admin and brand Admin may publish this document. + admin: [ + "Root Admin", + "Brand Admin", + ] } versions: [ diff --git a/specs/signed_docs/docs/proposal_moderation_action.cue b/specs/signed_docs/docs/proposal_moderation_action.cue index e6fdcda9a82..a91a356705c 100644 --- a/specs/signed_docs/docs/proposal_moderation_action.cue +++ b/specs/signed_docs/docs/proposal_moderation_action.cue @@ -9,11 +9,10 @@ docs: #DocumentDefinitions & { A Moderation action performed on a Proposal. """ - metadata: { - ref: { - required: "yes" - type: "Proposal" - }} + metadata: ref: { + required: "yes" + type: "Proposal" + } versions: [ { diff --git a/specs/signed_docs/docs/proposal_submission_action.cue b/specs/signed_docs/docs/proposal_submission_action.cue index 6d09f9a7fd1..03518f9a42a 100644 --- a/specs/signed_docs/docs/proposal_submission_action.cue +++ b/specs/signed_docs/docs/proposal_submission_action.cue @@ -120,8 +120,7 @@ docs: #DocumentDefinitions & { }, ] } - - "signers": { + signers: { roles: { // Proposers may publish this document. user: [ @@ -131,9 +130,7 @@ docs: #DocumentDefinitions & { referenced: true - update: { - collaborators: true - } + update: collaborators: true } versions: [ diff --git a/specs/signed_docs/docs/proposal_template.cue b/specs/signed_docs/docs/proposal_template.cue index 845059d0224..af711f15bbf 100644 --- a/specs/signed_docs/docs/proposal_template.cue +++ b/specs/signed_docs/docs/proposal_template.cue @@ -16,11 +16,7 @@ docs: #DocumentDefinitions & { The payload of a proposal is controlled by its template. """ - headers: { - "content type": { - value: "application/schema+json" - } - } + headers: "content type": value: "application/schema+json" metadata: { template: { @@ -37,23 +33,19 @@ docs: #DocumentDefinitions & { } } - payload: { - description: """ - JSON Schema document which defines the valid contents of a proposal document. - """ - } + payload: description: """ + JSON Schema document which defines the valid contents of a proposal document. + """ - signers: { - roles: { - // No User Role may publish this document. - user: [] + signers: roles: { + // No User Role may publish this document. + user: [] - // Brand Admin and Lower may publish this document. - admin: [ - "Brand Admin", - "Campaign Admin", - ] - } + // Brand Admin and Lower may publish this document. + admin: [ + "Brand Admin", + "Campaign Admin", + ] } versions: [ diff --git a/specs/signed_docs/documentation_links.cue b/specs/signed_docs/documentation_links.cue index ff9f1bc98df..590e4e4c9bb 100644 --- a/specs/signed_docs/documentation_links.cue +++ b/specs/signed_docs/documentation_links.cue @@ -12,9 +12,7 @@ import ( [_allMetadataNames]: #metadataField } -#namedLink: { - [string]: string -} +#namedLink: [string]: string // Constrains the URLs being linked to be unique #uniqueLinkValues: list.UniqueItems @@ -24,9 +22,9 @@ 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 + 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 @@ -40,16 +38,14 @@ documentationLinks: { for k, _ in documentationLinks {k}, ]) -linkAKA: { - [string]: #allLinkNames -} +linkAKA: [string]: #allLinkNames // Known aliases for links. Lets us automatically create [Named Link][Reference Link] linkAKA: { - "UUIDv7": "RFC9562-V7" - "UUIDv4": "RFC9562-V4" - "UUID": "RFC9562" - "URI": "RFC3986" + UUIDv7: "RFC9562-V7" + UUIDv4: "RFC9562-V4" + UUID: "RFC9562" + URI: "RFC3986" "UTF-8": "RFC3629" "CBOR Encoded IPLD Content Identifier": "CBOR-TAG-42" "IPFS CID": "IPFS-CID" diff --git a/specs/signed_docs/metadata.cue b/specs/signed_docs/metadata.cue index b1952e70f61..58a347cc13f 100644 --- a/specs/signed_docs/metadata.cue +++ b/specs/signed_docs/metadata.cue @@ -22,11 +22,11 @@ metadataFormats: #metadataFormats & { description: "A document reference identifier" cddl: "document_ref" } - "UUIDv7": { + UUIDv7: { description: "Version 7 formatted UUID" cddl: "uuid_v7" } - "UUIDv4": { + UUIDv4: { description: "Version 4 formatted UUID" cddl: "uuid_v4" } diff --git a/specs/signed_docs/signed_doc.cue b/specs/signed_docs/signed_doc.cue index 796da6b1079..fc1ff536136 100644 --- a/specs/signed_docs/signed_doc.cue +++ b/specs/signed_docs/signed_doc.cue @@ -63,9 +63,7 @@ import ( // Customize each document type in its own `.cue` file. docs: #DocumentDefinitions & { for k, v in _allDocs { - (k): { - type: v - } + (k): type: v } } From 9d66693c124387d8ce8824e921e2df64bf810c61 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 9 Jun 2025 17:51:52 +0700 Subject: [PATCH 09/42] feat(docs): WIP template defs dictionary --- specs/gen_docs/spec/json_schema_defs.py | 31 +++ specs/gen_docs/spec/signed_doc.py | 2 + specs/signed_doc.json | 231 ++++++++++++++++++ specs/template_field_definitions/field.cue | 6 + .../multi_line_text_entry_markdown_list.cue | 34 +++ .../fields/multi_select.cue | 4 + .../fields/single_grouped_tag_selector.cue | 47 ++++ .../single_line_https_url_entry_list.cue | 34 +++ .../fields/single_line_text_entry_list.cue | 34 +++ .../template_field_definitions/parameters.cue | 40 +++ 10 files changed, 463 insertions(+) create mode 100644 specs/gen_docs/spec/json_schema_defs.py create mode 100644 specs/template_field_definitions/fields/multi_line_text_entry_markdown_list.cue create mode 100644 specs/template_field_definitions/fields/single_grouped_tag_selector.cue create mode 100644 specs/template_field_definitions/fields/single_line_https_url_entry_list.cue create mode 100644 specs/template_field_definitions/fields/single_line_text_entry_list.cue diff --git a/specs/gen_docs/spec/json_schema_defs.py b/specs/gen_docs/spec/json_schema_defs.py new file mode 100644 index 00000000000..779f22efa2a --- /dev/null +++ b/specs/gen_docs/spec/json_schema_defs.py @@ -0,0 +1,31 @@ +"""Jsonschema Def Definition.""" + +from typing import Any + +from pydantic import BaseModel, ConfigDict, Field + +from spec.optional import OptionalField + + +class JsonSchemaDefParameters(BaseModel): + """Specification of a single Json Schema Template Definition.""" + + property: str | None = Field(default=None) + description: str + required: OptionalField + type: str + items: "None | JsonSchemaDefParameters" = Field(default=None) + choices: list[str] | None = Field(default=None) + + model_config = ConfigDict(extra="forbid") + + +class JsonSchemaDefs(BaseModel): + """Specification of an individual Json Schema Template Definition.""" + + description: str + definition: dict[str, Any] # Raw definition from JSON + parameters: dict[str, JsonSchemaDefParameters] + parent: str | None = Field(default=None) + + model_config = ConfigDict(extra="forbid") diff --git a/specs/gen_docs/spec/signed_doc.py b/specs/gen_docs/spec/signed_doc.py index ad1ae1d7714..4f141b696a6 100644 --- a/specs/gen_docs/spec/signed_doc.py +++ b/specs/gen_docs/spec/signed_doc.py @@ -18,6 +18,7 @@ from spec.cose_header import CoseHeader from spec.doc_clusters import DocCluster from spec.document import Document +from spec.json_schema_defs import JsonSchemaDefs from spec.metadata import Metadata from spec.metadata_formats import MetadataFormats from spec.optional import OptionalField @@ -70,6 +71,7 @@ class SignedDoc(BaseModel): metadata: dict[str, Metadata] metadata_formats: dict[str, MetadataFormats] = Field(alias="metadataFormats") metadata_order: list[str] + template_json_schema_defs: dict[str, JsonSchemaDefs] = Field(alias="templateJsonSchemaDefs") _data: dict[str, typing.Any] _file: str diff --git a/specs/signed_doc.json b/specs/signed_doc.json index e758e66669c..0603165eb9e 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -2380,6 +2380,68 @@ } } }, + "multiLineTextEntryListMarkdown": { + "definition": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "items": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "contentMediaType": "text/markdown", + "minLength": 1, + "pattern": "^[\\S\\s]*$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "description": "UI - A Growable List of markdown formatted text fields.\nEach entry is a multiline markdown formatted string.\nMarkdown Formatting, line breaks, or special characters are allowed.\nAdd multiple text entries.\nEach entry should be unique.", + "parameters": { + "contains": { + "description": "The choices the multi select can contain.", + "items": { + "description": "An individual Choice.", + "required": "excluded", + "type": "string" + }, + "required": "yes", + "type": "array" + }, + "default": { + "description": "Default Array of text can be supplied.", + "required": "optional", + "type": "string" + }, + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "maxItems": { + "description": "An array instance is valid against \"maxItems\" if its size is less than, or equal to, the value of this keyword.", + "required": "yes", + "type": "integer" + }, + "minItems": { + "description": "An array instance is valid against \"minItems\" if its size is greater than, or equal to, the value of this keyword.", + "required": "optional", + "type": "integer" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + }, + "x-placeholder": { + "description": "Placeholder text to display inside the field if it is empty.", + "required": "optional", + "type": "string" + } + } + }, "multiLineTextEntryMarkdown": { "definition": { "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", @@ -2445,6 +2507,11 @@ "required": "yes", "type": "array" }, + "default": { + "description": "Default selections can be supplied.", + "required": "optional", + "type": "string" + }, "description": { "description": "The description of the field presented during data entry.", "required": "optional", @@ -3144,6 +3211,46 @@ } } }, + "singleGroupedTagSelector": { + "definition": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "additionalProperties": false, + "required": [ + "group", + "tag" + ], + "type": "object" + }, + "description": "UI - A selector where a top level group selection, allows a single choice from a list of tags.\nSelect one option from the dropdown menu. \nOnly one choice is allowed.\n\nThe contents of the `singleGroupedTagSelector` *MUST* have the following format:\n\n```json\n\"oneOf\": [\n\t{\n\t\t\"properties\": {\n\t\t\t\"group\": {\n\t\t\t\t\"$ref\": \"#/definitions/tagGroup\",\n\t\t\t\t\"const\": \"Governance\"\n\t\t\t},\n\t\t\t\"tag\": {\n\t\t\t\t\"$ref\": \"#/definitions/tagSelection\",\n\t\t\t\t\"enum\": [\n\t\t\t\t\t\"Governance\",\n\t\t\t\t\t\"DAO\"\n\t\t\t\t]\n\t\t\t}\n\t\t}\n\t},\n```", + "parameters": { + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "oneOf_groupedTags": { + "description": "A set of tags with a group selector.", + "items": { + "description": "\tAn array of grouped tag objects, of which one can be selected.\n\tEach object *MUST* have the form:\n\t\n\t```json\n\t\"properties\": {\n\t\t\"group\": {\n\t\t\t\"$ref\": \"#/definitions/tagGroup\",\n\t\t\t\"const\": \n\t\t},\n\t\t\"tag\": {\n\t\t\t\"$ref\": \"#/definitions/tagSelection\",\n\t\t\t\"enum\": [\n\t\t\t\t,\n\t\t\t\t,\n\t\t\t\t...\n\t\t\t]\n\t\t}\n\t}\n\t```", + "required": "excluded", + "type": "object" + }, + "property": "oneOf", + "required": "excluded", + "type": "array" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + } + } + }, "singleLineHttpsURLEntry": { "definition": { "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", @@ -3185,6 +3292,68 @@ } } }, + "singleLineHttpsURLEntryList": { + "definition": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "items": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "format": "uri", + "minLength": 1, + "pattern": "^https://[^\\s]+$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "description": "UI - A Growable List of single line text\nA single line of text.\nNo formatting, markup, line breaks, or special characters are allowed.\nAdd multiple single-line text entries.\nEach entry should be unique.", + "parameters": { + "contains": { + "description": "The choices the multi select can contain.", + "items": { + "description": "An individual Choice.", + "required": "excluded", + "type": "string" + }, + "required": "yes", + "type": "array" + }, + "default": { + "description": "Default Array of URLs can be supplied.", + "required": "optional", + "type": "string" + }, + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "maxItems": { + "description": "An array instance is valid against \"maxItems\" if its size is less than, or equal to, the value of this keyword.", + "required": "yes", + "type": "integer" + }, + "minItems": { + "description": "An array instance is valid against \"minItems\" if its size is greater than, or equal to, the value of this keyword.", + "required": "optional", + "type": "integer" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + }, + "x-placeholder": { + "description": "Placeholder text to display inside the field if it is empty.", + "required": "optional", + "type": "string" + } + } + }, "singleLineTextEntry": { "definition": { "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", @@ -3225,6 +3394,68 @@ "type": "string" } } + }, + "singleLineTextEntryList": { + "definition": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "items": { + "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", + "contentMediaType": "text/plain", + "minLength": 1, + "pattern": "^.*$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "description": "UI - A Growable List of single line text\nA single line of text.\nNo formatting, markup, line breaks, or special characters are allowed.\nAdd multiple single-line text entries.\nEach entry should be unique.", + "parameters": { + "contains": { + "description": "The choices the multi select can contain.", + "items": { + "description": "An individual Choice.", + "required": "excluded", + "type": "string" + }, + "required": "yes", + "type": "array" + }, + "default": { + "description": "Default Array of text can be supplied.", + "required": "optional", + "type": "string" + }, + "description": { + "description": "The description of the field presented during data entry.", + "required": "optional", + "type": "string" + }, + "maxItems": { + "description": "An array instance is valid against \"maxItems\" if its size is less than, or equal to, the value of this keyword.", + "required": "yes", + "type": "integer" + }, + "minItems": { + "description": "An array instance is valid against \"minItems\" if its size is greater than, or equal to, the value of this keyword.", + "required": "optional", + "type": "integer" + }, + "title": { + "description": "The label attached to the field.", + "required": "yes", + "type": "string" + }, + "x-guidance": { + "description": "Long form Markdown formatted description to give guidance about how the field is to be completed.", + "required": "optional", + "type": "string" + }, + "x-placeholder": { + "description": "Placeholder text to display inside the field if it is empty.", + "required": "optional", + "type": "string" + } + } } } } diff --git a/specs/template_field_definitions/field.cue b/specs/template_field_definitions/field.cue index 6ead7081e44..3cb274a571d 100644 --- a/specs/template_field_definitions/field.cue +++ b/specs/template_field_definitions/field.cue @@ -5,6 +5,10 @@ import ( "regexp" ) +// Note: only attributes which make sense for and are used by definitions +// are defined. This should not list any attribute which would needlessly +// restrict the definition, and should otherwise be a parameter set by the +// template itself. #fieldDefinition: { $comment: "See the Template Schema Definition Dictionary for detailed documentation." type: #fieldType @@ -12,6 +16,7 @@ import ( if type == "object" { additionalProperties: false // IF false, can not define extra fields. + required?: [...string] } if type == "array" { @@ -23,6 +28,7 @@ import ( format?: #formatChoices contentMediaType?: #contentMediaTypeChoices pattern?: regexp.Valid + minLength?: int // Only to enforce that the field can not be empty (such as when used in lists) } } diff --git a/specs/template_field_definitions/fields/multi_line_text_entry_markdown_list.cue b/specs/template_field_definitions/fields/multi_line_text_entry_markdown_list.cue new file mode 100644 index 00000000000..b91f04ddfdd --- /dev/null +++ b/specs/template_field_definitions/fields/multi_line_text_entry_markdown_list.cue @@ -0,0 +1,34 @@ +// Single Line Text Entry List + +package template_field_definitions + +dictionary: #jsonSchemaFields & { + multiLineTextEntryListMarkdown: { + description: """ + UI - A Growable List of markdown formatted text fields. + Each entry is a multiline markdown formatted string. + Markdown Formatting, line breaks, or special characters are allowed. + Add multiple text entries. + Each entry should be unique. + """ + definition: { + type: "array" + items: dictionary.multiLineTextEntryMarkdown.definition + items: minLength: 1 + uniqueItems: true + } + parameters: { + title: {} + description: {} + default: { + description: "Default Array of text can be supplied." + required: "optional" + } + minItems: {} + maxItems: {} + contains: {} + "x-guidance": {} + "x-placeholder": {} + } + } +} diff --git a/specs/template_field_definitions/fields/multi_select.cue b/specs/template_field_definitions/fields/multi_select.cue index 4bf532d2b1d..f49e9c37380 100644 --- a/specs/template_field_definitions/fields/multi_select.cue +++ b/specs/template_field_definitions/fields/multi_select.cue @@ -19,6 +19,10 @@ dictionary: #jsonSchemaFields & { parameters: { title: {} description: {} + default: { + description: "Default selections can be supplied." + required: "optional" + } minItems: {} maxItems: {} contains: {} diff --git a/specs/template_field_definitions/fields/single_grouped_tag_selector.cue b/specs/template_field_definitions/fields/single_grouped_tag_selector.cue new file mode 100644 index 00000000000..4d898d264f7 --- /dev/null +++ b/specs/template_field_definitions/fields/single_grouped_tag_selector.cue @@ -0,0 +1,47 @@ +// Tag Input +package template_field_definitions + +dictionary: #jsonSchemaFields & { + + singleGroupedTagSelector: { + description: """ + UI - A selector where a top level group selection, allows a single choice from a list of tags. + Select one option from the dropdown menu. + Only one choice is allowed. + + The contents of the `singleGroupedTagSelector` *MUST* have the following format: + + ```json + "oneOf": [ + { + "properties": { + "group": { + "$ref": "#/definitions/tagGroup", + "const": "Governance" + }, + "tag": { + "$ref": "#/definitions/tagSelection", + "enum": [ + "Governance", + "DAO" + ] + } + } + }, + ``` + """ + definition: { + type: "object" + required: [ + "group", + "tag", + ] + } + parameters: { + title: {} + description: {} + "x-guidance": {} + oneOf_groupedTags: {} + } + } +} diff --git a/specs/template_field_definitions/fields/single_line_https_url_entry_list.cue b/specs/template_field_definitions/fields/single_line_https_url_entry_list.cue new file mode 100644 index 00000000000..b959e2cc749 --- /dev/null +++ b/specs/template_field_definitions/fields/single_line_https_url_entry_list.cue @@ -0,0 +1,34 @@ +// Single Line Text Entry List + +package template_field_definitions + +dictionary: #jsonSchemaFields & { + singleLineHttpsURLEntryList: { + description: """ + UI - A Growable List of single line text + A single line of text. + No formatting, markup, line breaks, or special characters are allowed. + Add multiple single-line text entries. + Each entry should be unique. + """ + definition: { + type: "array" + items: dictionary.singleLineHttpsURLEntry.definition + items: minLength: 1 + uniqueItems: true + } + parameters: { + title: {} + description: {} + default: { + description: "Default Array of URLs can be supplied." + required: "optional" + } + minItems: {} + maxItems: {} + contains: {} + "x-guidance": {} + "x-placeholder": {} + } + } +} diff --git a/specs/template_field_definitions/fields/single_line_text_entry_list.cue b/specs/template_field_definitions/fields/single_line_text_entry_list.cue new file mode 100644 index 00000000000..77f61beabdc --- /dev/null +++ b/specs/template_field_definitions/fields/single_line_text_entry_list.cue @@ -0,0 +1,34 @@ +// Single Line Text Entry List + +package template_field_definitions + +dictionary: #jsonSchemaFields & { + singleLineTextEntryList: { + description: """ + UI - A Growable List of single line text + A single line of text. + No formatting, markup, line breaks, or special characters are allowed. + Add multiple single-line text entries. + Each entry should be unique. + """ + definition: { + type: "array" + items: dictionary.singleLineTextEntry.definition + items: minLength: 1 + uniqueItems: true + } + parameters: { + title: {} + description: {} + default: { + description: "Default Array of text can be supplied." + required: "optional" + } + minItems: {} + maxItems: {} + contains: {} + "x-guidance": {} + "x-placeholder": {} + } + } +} diff --git a/specs/template_field_definitions/parameters.cue b/specs/template_field_definitions/parameters.cue index a9a5721387c..b205f7e9d9e 100644 --- a/specs/template_field_definitions/parameters.cue +++ b/specs/template_field_definitions/parameters.cue @@ -16,7 +16,11 @@ import ( "object" | *"string" +// List of properties allowed in the `property` field of `jsonParameter` +#properties: "oneOf" + #jsonParameter: { + property?: #properties // Name of the property, IF its not the same as the parameter. description: string required: optional.#field type: #fieldType @@ -86,6 +90,35 @@ _allParameters: { description: _ | *"The choices the multi select can contain." required: "yes" } + oneOf_groupedTags?: #jsonParameter & { + property: "oneOf" + type: "array" + items: { + description: """ + An array of grouped tag objects, of which one can be selected. + Each object *MUST* have the form: + + ```json + "properties": { + "group": { + "$ref": "#/definitions/tagGroup", + "const": + }, + "tag": { + "$ref": "#/definitions/tagSelection", + "enum": [ + , + , + ... + ] + } + } + ``` + """ + type: "object" + } + description: "A set of tags with a group selector." + } "x-guidance"?: #jsonParameter & { description: _ | *"Long form Markdown formatted description to give guidance about how the field is to be completed." required: "optional" @@ -106,4 +139,11 @@ _allParameters: { Any field not listed here will get displayed in an arbitrary order. """ } + "x-subsection"?: #jsonParameter & { + required: "optional" + type: bool + description: """ + TODO: Explain what this parameter does... + """ + } } From 812ebdb795536eaecab1deb9139c9d02f3f5ca52 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 14 Jun 2025 22:21:33 +0700 Subject: [PATCH 10/42] fix(docs): update python files we don't want in git --- .gitignore | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9f75a0f579b..10d3ca25f74 100644 --- a/.gitignore +++ b/.gitignore @@ -87,4 +87,9 @@ $RECYCLE.BIN/ # Python stuff .pytest_cache -__pycache__ \ No newline at end of file +__pycache__ +py.typed +*.egg-info +.venv +.ruff_cache +dist \ No newline at end of file From d7fea02de80d9fa83f79d4d3fa66a4558618c903 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 14 Jun 2025 22:23:58 +0700 Subject: [PATCH 11/42] refactor(docs): reorganize the cue files for better modularity --- specs/{ => definitions}/cue.mod/module.cue | 0 .../form_template}/choices.cue | 9 ++- .../form_template}/dictionary.cue | 8 +- specs/definitions/form_template/field.cue | 75 ++++++++++++++++++ .../fields/drop_down_single_select.cue | 6 +- .../fields/multi_line_text_entry.cue | 6 +- .../fields/multi_line_text_entry_markdown.cue | 5 +- .../multi_line_text_entry_markdown_list.cue | 5 +- .../form_template}/fields/multi_select.cue | 6 +- .../fields/radio_button_select.cue | 7 +- .../fields/schema_reference.cue | 6 +- .../form_template}/fields/section.cue | 4 +- .../form_template}/fields/segment.cue | 4 +- .../fields/single_grouped_tag_selector.cue | 6 +- .../fields/single_line_https_url_entry.cue | 6 +- .../single_line_https_url_entry_list.cue | 6 +- .../fields/single_line_text_entry.cue | 11 +-- .../fields/single_line_text_entry_list.cue | 6 +- .../form_template}/icon_choices.cue | 2 +- .../form_template}/parameters.cue | 79 +++++++++++++------ .../form_template}/patterns.cue | 2 +- specs/{ => definitions}/generic/date.cue | 0 specs/{ => definitions}/generic/optional.cue | 0 specs/{ => definitions}/generic/uuid.cue | 0 .../signed_docs/authors_copyright.cue | 0 .../signed_docs/cddl_defs.cue | 0 .../signed_docs/cose_headers.cue | 0 .../signed_docs/cose_signed_doc_cddl_defs.cue | 0 .../signed_docs/docs/all.cue | 0 .../signed_docs/docs/brand_parameters.cue | 0 .../signed_docs/docs/campaign_parameters.cue | 0 .../signed_docs/docs/category_parameters.cue | 0 .../docs/comment_moderation_action.cue | 0 .../signed_docs/docs/decision_parameters.cue | 0 ...posal_submission_action.draft.example.json | 0 ...posal_submission_action.final.example.json | 0 ...oposal_submission_action.hide.example.json | 0 .../proposal_submission_action.schema.json | 0 .../signed_docs/docs/proposal.cue | 0 .../signed_docs/docs/proposal_comment.cue | 0 .../docs/proposal_comment_meta_template.cue | 0 .../docs/proposal_comment_template.cue | 0 .../docs/proposal_meta_template.cue | 0 .../docs/proposal_moderation_action.cue | 0 .../docs/proposal_submission_action.cue | 0 .../signed_docs/docs/proposal_template.cue | 0 .../signed_docs/documentation_links.cue | 0 .../signed_docs/metadata.cue | 0 .../{ => definitions}/signed_docs/payload.cue | 0 .../signed_docs/signed_doc.cue | 4 +- .../{ => definitions}/signed_docs/signers.cue | 0 specs/template_field_definitions/field.cue | 51 ------------ 52 files changed, 195 insertions(+), 119 deletions(-) rename specs/{ => definitions}/cue.mod/module.cue (100%) rename specs/{template_field_definitions => definitions/form_template}/choices.cue (75%) rename specs/{template_field_definitions => definitions/form_template}/dictionary.cue (75%) create mode 100644 specs/definitions/form_template/field.cue rename specs/{template_field_definitions => definitions/form_template}/fields/drop_down_single_select.cue (81%) rename specs/{template_field_definitions => definitions/form_template}/fields/multi_line_text_entry.cue (88%) rename specs/{template_field_definitions => definitions/form_template}/fields/multi_line_text_entry_markdown.cue (89%) rename specs/{template_field_definitions => definitions/form_template}/fields/multi_line_text_entry_markdown_list.cue (91%) rename specs/{template_field_definitions => definitions/form_template}/fields/multi_select.cue (89%) rename specs/{template_field_definitions => definitions/form_template}/fields/radio_button_select.cue (80%) rename specs/{template_field_definitions => definitions/form_template}/fields/schema_reference.cue (87%) rename specs/{template_field_definitions => definitions/form_template}/fields/section.cue (90%) rename specs/{template_field_definitions => definitions/form_template}/fields/segment.cue (91%) rename specs/{template_field_definitions => definitions/form_template}/fields/single_grouped_tag_selector.cue (91%) rename specs/{template_field_definitions => definitions/form_template}/fields/single_line_https_url_entry.cue (87%) rename specs/{template_field_definitions => definitions/form_template}/fields/single_line_https_url_entry_list.cue (90%) rename specs/{template_field_definitions => definitions/form_template}/fields/single_line_text_entry.cue (69%) rename specs/{template_field_definitions => definitions/form_template}/fields/single_line_text_entry_list.cue (90%) rename specs/{template_field_definitions => definitions/form_template}/icon_choices.cue (99%) rename specs/{template_field_definitions => definitions/form_template}/parameters.cue (64%) rename specs/{template_field_definitions => definitions/form_template}/patterns.cue (80%) rename specs/{ => definitions}/generic/date.cue (100%) rename specs/{ => definitions}/generic/optional.cue (100%) rename specs/{ => definitions}/generic/uuid.cue (100%) rename specs/{ => definitions}/signed_docs/authors_copyright.cue (100%) rename specs/{ => definitions}/signed_docs/cddl_defs.cue (100%) rename specs/{ => definitions}/signed_docs/cose_headers.cue (100%) rename specs/{ => definitions}/signed_docs/cose_signed_doc_cddl_defs.cue (100%) rename specs/{ => definitions}/signed_docs/docs/all.cue (100%) rename specs/{ => definitions}/signed_docs/docs/brand_parameters.cue (100%) rename specs/{ => definitions}/signed_docs/docs/campaign_parameters.cue (100%) rename specs/{ => definitions}/signed_docs/docs/category_parameters.cue (100%) rename specs/{ => definitions}/signed_docs/docs/comment_moderation_action.cue (100%) rename specs/{ => definitions}/signed_docs/docs/decision_parameters.cue (100%) rename specs/{ => definitions}/signed_docs/docs/payload_schemas/proposal_submission_action.draft.example.json (100%) rename specs/{ => definitions}/signed_docs/docs/payload_schemas/proposal_submission_action.final.example.json (100%) rename specs/{ => definitions}/signed_docs/docs/payload_schemas/proposal_submission_action.hide.example.json (100%) rename specs/{ => definitions}/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json (100%) rename specs/{ => definitions}/signed_docs/docs/proposal.cue (100%) rename specs/{ => definitions}/signed_docs/docs/proposal_comment.cue (100%) rename specs/{ => definitions}/signed_docs/docs/proposal_comment_meta_template.cue (100%) rename specs/{ => definitions}/signed_docs/docs/proposal_comment_template.cue (100%) rename specs/{ => definitions}/signed_docs/docs/proposal_meta_template.cue (100%) rename specs/{ => definitions}/signed_docs/docs/proposal_moderation_action.cue (100%) rename specs/{ => definitions}/signed_docs/docs/proposal_submission_action.cue (100%) rename specs/{ => definitions}/signed_docs/docs/proposal_template.cue (100%) rename specs/{ => definitions}/signed_docs/documentation_links.cue (100%) rename specs/{ => definitions}/signed_docs/metadata.cue (100%) rename specs/{ => definitions}/signed_docs/payload.cue (100%) rename specs/{ => definitions}/signed_docs/signed_doc.cue (94%) rename specs/{ => definitions}/signed_docs/signers.cue (100%) delete mode 100644 specs/template_field_definitions/field.cue diff --git a/specs/cue.mod/module.cue b/specs/definitions/cue.mod/module.cue similarity index 100% rename from specs/cue.mod/module.cue rename to specs/definitions/cue.mod/module.cue diff --git a/specs/template_field_definitions/choices.cue b/specs/definitions/form_template/choices.cue similarity index 75% rename from specs/template_field_definitions/choices.cue rename to specs/definitions/form_template/choices.cue index 8c4d6cad873..54b91c542c8 100644 --- a/specs/template_field_definitions/choices.cue +++ b/specs/definitions/form_template/choices.cue @@ -1,5 +1,5 @@ // Choices that can be made for a string field. -package template_field_definitions +package form_template import ( "list" @@ -10,9 +10,6 @@ _allFormats: list.UniqueItems _allFormats: list.Sort([ "uri", "path", - "radioButtonSelect", - "dropDownSingleSelect", - "multiSelect", ], list.Ascending) #formatChoices: or(_allFormats) @@ -21,7 +18,11 @@ _allFormats: list.Sort([ _allContentMediaTypes: list.UniqueItems _allContentMediaTypes: list.Sort([ "text/plain", + "text/plain; template=mustache", "text/markdown", + "text/markdown; template=mustache", + "text/html", + "text/html; template=mustache", ], list.Ascending) #contentMediaTypeChoices: or(_allContentMediaTypes) diff --git a/specs/template_field_definitions/dictionary.cue b/specs/definitions/form_template/dictionary.cue similarity index 75% rename from specs/template_field_definitions/dictionary.cue rename to specs/definitions/form_template/dictionary.cue index cb623e6d5d3..dad7de9b052 100644 --- a/specs/template_field_definitions/dictionary.cue +++ b/specs/definitions/form_template/dictionary.cue @@ -4,17 +4,17 @@ // and their parameters and documentation so that // a dictionary document and the definitions themselves // can be generated. -package template_field_definitions +package form_template // Types of a Metadata Fields -#templateJsonSchemaDefNames: or([ +#formTemplateElementNames: or([ for k, _ in dictionary {k}, ]) // Definitions for all defined template schema field types. -dictionary: #jsonSchemaFields & {} +formTemplate: #formTemplate & {} // Types of a Metadata Fields -#templateJsonSchemaDefNames: or([ +#formTemplateElementNames: or([ for k, _ in dictionary {k}, ]) diff --git a/specs/definitions/form_template/field.cue b/specs/definitions/form_template/field.cue new file mode 100644 index 00000000000..d679d06ac7a --- /dev/null +++ b/specs/definitions/form_template/field.cue @@ -0,0 +1,75 @@ +// Individual Field Definition. +package form_template + +import ( + "regexp" +) + +// Schema Definition for the Form Element. +// This appears in the `definitions` section of the Form Template +// exactly as defined here. +// UI *MUST* not process definitions, its only use is to enforce validation. +// UI/UX *MUST* interpret the name of the Form Element via `$ref` only. +// The values in the definition can inform creation of a valid UI widget +// which matches the Form Element, but that *MUST* not be dynamic. +#formElementDefinition: { + // The underlying json type of the Form Element. + type: #fieldType + + // IF true, the Form Element is not a data entry field. + // Depending on the Form Element, it may not be displayed by the form. + // but MUST be present in the encoded json form data.but can be used for presentation and formatting. + readOnly?: true + + // Form Elements which hold other form elements + if type == "object" { + // MUST not allow undefined properties + additionalProperties: false // IF false, can not define extra fields. + // MAY list properties as non optional by including them in a `required` list. + // properties not included in this list are optional. + // may not be entered by the user into the form, and if not entered + // should be excluded (or defaulted as required) from the + // forms json data. + required?: [...string] + } + + // Form Elements which are a list of other Form Elements + if type == "array" { + // The type of Form Elements in the list. + items: #formElementDefinition + // Are the Elements Unique? + uniqueItems: false | *true + } + + if type == "string" { + format?: #formatChoices + contentMediaType?: #contentMediaTypeChoices + pattern?: regexp.Valid + minLength?: int // Only to enforce that the field can not be empty (such as when used in lists) + } + +} + +// An Element which can be present in a Templated Form. +// Elements define both the data validation and the expected +// type of data entry UI expected of the Element. +// This allows JsonSchema to express both Validation and Presentation without +// requiring an extensive new DSL to be created. +#formElement: { + // Documentation + description: string + + // MAPS 1:1 to the `definitions` section within JSON Schema draft 7. + definition: #formElementDefinition + + // If this field type must appear only as a child of another field type. + // If `parent` is NOT defined, then the `parent` is the root of the template. + // The root object of the template is defined with the special string `{}` + // + parent: #formTemplateElementNames | *"{}" + + // The parameters supported by a particular field definition + parameters: _allParameters +} + +#formTemplate: [string]: #formElement diff --git a/specs/template_field_definitions/fields/drop_down_single_select.cue b/specs/definitions/form_template/fields/drop_down_single_select.cue similarity index 81% rename from specs/template_field_definitions/fields/drop_down_single_select.cue rename to specs/definitions/form_template/fields/drop_down_single_select.cue index 2495a25f7a4..a21d0cc7c64 100644 --- a/specs/template_field_definitions/fields/drop_down_single_select.cue +++ b/specs/definitions/form_template/fields/drop_down_single_select.cue @@ -1,8 +1,8 @@ // Radio Button selection from a list of text options. -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { dropDownSingleSelect: { description: """ UI - Drop Down Selection of a single entry from the defined enum. @@ -10,9 +10,9 @@ dictionary: #jsonSchemaFields & { Select one option from a selector styled as a dropdown menu. Only one choice is allowed. """ + parent: "section" definition: { type: "string" - format: "dropDownSingleSelect" contentMediaType: "text/plain" pattern: _regexTextSingleLine } diff --git a/specs/template_field_definitions/fields/multi_line_text_entry.cue b/specs/definitions/form_template/fields/multi_line_text_entry.cue similarity index 88% rename from specs/template_field_definitions/fields/multi_line_text_entry.cue rename to specs/definitions/form_template/fields/multi_line_text_entry.cue index 7f0c35ebd66..2840e760e9d 100644 --- a/specs/template_field_definitions/fields/multi_line_text_entry.cue +++ b/specs/definitions/form_template/fields/multi_line_text_entry.cue @@ -1,7 +1,7 @@ // Single Line Text Entry -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { multiLineTextEntry: { description: """ UI - One or more Lines of text entry. @@ -9,6 +9,8 @@ dictionary: #jsonSchemaFields & { Special formatted markup, such as Markdown are not allowed. Enter multiple lines of plain text. You can use line breaks but no special formatting. """ + parent: "section" + definition: { type: "string" contentMediaType: "text/plain" diff --git a/specs/template_field_definitions/fields/multi_line_text_entry_markdown.cue b/specs/definitions/form_template/fields/multi_line_text_entry_markdown.cue similarity index 89% rename from specs/template_field_definitions/fields/multi_line_text_entry_markdown.cue rename to specs/definitions/form_template/fields/multi_line_text_entry_markdown.cue index 659681574e8..3d06bd7ca04 100644 --- a/specs/template_field_definitions/fields/multi_line_text_entry_markdown.cue +++ b/specs/definitions/form_template/fields/multi_line_text_entry_markdown.cue @@ -1,7 +1,7 @@ // Single Line Text Entry -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { multiLineTextEntryMarkdown: { description: """ UI - Multiline text entry with Markdown content. @@ -17,6 +17,7 @@ dictionary: #jsonSchemaFields & { contentMediaType: "text/markdown" pattern: _regexTextMultiLine } + parent: "section" parameters: { title: {} description: {} diff --git a/specs/template_field_definitions/fields/multi_line_text_entry_markdown_list.cue b/specs/definitions/form_template/fields/multi_line_text_entry_markdown_list.cue similarity index 91% rename from specs/template_field_definitions/fields/multi_line_text_entry_markdown_list.cue rename to specs/definitions/form_template/fields/multi_line_text_entry_markdown_list.cue index b91f04ddfdd..c680ad79d6a 100644 --- a/specs/template_field_definitions/fields/multi_line_text_entry_markdown_list.cue +++ b/specs/definitions/form_template/fields/multi_line_text_entry_markdown_list.cue @@ -1,8 +1,8 @@ // Single Line Text Entry List -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { multiLineTextEntryListMarkdown: { description: """ UI - A Growable List of markdown formatted text fields. @@ -17,6 +17,7 @@ dictionary: #jsonSchemaFields & { items: minLength: 1 uniqueItems: true } + parent: "section" parameters: { title: {} description: {} diff --git a/specs/template_field_definitions/fields/multi_select.cue b/specs/definitions/form_template/fields/multi_select.cue similarity index 89% rename from specs/template_field_definitions/fields/multi_select.cue rename to specs/definitions/form_template/fields/multi_select.cue index f49e9c37380..82fcf100d0f 100644 --- a/specs/template_field_definitions/fields/multi_select.cue +++ b/specs/definitions/form_template/fields/multi_select.cue @@ -1,8 +1,8 @@ // Radio Button selection from a list of text options. -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { multiSelect: { description: """ UI - Multiselect from the given items. @@ -11,6 +11,8 @@ dictionary: #jsonSchemaFields & { Multiple choices are allowed. All choices MUST be unique. """ + parent: "section" + definition: { type: "array" uniqueItems: true diff --git a/specs/template_field_definitions/fields/radio_button_select.cue b/specs/definitions/form_template/fields/radio_button_select.cue similarity index 80% rename from specs/template_field_definitions/fields/radio_button_select.cue rename to specs/definitions/form_template/fields/radio_button_select.cue index e378aa6fc91..4c28c4c3818 100644 --- a/specs/template_field_definitions/fields/radio_button_select.cue +++ b/specs/definitions/form_template/fields/radio_button_select.cue @@ -1,8 +1,8 @@ // Radio Button selection from a list of text options. -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { radioButtonSelect: { description: """ UI - Radio Button Selection. @@ -10,9 +10,10 @@ dictionary: #jsonSchemaFields & { Select one option from a list of text options. Selector is styled as a set of Radio Buttons. """ + parent: "section" + definition: { type: "string" - format: "radioButtonSelect" contentMediaType: "text/plain" pattern: _regexTextSingleLine } diff --git a/specs/template_field_definitions/fields/schema_reference.cue b/specs/definitions/form_template/fields/schema_reference.cue similarity index 87% rename from specs/template_field_definitions/fields/schema_reference.cue rename to specs/definitions/form_template/fields/schema_reference.cue index 406da9ced4b..48ab3c1daf2 100644 --- a/specs/template_field_definitions/fields/schema_reference.cue +++ b/specs/definitions/form_template/fields/schema_reference.cue @@ -1,11 +1,13 @@ // Schema Reference - Not used in any UI -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { schemaReferenceNonUI: { description: """ Enforces the json document having a proper reference to the schema. """ + parent: "section" + definition: { type: "string" readOnly: true diff --git a/specs/template_field_definitions/fields/section.cue b/specs/definitions/form_template/fields/section.cue similarity index 90% rename from specs/template_field_definitions/fields/section.cue rename to specs/definitions/form_template/fields/section.cue index bcaa3be6242..97105a30443 100644 --- a/specs/template_field_definitions/fields/section.cue +++ b/specs/definitions/form_template/fields/section.cue @@ -3,9 +3,9 @@ // Segment - // Section - // Topic - -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { section: { description: """ UI - Logical Document Sub-Section Break. diff --git a/specs/template_field_definitions/fields/segment.cue b/specs/definitions/form_template/fields/segment.cue similarity index 91% rename from specs/template_field_definitions/fields/segment.cue rename to specs/definitions/form_template/fields/segment.cue index b0a1de68d08..3af9472bb4b 100644 --- a/specs/template_field_definitions/fields/segment.cue +++ b/specs/definitions/form_template/fields/segment.cue @@ -3,9 +3,9 @@ // Segment - // Section - // Topic - -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { segment: { description: """ Logical Document Section - Grouping Only - Highest Level Group diff --git a/specs/template_field_definitions/fields/single_grouped_tag_selector.cue b/specs/definitions/form_template/fields/single_grouped_tag_selector.cue similarity index 91% rename from specs/template_field_definitions/fields/single_grouped_tag_selector.cue rename to specs/definitions/form_template/fields/single_grouped_tag_selector.cue index 4d898d264f7..b1f18645e58 100644 --- a/specs/template_field_definitions/fields/single_grouped_tag_selector.cue +++ b/specs/definitions/form_template/fields/single_grouped_tag_selector.cue @@ -1,7 +1,7 @@ // Tag Input -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { singleGroupedTagSelector: { description: """ @@ -30,6 +30,8 @@ dictionary: #jsonSchemaFields & { }, ``` """ + parent: "section" + definition: { type: "object" required: [ diff --git a/specs/template_field_definitions/fields/single_line_https_url_entry.cue b/specs/definitions/form_template/fields/single_line_https_url_entry.cue similarity index 87% rename from specs/template_field_definitions/fields/single_line_https_url_entry.cue rename to specs/definitions/form_template/fields/single_line_https_url_entry.cue index 5f1b65cc216..f9fd59be6a9 100644 --- a/specs/template_field_definitions/fields/single_line_https_url_entry.cue +++ b/specs/definitions/form_template/fields/single_line_https_url_entry.cue @@ -1,7 +1,7 @@ // Single Line HTTPS URL Text Entry -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { singleLineHttpsURLEntry: { description: """ UI - Single Line text entry for HTTPS Urls. @@ -10,6 +10,8 @@ dictionary: #jsonSchemaFields & { non-whitespace characters, ending at the end of the string. """ + parent: "section" + definition: { type: "string" format: "uri" diff --git a/specs/template_field_definitions/fields/single_line_https_url_entry_list.cue b/specs/definitions/form_template/fields/single_line_https_url_entry_list.cue similarity index 90% rename from specs/template_field_definitions/fields/single_line_https_url_entry_list.cue rename to specs/definitions/form_template/fields/single_line_https_url_entry_list.cue index b959e2cc749..1c1c4843804 100644 --- a/specs/template_field_definitions/fields/single_line_https_url_entry_list.cue +++ b/specs/definitions/form_template/fields/single_line_https_url_entry_list.cue @@ -1,8 +1,8 @@ // Single Line Text Entry List -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { singleLineHttpsURLEntryList: { description: """ UI - A Growable List of single line text @@ -11,6 +11,8 @@ dictionary: #jsonSchemaFields & { Add multiple single-line text entries. Each entry should be unique. """ + parent: "section" + definition: { type: "array" items: dictionary.singleLineHttpsURLEntry.definition diff --git a/specs/template_field_definitions/fields/single_line_text_entry.cue b/specs/definitions/form_template/fields/single_line_text_entry.cue similarity index 69% rename from specs/template_field_definitions/fields/single_line_text_entry.cue rename to specs/definitions/form_template/fields/single_line_text_entry.cue index 03d70bd8530..d79b8b397cf 100644 --- a/specs/template_field_definitions/fields/single_line_text_entry.cue +++ b/specs/definitions/form_template/fields/single_line_text_entry.cue @@ -1,17 +1,18 @@ // Single Line Text Entry -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { singleLineTextEntry: { description: """ UI - Single Line text entry without any markup or rich text capability. A single line of text. No formatting, markup, line breaks, or special characters are allowed. """ + parent: "section" + definition: { - type: "string" - contentMediaType: "text/plain" - pattern: _regexTextSingleLine + type: "string" + pattern: _regexTextSingleLine } parameters: { title: {} diff --git a/specs/template_field_definitions/fields/single_line_text_entry_list.cue b/specs/definitions/form_template/fields/single_line_text_entry_list.cue similarity index 90% rename from specs/template_field_definitions/fields/single_line_text_entry_list.cue rename to specs/definitions/form_template/fields/single_line_text_entry_list.cue index 77f61beabdc..961d421cf5d 100644 --- a/specs/template_field_definitions/fields/single_line_text_entry_list.cue +++ b/specs/definitions/form_template/fields/single_line_text_entry_list.cue @@ -1,8 +1,8 @@ // Single Line Text Entry List -package template_field_definitions +package form_template -dictionary: #jsonSchemaFields & { +dictionary: #formTemplate & { singleLineTextEntryList: { description: """ UI - A Growable List of single line text @@ -11,6 +11,8 @@ dictionary: #jsonSchemaFields & { Add multiple single-line text entries. Each entry should be unique. """ + parent: "section" + definition: { type: "array" items: dictionary.singleLineTextEntry.definition diff --git a/specs/template_field_definitions/icon_choices.cue b/specs/definitions/form_template/icon_choices.cue similarity index 99% rename from specs/template_field_definitions/icon_choices.cue rename to specs/definitions/form_template/icon_choices.cue index bb1d438814b..dfc4b77de8d 100644 --- a/specs/template_field_definitions/icon_choices.cue +++ b/specs/definitions/form_template/icon_choices.cue @@ -1,7 +1,7 @@ // List of all valid ICON choices. // The UI is free to render Icons or not and render them in its own style. // However, Icons not listed here are not supported. -package template_field_definitions +package form_template import ( "list" diff --git a/specs/template_field_definitions/parameters.cue b/specs/definitions/form_template/parameters.cue similarity index 64% rename from specs/template_field_definitions/parameters.cue rename to specs/definitions/form_template/parameters.cue index b205f7e9d9e..ab877972b0c 100644 --- a/specs/template_field_definitions/parameters.cue +++ b/specs/definitions/form_template/parameters.cue @@ -1,8 +1,9 @@ // Definitions of the field parameters within a template. -package template_field_definitions +package form_template import ( "list" + "regexp" "github.com/input-output-hk/catalyst-libs/specs/generic:optional" ) @@ -19,50 +20,82 @@ import ( // List of properties allowed in the `property` field of `jsonParameter` #properties: "oneOf" -#jsonParameter: { +#parameter: { property?: #properties // Name of the property, IF its not the same as the parameter. description: string required: optional.#field - type: #fieldType - items?: #jsonParameter - choices?: list.UniqueItems + + // The following constrain the value of the parameter + // within a template. + // They DO NOT constrain the value of the field element + // The parameter relates to. + // The Field element is constrained by the parameters value. + // Their purpose is to assist creation of templates to set + // the appropriate form element parameters within the template properties. + type: #fieldType + items?: #parameter + choices?: list.UniqueItems + + // All parameters when defined require an example of their use + // within the + example?: _ // Set to `null` ONLY when the example is autogenerated. + + // If the parameter is a `string` it can be constrained with the following + // options. + if type == "string" { + format?: #formatChoices + contentMediaType?: #contentMediaTypeChoices + pattern?: regexp.Valid + minLength?: int // Only to enforce that the field can not be empty (such as when used in lists) + choices?: [...string] + } + + // If the parameter is a `integer` it can be constrained with the following + // options. + if type == "integer" { + choices?: [...int] + minimum?: int + maximum?: int + } + } // The parameters supported by a particular field definition _allParameters: { - title?: #jsonParameter & { + title?: #parameter & { description: _ | *"The label attached to the field." required: "yes" } - description?: #jsonParameter & { + description?: #parameter & { description: _ | *"The description of the field presented during data entry." required: "optional" } - required?: #jsonParameter & { + required?: #parameter & { required: _ | *"optional" } - default?: #jsonParameter & { + default?: #parameter & { required: _ | *"yes" } - const?: #jsonParameter & { + const?: #parameter & { required: _ | *"yes" } - properties?: #jsonParameter & { + properties?: #parameter & { required: _ | *"yes" description: _ | *"All sub fields contained in the object." required: "yes" + //example: null // Example properties are generated from child properties. } - minLength?: #jsonParameter & { + minLength?: #parameter & { type: "integer" description: _ | *"Minimum number of characters allowed in the field." required: "optional" } - maxLength?: #jsonParameter & { + maxLength?: #parameter & { type: "integer" description: _ | *"Maximum number of characters allowed in the field." required: "yes" } - enum?: #jsonParameter & { + enum?: #parameter & { type: "array" items: { description: "An element of the Enum." @@ -71,17 +104,17 @@ _allParameters: { description: _ | *"An array of string to select from." required: "yes" } - minItems?: #jsonParameter & { + minItems?: #parameter & { type: "integer" description: _ | *#"An array instance is valid against "minItems" if its size is greater than, or equal to, the value of this keyword."# required: "optional" } - maxItems?: #jsonParameter & { + maxItems?: #parameter & { type: "integer" description: _ | *#"An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword."# required: "yes" } - contains?: #jsonParameter & { + contains?: #parameter & { type: "array" items: { description: "An individual Choice." @@ -90,7 +123,7 @@ _allParameters: { description: _ | *"The choices the multi select can contain." required: "yes" } - oneOf_groupedTags?: #jsonParameter & { + oneOf_groupedTags?: #parameter & { property: "oneOf" type: "array" items: { @@ -119,27 +152,27 @@ _allParameters: { } description: "A set of tags with a group selector." } - "x-guidance"?: #jsonParameter & { + "x-guidance"?: #parameter & { description: _ | *"Long form Markdown formatted description to give guidance about how the field is to be completed." required: "optional" } - "x-placeholder"?: #jsonParameter & { + "x-placeholder"?: #parameter & { description: _ | *"Placeholder text to display inside the field if it is empty." required: "optional" } - "x-icon"?: #jsonParameter & { + "x-icon"?: #parameter & { description: _ | *"The name of the Icon to display with the field." required: "optional" choices: _allIcons } - "x-order"?: #jsonParameter & { + "x-order"?: #parameter & { required: "yes" description: """ The ordering of the properties to be enforced when displayed. Any field not listed here will get displayed in an arbitrary order. """ } - "x-subsection"?: #jsonParameter & { + "x-subsection"?: #parameter & { required: "optional" type: bool description: """ diff --git a/specs/template_field_definitions/patterns.cue b/specs/definitions/form_template/patterns.cue similarity index 80% rename from specs/template_field_definitions/patterns.cue rename to specs/definitions/form_template/patterns.cue index 645d512570a..3079fea973e 100644 --- a/specs/template_field_definitions/patterns.cue +++ b/specs/definitions/form_template/patterns.cue @@ -1,5 +1,5 @@ // Regex patterns that are defined. -package template_field_definitions +package form_template _regexTextSingleLine: #"^.*$"# _regexTextMultiLine: #"^[\S\s]*$"# diff --git a/specs/generic/date.cue b/specs/definitions/generic/date.cue similarity index 100% rename from specs/generic/date.cue rename to specs/definitions/generic/date.cue diff --git a/specs/generic/optional.cue b/specs/definitions/generic/optional.cue similarity index 100% rename from specs/generic/optional.cue rename to specs/definitions/generic/optional.cue diff --git a/specs/generic/uuid.cue b/specs/definitions/generic/uuid.cue similarity index 100% rename from specs/generic/uuid.cue rename to specs/definitions/generic/uuid.cue diff --git a/specs/signed_docs/authors_copyright.cue b/specs/definitions/signed_docs/authors_copyright.cue similarity index 100% rename from specs/signed_docs/authors_copyright.cue rename to specs/definitions/signed_docs/authors_copyright.cue diff --git a/specs/signed_docs/cddl_defs.cue b/specs/definitions/signed_docs/cddl_defs.cue similarity index 100% rename from specs/signed_docs/cddl_defs.cue rename to specs/definitions/signed_docs/cddl_defs.cue diff --git a/specs/signed_docs/cose_headers.cue b/specs/definitions/signed_docs/cose_headers.cue similarity index 100% rename from specs/signed_docs/cose_headers.cue rename to specs/definitions/signed_docs/cose_headers.cue diff --git a/specs/signed_docs/cose_signed_doc_cddl_defs.cue b/specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue similarity index 100% rename from specs/signed_docs/cose_signed_doc_cddl_defs.cue rename to specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue diff --git a/specs/signed_docs/docs/all.cue b/specs/definitions/signed_docs/docs/all.cue similarity index 100% rename from specs/signed_docs/docs/all.cue rename to specs/definitions/signed_docs/docs/all.cue diff --git a/specs/signed_docs/docs/brand_parameters.cue b/specs/definitions/signed_docs/docs/brand_parameters.cue similarity index 100% rename from specs/signed_docs/docs/brand_parameters.cue rename to specs/definitions/signed_docs/docs/brand_parameters.cue diff --git a/specs/signed_docs/docs/campaign_parameters.cue b/specs/definitions/signed_docs/docs/campaign_parameters.cue similarity index 100% rename from specs/signed_docs/docs/campaign_parameters.cue rename to specs/definitions/signed_docs/docs/campaign_parameters.cue diff --git a/specs/signed_docs/docs/category_parameters.cue b/specs/definitions/signed_docs/docs/category_parameters.cue similarity index 100% rename from specs/signed_docs/docs/category_parameters.cue rename to specs/definitions/signed_docs/docs/category_parameters.cue diff --git a/specs/signed_docs/docs/comment_moderation_action.cue b/specs/definitions/signed_docs/docs/comment_moderation_action.cue similarity index 100% rename from specs/signed_docs/docs/comment_moderation_action.cue rename to specs/definitions/signed_docs/docs/comment_moderation_action.cue diff --git a/specs/signed_docs/docs/decision_parameters.cue b/specs/definitions/signed_docs/docs/decision_parameters.cue similarity index 100% rename from specs/signed_docs/docs/decision_parameters.cue rename to specs/definitions/signed_docs/docs/decision_parameters.cue diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.draft.example.json b/specs/definitions/signed_docs/docs/payload_schemas/proposal_submission_action.draft.example.json similarity index 100% rename from specs/signed_docs/docs/payload_schemas/proposal_submission_action.draft.example.json rename to specs/definitions/signed_docs/docs/payload_schemas/proposal_submission_action.draft.example.json diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.final.example.json b/specs/definitions/signed_docs/docs/payload_schemas/proposal_submission_action.final.example.json similarity index 100% rename from specs/signed_docs/docs/payload_schemas/proposal_submission_action.final.example.json rename to specs/definitions/signed_docs/docs/payload_schemas/proposal_submission_action.final.example.json diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.hide.example.json b/specs/definitions/signed_docs/docs/payload_schemas/proposal_submission_action.hide.example.json similarity index 100% rename from specs/signed_docs/docs/payload_schemas/proposal_submission_action.hide.example.json rename to specs/definitions/signed_docs/docs/payload_schemas/proposal_submission_action.hide.example.json diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json b/specs/definitions/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json similarity index 100% rename from specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json rename to specs/definitions/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json diff --git a/specs/signed_docs/docs/proposal.cue b/specs/definitions/signed_docs/docs/proposal.cue similarity index 100% rename from specs/signed_docs/docs/proposal.cue rename to specs/definitions/signed_docs/docs/proposal.cue diff --git a/specs/signed_docs/docs/proposal_comment.cue b/specs/definitions/signed_docs/docs/proposal_comment.cue similarity index 100% rename from specs/signed_docs/docs/proposal_comment.cue rename to specs/definitions/signed_docs/docs/proposal_comment.cue diff --git a/specs/signed_docs/docs/proposal_comment_meta_template.cue b/specs/definitions/signed_docs/docs/proposal_comment_meta_template.cue similarity index 100% rename from specs/signed_docs/docs/proposal_comment_meta_template.cue rename to specs/definitions/signed_docs/docs/proposal_comment_meta_template.cue diff --git a/specs/signed_docs/docs/proposal_comment_template.cue b/specs/definitions/signed_docs/docs/proposal_comment_template.cue similarity index 100% rename from specs/signed_docs/docs/proposal_comment_template.cue rename to specs/definitions/signed_docs/docs/proposal_comment_template.cue diff --git a/specs/signed_docs/docs/proposal_meta_template.cue b/specs/definitions/signed_docs/docs/proposal_meta_template.cue similarity index 100% rename from specs/signed_docs/docs/proposal_meta_template.cue rename to specs/definitions/signed_docs/docs/proposal_meta_template.cue diff --git a/specs/signed_docs/docs/proposal_moderation_action.cue b/specs/definitions/signed_docs/docs/proposal_moderation_action.cue similarity index 100% rename from specs/signed_docs/docs/proposal_moderation_action.cue rename to specs/definitions/signed_docs/docs/proposal_moderation_action.cue diff --git a/specs/signed_docs/docs/proposal_submission_action.cue b/specs/definitions/signed_docs/docs/proposal_submission_action.cue similarity index 100% rename from specs/signed_docs/docs/proposal_submission_action.cue rename to specs/definitions/signed_docs/docs/proposal_submission_action.cue diff --git a/specs/signed_docs/docs/proposal_template.cue b/specs/definitions/signed_docs/docs/proposal_template.cue similarity index 100% rename from specs/signed_docs/docs/proposal_template.cue rename to specs/definitions/signed_docs/docs/proposal_template.cue diff --git a/specs/signed_docs/documentation_links.cue b/specs/definitions/signed_docs/documentation_links.cue similarity index 100% rename from specs/signed_docs/documentation_links.cue rename to specs/definitions/signed_docs/documentation_links.cue diff --git a/specs/signed_docs/metadata.cue b/specs/definitions/signed_docs/metadata.cue similarity index 100% rename from specs/signed_docs/metadata.cue rename to specs/definitions/signed_docs/metadata.cue diff --git a/specs/signed_docs/payload.cue b/specs/definitions/signed_docs/payload.cue similarity index 100% rename from specs/signed_docs/payload.cue rename to specs/definitions/signed_docs/payload.cue diff --git a/specs/signed_docs/signed_doc.cue b/specs/definitions/signed_docs/signed_doc.cue similarity index 94% rename from specs/signed_docs/signed_doc.cue rename to specs/definitions/signed_docs/signed_doc.cue index fc1ff536136..a6b12e3ae46 100644 --- a/specs/signed_docs/signed_doc.cue +++ b/specs/definitions/signed_docs/signed_doc.cue @@ -7,7 +7,7 @@ import ( "list" "strings" "github.com/input-output-hk/catalyst-libs/specs/generic:uuid" - "github.com/input-output-hk/catalyst-libs/specs/template_field_definitions/fields:template_field_definitions" + "github.com/input-output-hk/catalyst-libs/specs/form_template/fields:form_template" ) // Document Type must be a valid UUIDv4 @@ -118,4 +118,4 @@ _allDocNames: or(_allDocNamesList) // Individual Valid Document Name constraint. #DocumentName: _allDocNames -templateJsonSchemaDefs: template_field_definitions.dictionary +formTemplate: form_template.dictionary diff --git a/specs/signed_docs/signers.cue b/specs/definitions/signed_docs/signers.cue similarity index 100% rename from specs/signed_docs/signers.cue rename to specs/definitions/signed_docs/signers.cue diff --git a/specs/template_field_definitions/field.cue b/specs/template_field_definitions/field.cue deleted file mode 100644 index 3cb274a571d..00000000000 --- a/specs/template_field_definitions/field.cue +++ /dev/null @@ -1,51 +0,0 @@ -// Individual Field Definition. -package template_field_definitions - -import ( - "regexp" -) - -// Note: only attributes which make sense for and are used by definitions -// are defined. This should not list any attribute which would needlessly -// restrict the definition, and should otherwise be a parameter set by the -// template itself. -#fieldDefinition: { - $comment: "See the Template Schema Definition Dictionary for detailed documentation." - type: #fieldType - readOnly?: true // IF true, is not a data entry field, but can be used for presentation and formatting. - - if type == "object" { - additionalProperties: false // IF false, can not define extra fields. - required?: [...string] - } - - if type == "array" { - items: #fieldDefinition - uniqueItems?: true - } - - if type == "string" { - format?: #formatChoices - contentMediaType?: #contentMediaTypeChoices - pattern?: regexp.Valid - minLength?: int // Only to enforce that the field can not be empty (such as when used in lists) - } - -} - -// A JSON Schema field definition -#jsonSchemaFieldDefinition: { - // Documentation - description: string - - // MAPS 1:1 to the `definitions` section within JSON Schema draft 7. - definition: #fieldDefinition - - // If this field type must appear only as a child of another field type. - parent?: #templateJsonSchemaDefNames - - // The parameters supported by a particular field definition - parameters: _allParameters -} - -#jsonSchemaFields: [string]: #jsonSchemaFieldDefinition From e27969144ae216fff502afc7f127e24d94a2770e Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 14 Jun 2025 22:25:50 +0700 Subject: [PATCH 12/42] refactor(docs): Move spec python model for better modularity --- specs/gen_docs/spec/json_schema_defs.py | 31 ------ .../generators/packages/spec/.python-version | 1 + specs/generators/packages/spec/README.md | 0 specs/generators/packages/spec/pyproject.toml | 17 ++++ .../packages/spec/src}/spec/__init__.py | 3 +- .../packages/spec/src/spec/cddl/__init__.py | 3 + .../spec/src}/spec/cddl_definitions.py | 0 .../spec/src}/spec/change_log_entry.py | 0 .../packages/spec/src}/spec/content_types.py | 0 .../packages/spec/src}/spec/copyright.py | 0 .../packages/spec/src}/spec/cose_header.py | 0 .../packages/spec/src}/spec/doc_clusters.py | 0 .../packages/spec/src}/spec/document.py | 0 .../packages/spec/src/spec/forms/__init__.py | 3 + .../spec/src/spec/forms/element/__init__.py | 3 + .../spec/src/spec/forms/element/element.py | 46 +++++++++ .../spec/src/spec/forms/element/parameters.py | 96 +++++++++++++++++++ .../packages/spec/src/spec/forms/template.py | 44 +++++++++ .../packages/spec/src/spec/hello.py | 6 ++ .../packages/spec/src}/spec/metadata.py | 0 .../spec/src}/spec/metadata_formats.py | 0 .../packages/spec/src}/spec/optional.py | 0 .../packages/spec/src}/spec/payload.py | 14 ++- .../packages/spec/src}/spec/signed_doc.py | 19 ++-- .../packages/spec/src}/spec/signers.py | 0 25 files changed, 242 insertions(+), 44 deletions(-) delete mode 100644 specs/gen_docs/spec/json_schema_defs.py create mode 100644 specs/generators/packages/spec/.python-version create mode 100644 specs/generators/packages/spec/README.md create mode 100644 specs/generators/packages/spec/pyproject.toml rename specs/{gen_docs => generators/packages/spec/src}/spec/__init__.py (50%) create mode 100644 specs/generators/packages/spec/src/spec/cddl/__init__.py rename specs/{gen_docs => generators/packages/spec/src}/spec/cddl_definitions.py (100%) rename specs/{gen_docs => generators/packages/spec/src}/spec/change_log_entry.py (100%) rename specs/{gen_docs => generators/packages/spec/src}/spec/content_types.py (100%) rename specs/{gen_docs => generators/packages/spec/src}/spec/copyright.py (100%) rename specs/{gen_docs => generators/packages/spec/src}/spec/cose_header.py (100%) rename specs/{gen_docs => generators/packages/spec/src}/spec/doc_clusters.py (100%) rename specs/{gen_docs => generators/packages/spec/src}/spec/document.py (100%) create mode 100644 specs/generators/packages/spec/src/spec/forms/__init__.py create mode 100644 specs/generators/packages/spec/src/spec/forms/element/__init__.py create mode 100644 specs/generators/packages/spec/src/spec/forms/element/element.py create mode 100644 specs/generators/packages/spec/src/spec/forms/element/parameters.py create mode 100644 specs/generators/packages/spec/src/spec/forms/template.py create mode 100644 specs/generators/packages/spec/src/spec/hello.py rename specs/{gen_docs => generators/packages/spec/src}/spec/metadata.py (100%) rename specs/{gen_docs => generators/packages/spec/src}/spec/metadata_formats.py (100%) rename specs/{gen_docs => generators/packages/spec/src}/spec/optional.py (100%) rename specs/{gen_docs => generators/packages/spec/src}/spec/payload.py (84%) rename specs/{gen_docs => generators/packages/spec/src}/spec/signed_doc.py (95%) rename specs/{gen_docs => generators/packages/spec/src}/spec/signers.py (100%) diff --git a/specs/gen_docs/spec/json_schema_defs.py b/specs/gen_docs/spec/json_schema_defs.py deleted file mode 100644 index 779f22efa2a..00000000000 --- a/specs/gen_docs/spec/json_schema_defs.py +++ /dev/null @@ -1,31 +0,0 @@ -"""Jsonschema Def Definition.""" - -from typing import Any - -from pydantic import BaseModel, ConfigDict, Field - -from spec.optional import OptionalField - - -class JsonSchemaDefParameters(BaseModel): - """Specification of a single Json Schema Template Definition.""" - - property: str | None = Field(default=None) - description: str - required: OptionalField - type: str - items: "None | JsonSchemaDefParameters" = Field(default=None) - choices: list[str] | None = Field(default=None) - - model_config = ConfigDict(extra="forbid") - - -class JsonSchemaDefs(BaseModel): - """Specification of an individual Json Schema Template Definition.""" - - description: str - definition: dict[str, Any] # Raw definition from JSON - parameters: dict[str, JsonSchemaDefParameters] - parent: str | None = Field(default=None) - - model_config = ConfigDict(extra="forbid") diff --git a/specs/generators/packages/spec/.python-version b/specs/generators/packages/spec/.python-version new file mode 100644 index 00000000000..24ee5b1be99 --- /dev/null +++ b/specs/generators/packages/spec/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/specs/generators/packages/spec/README.md b/specs/generators/packages/spec/README.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/specs/generators/packages/spec/pyproject.toml b/specs/generators/packages/spec/pyproject.toml new file mode 100644 index 00000000000..f6396ccf16f --- /dev/null +++ b/specs/generators/packages/spec/pyproject.toml @@ -0,0 +1,17 @@ +[project] +name = "spec" +version = "0.1.0" +description = "Interpreted Specification Library" +readme = "README.md" +authors = [ + { name = "Steven Johnson", email = "steven.joshnson@iohk.io" } +] +requires-python = ">=3.13" +dependencies = [] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["src/spec"] \ No newline at end of file diff --git a/specs/gen_docs/spec/__init__.py b/specs/generators/packages/spec/src/spec/__init__.py similarity index 50% rename from specs/gen_docs/spec/__init__.py rename to specs/generators/packages/spec/src/spec/__init__.py index 16ad0890f59..241c60cc2b4 100644 --- a/specs/gen_docs/spec/__init__.py +++ b/specs/generators/packages/spec/src/spec/__init__.py @@ -1,2 +1,3 @@ -# Intentionally Empty """Spec Definition Module.""" + +# Intentionally Empty File. diff --git a/specs/generators/packages/spec/src/spec/cddl/__init__.py b/specs/generators/packages/spec/src/spec/cddl/__init__.py new file mode 100644 index 00000000000..104d9cd342c --- /dev/null +++ b/specs/generators/packages/spec/src/spec/cddl/__init__.py @@ -0,0 +1,3 @@ +"""Spec - CDDL - Definition Module.""" + +# Intentionally Empty File. diff --git a/specs/gen_docs/spec/cddl_definitions.py b/specs/generators/packages/spec/src/spec/cddl_definitions.py similarity index 100% rename from specs/gen_docs/spec/cddl_definitions.py rename to specs/generators/packages/spec/src/spec/cddl_definitions.py diff --git a/specs/gen_docs/spec/change_log_entry.py b/specs/generators/packages/spec/src/spec/change_log_entry.py similarity index 100% rename from specs/gen_docs/spec/change_log_entry.py rename to specs/generators/packages/spec/src/spec/change_log_entry.py diff --git a/specs/gen_docs/spec/content_types.py b/specs/generators/packages/spec/src/spec/content_types.py similarity index 100% rename from specs/gen_docs/spec/content_types.py rename to specs/generators/packages/spec/src/spec/content_types.py diff --git a/specs/gen_docs/spec/copyright.py b/specs/generators/packages/spec/src/spec/copyright.py similarity index 100% rename from specs/gen_docs/spec/copyright.py rename to specs/generators/packages/spec/src/spec/copyright.py diff --git a/specs/gen_docs/spec/cose_header.py b/specs/generators/packages/spec/src/spec/cose_header.py similarity index 100% rename from specs/gen_docs/spec/cose_header.py rename to specs/generators/packages/spec/src/spec/cose_header.py diff --git a/specs/gen_docs/spec/doc_clusters.py b/specs/generators/packages/spec/src/spec/doc_clusters.py similarity index 100% rename from specs/gen_docs/spec/doc_clusters.py rename to specs/generators/packages/spec/src/spec/doc_clusters.py diff --git a/specs/gen_docs/spec/document.py b/specs/generators/packages/spec/src/spec/document.py similarity index 100% rename from specs/gen_docs/spec/document.py rename to specs/generators/packages/spec/src/spec/document.py diff --git a/specs/generators/packages/spec/src/spec/forms/__init__.py b/specs/generators/packages/spec/src/spec/forms/__init__.py new file mode 100644 index 00000000000..e0dcc786dcf --- /dev/null +++ b/specs/generators/packages/spec/src/spec/forms/__init__.py @@ -0,0 +1,3 @@ +"""Spec - Forms - Definition Module.""" + +# Intentionally Empty File. diff --git a/specs/generators/packages/spec/src/spec/forms/element/__init__.py b/specs/generators/packages/spec/src/spec/forms/element/__init__.py new file mode 100644 index 00000000000..e0dcc786dcf --- /dev/null +++ b/specs/generators/packages/spec/src/spec/forms/element/__init__.py @@ -0,0 +1,3 @@ +"""Spec - Forms - Definition Module.""" + +# Intentionally Empty File. diff --git a/specs/generators/packages/spec/src/spec/forms/element/element.py b/specs/generators/packages/spec/src/spec/forms/element/element.py new file mode 100644 index 00000000000..86ee64d5fd7 --- /dev/null +++ b/specs/generators/packages/spec/src/spec/forms/element/element.py @@ -0,0 +1,46 @@ +"""Form Template Definition.""" + +from functools import cached_property +from typing import Any + +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, computed_field + +from spec.forms.element.parameters import Parameters + + +class Element(BaseModel): + """Specification of an individual Form Element.""" + + description: str + definition: dict[str, Any] # Raw definition from JSON + parameters: Parameters + parent: str | None = Field(default=None) + _name: str = PrivateAttr(default="Unknown") + + model_config = ConfigDict(extra="forbid") + + @computed_field + def name(self) -> str: # type: ignore[obscured] + """Name Of the Parameter.""" + return self._name + + @name.setter # type: ignore[prop-decorator] + def name(self, val: str) -> None: + self._name = val + + @computed_field() + @cached_property + def json_definition(self) -> dict[str, Any]: + """Json Definition.""" + return self.definition + + @computed_field() + @cached_property + def example(self) -> dict[str, Any]: + """Generate an example of the definition.""" + name = self._name + example_name = "example" + name[0].upper() + name[1:] + example: dict[str, Any] = {example_name: self.parameters.example} + example["$ref"] = f"#/$defs/{name}" + + return example diff --git a/specs/generators/packages/spec/src/spec/forms/element/parameters.py b/specs/generators/packages/spec/src/spec/forms/element/parameters.py new file mode 100644 index 00000000000..4245c797d9d --- /dev/null +++ b/specs/generators/packages/spec/src/spec/forms/element/parameters.py @@ -0,0 +1,96 @@ +"""Form Template Definition.""" + +import typing +from functools import cached_property +from typing import Any + +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, RootModel, computed_field + +from spec.optional import OptionalField + + +class Parameter(BaseModel): + """Specification of a single Json Schema Template Definition. + + Models `specs/definitions/form_template/parameters.cue:#parameter` + """ + + property: str | None = Field(default=None) + description: str + required: OptionalField + type: str + items: "None | Parameter" = Field(default=None) + choices: list[str] | list[int] | None = Field(default=None) + format: str | None = Field(default=None) + content_media_type: str | None = Field(default=None, alias="contentMediaType") + pattern: str | None = Field(default=None) + min_length: int | None = Field(default=None) + minimum: int | None = Field(default=None) + maximum: int | None = Field(default=None) + example: Any = Field(default=None) + _name: str = PrivateAttr(default="Unknown") + _element_name: str = PrivateAttr(default="Unknown") + + model_config = ConfigDict(extra="forbid") + + @computed_field + def element_name(self) -> str: # type: ignore[obscured] + """Name Of the Parameters Element Type.""" + return self._name + + @element_name.setter # type: ignore[prop-decorator] + def element_name(self, val: str) -> None: + self._name = val + + @computed_field + def name(self) -> str: # type: ignore[obscured] + """Name Of the Parameter.""" + return self._name + + @name.setter # type: ignore[prop-decorator] + def name(self, val: str) -> None: + self._name = val + + def example_kv(self, index: int = 0) -> tuple[str, Any]: + """Generate an example value of the parameter.""" + prop = self.property if self.property is not None else "Unknown" + value: dict[Any, Any] | str = {} + if self.type == "string": + value = f"An Example String {index}" + + return (prop, value) + + +class Parameters(RootModel[dict[str, Parameter]]): + """All Parameters defined for an Element.""" + + root: dict[str, Parameter] + _element_name: str = PrivateAttr(default="Unknown") + + @computed_field + def element_name(self) -> str | None: # type: ignore[obscured] + """Name Of the Parameters Element Type.""" + return self._name + + @element_name.setter # type: ignore[prop-decorator] + def element_name(self, val: str) -> None: + self._name = val + for name, value in self.root.items(): + value.element_name = name + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + for name, value in self.root.items(): + value.name = name + + @computed_field() + @cached_property + def example(self) -> dict[str, Any]: + """Generate an example of the definition.""" + example: dict[str, Any] = {} + + for name, value in self.root.items(): + example[name] = value.example + return example diff --git a/specs/generators/packages/spec/src/spec/forms/template.py b/specs/generators/packages/spec/src/spec/forms/template.py new file mode 100644 index 00000000000..40ed2459dd3 --- /dev/null +++ b/specs/generators/packages/spec/src/spec/forms/template.py @@ -0,0 +1,44 @@ +"""Form Template Definition.""" + +import typing +from functools import cached_property +from typing import Any + +from pydantic import RootModel, computed_field + +from spec.forms.element.element import Element + + +class FormTemplate(RootModel[dict[str, Element]]): + """Template Json Schema Definitions.""" + + root: dict[str, Element] + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + for def_name, value in self.root.items(): + value.name = def_name + + @computed_field() + @cached_property + def json_definition(self) -> dict[str, Any]: + """Json Definition.""" + definitions: dict[str, Any] = {} + + for k, v in self.root.items(): + definitions[k] = v.json_definition + + return definitions + + @computed_field() + @cached_property + def example(self) -> dict[str, Any]: + """Generate an example of the definitions.""" + examples: dict[str, Any] = {} + + for k, v in self.root.items(): + examples[k] = v.example + + return examples diff --git a/specs/generators/packages/spec/src/spec/hello.py b/specs/generators/packages/spec/src/spec/hello.py new file mode 100644 index 00000000000..8262099a66d --- /dev/null +++ b/specs/generators/packages/spec/src/spec/hello.py @@ -0,0 +1,6 @@ +"""Test.""" + + +def get_hello_world() -> str: + """Test.""" + return "Hello World from spec!" diff --git a/specs/gen_docs/spec/metadata.py b/specs/generators/packages/spec/src/spec/metadata.py similarity index 100% rename from specs/gen_docs/spec/metadata.py rename to specs/generators/packages/spec/src/spec/metadata.py diff --git a/specs/gen_docs/spec/metadata_formats.py b/specs/generators/packages/spec/src/spec/metadata_formats.py similarity index 100% rename from specs/gen_docs/spec/metadata_formats.py rename to specs/generators/packages/spec/src/spec/metadata_formats.py diff --git a/specs/gen_docs/spec/optional.py b/specs/generators/packages/spec/src/spec/optional.py similarity index 100% rename from specs/gen_docs/spec/optional.py rename to specs/generators/packages/spec/src/spec/optional.py diff --git a/specs/gen_docs/spec/payload.py b/specs/generators/packages/spec/src/spec/payload.py similarity index 84% rename from specs/gen_docs/spec/payload.py rename to specs/generators/packages/spec/src/spec/payload.py index 3caa4efdc04..dfe075d969a 100644 --- a/specs/gen_docs/spec/payload.py +++ b/specs/generators/packages/spec/src/spec/payload.py @@ -65,6 +65,8 @@ def model_post_init(self, context: Any) -> None: # noqa: ANN401 if isinstance(self.doc_schema, HttpUrl): if f"{self.doc_schema}" == "https://json-schema.org/draft-07/schema": schema = jsonschema.Draft7Validator.META_SCHEMA + elif f"{self.doc_schema}" == "https://json-schema.org/draft/2020-12/schema": + schema = jsonschema.Draft202012Validator.META_SCHEMA else: rich.print(f"Downloading Schema from: {self.doc_schema}") with urllib.request.urlopen(f"{self.doc_schema}") as response: # noqa: S310 @@ -73,9 +75,15 @@ def model_post_init(self, context: Any) -> None: # noqa: ANN401 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) + # Check that its valid jsonschema Draft 7 or 202012. + try: + jsonschema.Draft7Validator.check_schema(schema) + validator = jsonschema.Draft7Validator(schema, format_checker=jsonschema.draft7_format_checker) + except: # noqa: E722 + jsonschema.Draft202012Validator.check_schema(schema) + validator = jsonschema.Draft202012Validator( + schema, format_checker=jsonschema.draft202012_format_checker + ) for example in self.examples: if validator is None: diff --git a/specs/gen_docs/spec/signed_doc.py b/specs/generators/packages/spec/src/spec/signed_doc.py similarity index 95% rename from specs/gen_docs/spec/signed_doc.py rename to specs/generators/packages/spec/src/spec/signed_doc.py index 4f141b696a6..43d47d0aa0d 100644 --- a/specs/gen_docs/spec/signed_doc.py +++ b/specs/generators/packages/spec/src/spec/signed_doc.py @@ -9,7 +9,7 @@ from enum import Enum from pathlib import Path -from pydantic import BaseModel, ConfigDict, Field, HttpUrl +from pydantic import BaseModel, ConfigDict, Field, HttpUrl, PrivateAttr from spec.cddl_definitions import CDDLDefinition from spec.change_log_entry import ChangeLogEntry @@ -18,7 +18,7 @@ from spec.cose_header import CoseHeader from spec.doc_clusters import DocCluster from spec.document import Document -from spec.json_schema_defs import JsonSchemaDefs +from spec.forms.template import FormTemplate from spec.metadata import Metadata from spec.metadata_formats import MetadataFormats from spec.optional import OptionalField @@ -71,10 +71,10 @@ class SignedDoc(BaseModel): metadata: dict[str, Metadata] metadata_formats: dict[str, MetadataFormats] = Field(alias="metadataFormats") metadata_order: list[str] - template_json_schema_defs: dict[str, JsonSchemaDefs] = Field(alias="templateJsonSchemaDefs") + form_template: FormTemplate = Field(alias="formTemplate") - _data: dict[str, typing.Any] - _file: str + _data: dict[str, typing.Any] = PrivateAttr(default_factory=dict[str, typing.Any]) + _file: str = PrivateAttr(default="Uninitialized") model_config = ConfigDict(extra="forbid") @@ -82,10 +82,11 @@ 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[str, typing.Any] = json.load(f) - doc = cls(**data) - doc._data = data - doc._file = spec_file + raw_json = f.read() + doc = cls.model_validate_json(raw_json, strict=True) + data: dict[str, typing.Any] = json.loads(raw_json) + doc._data = data # noqa: SLF001 + doc._file = spec_file # noqa: SLF001 return doc def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 diff --git a/specs/gen_docs/spec/signers.py b/specs/generators/packages/spec/src/spec/signers.py similarity index 100% rename from specs/gen_docs/spec/signers.py rename to specs/generators/packages/spec/src/spec/signers.py From c1aeb7a3234dd63b3e4bf806d894aff92d0a7a5d Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 14 Jun 2025 22:27:32 +0700 Subject: [PATCH 13/42] docs(docs): Add base of new spec python workspace and modules --- specs/Justfile | 21 +- specs/generators/.python-version | 1 + specs/generators/pyproject.toml | 40 ++ specs/generators/ruff.toml | 1 + specs/generators/src/validator/__init__.py | 1 + specs/generators/src/validator/main.py | 73 ++++ specs/generators/uv.lock | 403 ++++++++++++++++++++ specs/signed_doc.json | 422 ++++++++++----------- 8 files changed, 737 insertions(+), 225 deletions(-) create mode 100644 specs/generators/.python-version create mode 100644 specs/generators/pyproject.toml create mode 120000 specs/generators/ruff.toml create mode 100644 specs/generators/src/validator/__init__.py create mode 100644 specs/generators/src/validator/main.py create mode 100644 specs/generators/uv.lock diff --git a/specs/Justfile b/specs/Justfile index 5e2d5af2b0b..89ef29a9699 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -10,36 +10,39 @@ default: # Fix cue files. This also sets all the file times on the cue files to NOW. # So it should only be run when required. fix: - cue fix ./signed_docs/docs:signed_docs - cue fix ./template_field_definitions/fields:template_field_definitions + cue fix ./definitions/signed_docs/docs:signed_docs + cue fix ./definitions/form_template/fields:form_template # Fix the format of cue files format: - cue fmt -s --files . + cue fmt -s --files ./definitions # Check the signed document cue files are valid. check: format - cue vet ./signed_docs/docs:signed_docs -c - cue vet ./template_field_definitions/fields:template_field_definitions -c + cd definitions; cue vet ./signed_docs/docs:signed_docs -c + cd definitions; cue vet ./form_template/fields:form_template -c # Regenerate the full signed document specification json file. regenerate-signed-doc-json: # Make sure keys are sorted so its both reproducible, AND diffs easily. - cue export -f -s ./signed_docs/docs:signed_docs --out json | jq -S > signed_doc.json + cd definitions; cue export -f -s ./signed_docs/docs:signed_docs --out json | jq -S > ../signed_doc.json # Fix and Check Markdown files regenerate: check regenerate-signed-doc-json validate && validate-docs # Generate the markdown docs from the specification. - cd gen_docs; ./main.py -g -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json + #cd gen_docs; ./main.py -g -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json # Validate the generated signed_docs.json is correct against the cue schema. validate: - cue vet ./signed_docs/docs:signed_docs signed_doc.json + # Generate the intermediate compiled schema data. + cd definitions; cue vet ./signed_docs/docs:signed_docs ../signed_doc.json + # Check the Model is valid. + cd generators; uv run validator ../signed_doc.json # Validate the generated docs is correct against the signed_docs.json. validate-docs: # Check our validation code actually works properly - cd gen_docs; ./main.py -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json + #cd gen_docs; ./main.py -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json # Pre Push Checks - intended to be run by a git pre-push hook. pre-push: format-python-code lint-python regenerate validate diff --git a/specs/generators/.python-version b/specs/generators/.python-version new file mode 100644 index 00000000000..24ee5b1be99 --- /dev/null +++ b/specs/generators/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/specs/generators/pyproject.toml b/specs/generators/pyproject.toml new file mode 100644 index 00000000000..f3cc2c7bdf8 --- /dev/null +++ b/specs/generators/pyproject.toml @@ -0,0 +1,40 @@ +[project] +name = "generators" +version = "0.1.0" +requires-python = ">=3.13" +dependencies = [ + "jsonschema[format]>=4.24.0", + "pydantic>=2.11.6", + "pydot>=4.0.0", + "rich>=14.0.0", + "rich-argparse>=1.7.1", + "spec", +] + +[project.scripts] +validator = "validator.main:main" + +[tool.uv.workspace] +members = [ + "packages/spec", +] + +[tool.uv.sources] +spec = { workspace = true } + +[tool.ruff] +# Extend the project wide `ruff.toml` file. +# Done so we can add known libraries to sorting. +extend = "ruff.toml" + +[tool.ruff.lint.isort] +known-third-party = ["pydantic", "pydot", "rich", "rich-argparse"] + +known-first-party = ["spec"] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["src/validator", "packages/spec"] \ No newline at end of file diff --git a/specs/generators/ruff.toml b/specs/generators/ruff.toml new file mode 120000 index 00000000000..e768b4aa2c2 --- /dev/null +++ b/specs/generators/ruff.toml @@ -0,0 +1 @@ +../../ruff.toml \ No newline at end of file diff --git a/specs/generators/src/validator/__init__.py b/specs/generators/src/validator/__init__.py new file mode 100644 index 00000000000..5182ed05f62 --- /dev/null +++ b/specs/generators/src/validator/__init__.py @@ -0,0 +1 @@ +"""Intentionally Blank.""" diff --git a/specs/generators/src/validator/main.py b/specs/generators/src/validator/main.py new file mode 100644 index 00000000000..685f6375c55 --- /dev/null +++ b/specs/generators/src/validator/main.py @@ -0,0 +1,73 @@ +"""Specification Validator.""" + +import argparse +import sys + +import rich +from pydantic import ValidationError +from rich.table import Table +from rich_argparse import RichHelpFormatter +from spec.signed_doc import SignedDoc + + +def parse_args() -> argparse.Namespace: + """Initialise and run the CLI parser.""" + parser = argparse.ArgumentParser( + description="Project Catalyst - Architectural Specifications Validator", + formatter_class=RichHelpFormatter, + ) + parser.add_argument("spec", help="Path to JSON Specification file") + + return parser.parse_args() + + +def main() -> None: + """Validate Architectural Specifications.""" + args = parse_args() + + # Get the compiled documentation json file + # Specs are validated automatically on load. + try: + _spec = SignedDoc.load(args.spec) + rich.print("Architectural Specifications Validated Successfully.") + except ValidationError as exc: + table = Table( + title=f"{exc.error_count()} Locations where Schema Data does not match the {exc.title} Model.", + caption="Model does not match Schema and needs updating.", + ) + table.add_column("Key", no_wrap=True, style="yellow") + table.add_column("Error", no_wrap=True, style="red") + table.add_column("Input", no_wrap=True, max_width=30, style="grey37") + + error_links: dict[str, str] = {} + errors = exc.errors() + errors.sort(key=lambda x: [x["loc"], x["type"]]) + for error in errors: + error_links[error["msg"]] = error["url"] # type: ignore # noqa: PGH003 + + loc: list[str] = [] + for x in error["loc"]: + if isinstance(x, int): + loc.append(f"[{x}]") + else: + loc.append(f"{x}") + + table.add_row( + ".".join(loc), + error["msg"], + str(error["input"]).splitlines()[0], + ) + rich.print(table) + + for msg, url in error_links.items(): + rich.print(f"* {msg} : {url}") + + sys.exit(1) + + except Exception: # noqa: BLE001 + rich.get_console().print_exception(show_locals=True) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/specs/generators/uv.lock b/specs/generators/uv.lock new file mode 100644 index 00000000000..d681470c72c --- /dev/null +++ b/specs/generators/uv.lock @@ -0,0 +1,403 @@ +version = 1 +revision = 2 +requires-python = ">=3.13" + +[manifest] +members = [ + "generators", + "spec", +] + +[[package]] +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" } +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" }, +] + +[[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]] +name = "generators" +version = "0.1.0" +source = { editable = "." } +dependencies = [ + { name = "jsonschema", extra = ["format"] }, + { name = "pydantic" }, + { name = "pydot" }, + { name = "rich" }, + { name = "rich-argparse" }, + { name = "spec" }, +] + +[package.metadata] +requires-dist = [ + { name = "jsonschema", extras = ["format"], specifier = ">=4.24.0" }, + { name = "pydantic", specifier = ">=2.11.6" }, + { name = "pydot", specifier = ">=4.0.0" }, + { name = "rich", specifier = ">=14.0.0" }, + { name = "rich-argparse", specifier = ">=1.7.1" }, + { name = "spec", editable = "packages/spec" }, +] + +[[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.24.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/bf/d3/1cf5326b923a53515d8f3a2cd442e6d7e94fcc444716e879ea70a0ce3177/jsonschema-4.24.0.tar.gz", hash = "sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196", size = 353480, upload-time = "2025-05-26T18:48:10.459Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/3d/023389198f69c722d039351050738d6755376c8fd343e91dc493ea485905/jsonschema-4.24.0-py3-none-any.whl", hash = "sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d", size = 88709, upload-time = "2025-05-26T18:48:08.417Z" }, +] + +[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" +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" } +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" }, +] + +[[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" } +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" }, +] + +[[package]] +name = "pydantic" +version = "2.11.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/8f/9af0f46acc943b8c4592d06523f26a150acf6e6e37e8bd5f0ace925e996d/pydantic-2.11.6.tar.gz", hash = "sha256:12b45cfb4af17e555d3c6283d0b55271865fb0b43cc16dd0d52749dc7abf70e7", size = 787868, upload-time = "2025-06-13T09:00:29.595Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/11/7912a9a194ee4ea96520740d1534bc31a03a4a59d62e1d7cac9461d3f379/pydantic-2.11.6-py3-none-any.whl", hash = "sha256:a24478d2be1b91b6d3bc9597439f69ed5e87f68ebd285d86f7c7932a084b72e7", size = 444718, upload-time = "2025-06-13T09:00:27.134Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +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" } +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" }, +] + +[[package]] +name = "pydot" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyparsing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/c3/6034ed1ebf2e3ba95a0e35fa7c43104e40444c0ed2b5325702c63e824dbf/pydot-4.0.0.tar.gz", hash = "sha256:12f16493337cade2f7631b87c8ccd299ba2e251f3ee5d0732a058df2887afe97", size = 161793, upload-time = "2025-05-04T11:13:03.214Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/16/984c0cf5073a23154b1f95c9d131b14c9fea83bfadae4ba8fc169daded11/pydot-4.0.0-py3-none-any.whl", hash = "sha256:cf86e13a6cfe2a96758a9702537f77e0ac1368db8ef277b4d3b34473ea425c97", size = 37535, upload-time = "2025-05-04T11:13:01.458Z" }, +] + +[[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" } +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" }, +] + +[[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" } +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" }, +] + +[[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]] +name = "rich" +version = "14.0.0" +source = { registry = "https://pypi.org/simple" } +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" } +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" }, +] + +[[package]] +name = "rich-argparse" +version = "1.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/a6/34460d81e5534f6d2fc8e8d91ff99a5835fdca53578eac89e4f37b3a7c6d/rich_argparse-1.7.1.tar.gz", hash = "sha256:d7a493cde94043e41ea68fb43a74405fa178de981bf7b800f7a3bd02ac5c27be", size = 38094, upload-time = "2025-05-25T20:20:35.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/f6/5fc0574af5379606ffd57a4b68ed88f9b415eb222047fe023aefcc00a648/rich_argparse-1.7.1-py3-none-any.whl", hash = "sha256:a8650b42e4a4ff72127837632fba6b7da40784842f08d7395eb67a9cbd7b4bf9", size = 25357, upload-time = "2025-05-25T20:20:33.793Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.25.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/a6/60184b7fc00dd3ca80ac635dd5b8577d444c57e8e8742cecabfacb829921/rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3", size = 27304, upload-time = "2025-05-21T12:46:12.502Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/da/323848a2b62abe6a0fec16ebe199dc6889c5d0a332458da8985b2980dffe/rpds_py-0.25.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559", size = 364498, upload-time = "2025-05-21T12:43:54.841Z" }, + { url = "https://files.pythonhosted.org/packages/1f/b4/4d3820f731c80fd0cd823b3e95b9963fec681ae45ba35b5281a42382c67d/rpds_py-0.25.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1", size = 350083, upload-time = "2025-05-21T12:43:56.428Z" }, + { url = "https://files.pythonhosted.org/packages/d5/b1/3a8ee1c9d480e8493619a437dec685d005f706b69253286f50f498cbdbcf/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c", size = 389023, upload-time = "2025-05-21T12:43:57.995Z" }, + { url = "https://files.pythonhosted.org/packages/3b/31/17293edcfc934dc62c3bf74a0cb449ecd549531f956b72287203e6880b87/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb", size = 403283, upload-time = "2025-05-21T12:43:59.546Z" }, + { url = "https://files.pythonhosted.org/packages/d1/ca/e0f0bc1a75a8925024f343258c8ecbd8828f8997ea2ac71e02f67b6f5299/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40", size = 524634, upload-time = "2025-05-21T12:44:01.087Z" }, + { url = "https://files.pythonhosted.org/packages/3e/03/5d0be919037178fff33a6672ffc0afa04ea1cfcb61afd4119d1b5280ff0f/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79", size = 416233, upload-time = "2025-05-21T12:44:02.604Z" }, + { url = "https://files.pythonhosted.org/packages/05/7c/8abb70f9017a231c6c961a8941403ed6557664c0913e1bf413cbdc039e75/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325", size = 390375, upload-time = "2025-05-21T12:44:04.162Z" }, + { url = "https://files.pythonhosted.org/packages/7a/ac/a87f339f0e066b9535074a9f403b9313fd3892d4a164d5d5f5875ac9f29f/rpds_py-0.25.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295", size = 424537, upload-time = "2025-05-21T12:44:06.175Z" }, + { url = "https://files.pythonhosted.org/packages/1f/8f/8d5c1567eaf8c8afe98a838dd24de5013ce6e8f53a01bd47fe8bb06b5533/rpds_py-0.25.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b", size = 566425, upload-time = "2025-05-21T12:44:08.242Z" }, + { url = "https://files.pythonhosted.org/packages/95/33/03016a6be5663b389c8ab0bbbcca68d9e96af14faeff0a04affcb587e776/rpds_py-0.25.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98", size = 595197, upload-time = "2025-05-21T12:44:10.449Z" }, + { url = "https://files.pythonhosted.org/packages/33/8d/da9f4d3e208c82fda311bff0cf0a19579afceb77cf456e46c559a1c075ba/rpds_py-0.25.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd", size = 561244, upload-time = "2025-05-21T12:44:12.387Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b3/39d5dcf7c5f742ecd6dbc88f6f84ae54184b92f5f387a4053be2107b17f1/rpds_py-0.25.1-cp313-cp313-win32.whl", hash = "sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31", size = 222254, upload-time = "2025-05-21T12:44:14.261Z" }, + { url = "https://files.pythonhosted.org/packages/5f/19/2d6772c8eeb8302c5f834e6d0dfd83935a884e7c5ce16340c7eaf89ce925/rpds_py-0.25.1-cp313-cp313-win_amd64.whl", hash = "sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500", size = 234741, upload-time = "2025-05-21T12:44:16.236Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5a/145ada26cfaf86018d0eb304fe55eafdd4f0b6b84530246bb4a7c4fb5c4b/rpds_py-0.25.1-cp313-cp313-win_arm64.whl", hash = "sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5", size = 224830, upload-time = "2025-05-21T12:44:17.749Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ca/d435844829c384fd2c22754ff65889c5c556a675d2ed9eb0e148435c6690/rpds_py-0.25.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129", size = 359668, upload-time = "2025-05-21T12:44:19.322Z" }, + { url = "https://files.pythonhosted.org/packages/1f/01/b056f21db3a09f89410d493d2f6614d87bb162499f98b649d1dbd2a81988/rpds_py-0.25.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d", size = 345649, upload-time = "2025-05-21T12:44:20.962Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0f/e0d00dc991e3d40e03ca36383b44995126c36b3eafa0ccbbd19664709c88/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72", size = 384776, upload-time = "2025-05-21T12:44:22.516Z" }, + { url = "https://files.pythonhosted.org/packages/9f/a2/59374837f105f2ca79bde3c3cd1065b2f8c01678900924949f6392eab66d/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34", size = 395131, upload-time = "2025-05-21T12:44:24.147Z" }, + { url = "https://files.pythonhosted.org/packages/9c/dc/48e8d84887627a0fe0bac53f0b4631e90976fd5d35fff8be66b8e4f3916b/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9", size = 520942, upload-time = "2025-05-21T12:44:25.915Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f5/ee056966aeae401913d37befeeab57a4a43a4f00099e0a20297f17b8f00c/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5", size = 411330, upload-time = "2025-05-21T12:44:27.638Z" }, + { url = "https://files.pythonhosted.org/packages/ab/74/b2cffb46a097cefe5d17f94ede7a174184b9d158a0aeb195f39f2c0361e8/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194", size = 387339, upload-time = "2025-05-21T12:44:29.292Z" }, + { url = "https://files.pythonhosted.org/packages/7f/9a/0ff0b375dcb5161c2b7054e7d0b7575f1680127505945f5cabaac890bc07/rpds_py-0.25.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6", size = 418077, upload-time = "2025-05-21T12:44:30.877Z" }, + { url = "https://files.pythonhosted.org/packages/0d/a1/fda629bf20d6b698ae84c7c840cfb0e9e4200f664fc96e1f456f00e4ad6e/rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78", size = 562441, upload-time = "2025-05-21T12:44:32.541Z" }, + { url = "https://files.pythonhosted.org/packages/20/15/ce4b5257f654132f326f4acd87268e1006cc071e2c59794c5bdf4bebbb51/rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72", size = 590750, upload-time = "2025-05-21T12:44:34.557Z" }, + { url = "https://files.pythonhosted.org/packages/fb/ab/e04bf58a8d375aeedb5268edcc835c6a660ebf79d4384d8e0889439448b0/rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66", size = 558891, upload-time = "2025-05-21T12:44:37.358Z" }, + { url = "https://files.pythonhosted.org/packages/90/82/cb8c6028a6ef6cd2b7991e2e4ced01c854b6236ecf51e81b64b569c43d73/rpds_py-0.25.1-cp313-cp313t-win32.whl", hash = "sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523", size = 218718, upload-time = "2025-05-21T12:44:38.969Z" }, + { url = "https://files.pythonhosted.org/packages/b6/97/5a4b59697111c89477d20ba8a44df9ca16b41e737fa569d5ae8bff99e650/rpds_py-0.25.1-cp313-cp313t-win_amd64.whl", hash = "sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763", size = 232218, upload-time = "2025-05-21T12:44:40.512Z" }, +] + +[[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 = "spec" +version = "0.1.0" +source = { editable = "packages/spec" } + +[[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.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, +] + +[[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/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 0603165eb9e..211fcd87716 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -2123,190 +2123,10 @@ "description": "BROTLI Compression" } }, - "linkAKA": { - "BROTLI": "RFC7932", - "CBOR": "RFC8949", - "CBOR Deterministic Encoding": "CBOR-LFD-ENCODING", - "CBOR Encoded IPLD Content Identifier": "CBOR-TAG-42", - "CDDL": "RFC8610", - "COSE": "RFC9052", - "COSE Header Parameters": "RFC9052-HeaderParameters", - "COSE Sign": "RFC9052-CoseSign", - "IPFS CID": "IPFS-CID", - "JSON": "RFC8259", - "RFC9165 - CDDL Additional Controls": "RFC9165", - "URI": "RFC3986", - "UTF-8": "RFC3629", - "UUID": "RFC9562", - "UUIDv4": "RFC9562-V4", - "UUIDv7": "RFC9562-V7" - }, - "metadata": { - "collaborators": { - "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, - "format": "Collaborators Reference List", - "required": "optional", - "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." - }, - "id": { - "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, - "format": "Document Id", - "required": "yes", - "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." - }, - "parameters": { - "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, - "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": [ - "Brand Parameters", - "Campaign Parameters", - "Category Parameters", - "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": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, - "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": [ - "Proposal Meta Template", - "Proposal Template", - "Proposal", - "Proposal Comment Meta Template", - "Proposal Comment Template", - "Proposal Comment", - "Proposal Submission Action", - "Proposal Moderation Action", - "Comment Moderation Action", - "Brand Parameters", - "Campaign Parameters", - "Category Parameters", - "Decision Parameters" - ], - "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." - }, - "reply": { - "description": "Reference to a Comment document type being referred to.", - "exclusive": null, - "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": [ - "Proposal Comment" - ], - "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." - }, - "revocations": { - "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, - "format": "Version Revocations", - "required": "excluded", - "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." - }, - "section": { - "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, - "format": "Section Reference", - "required": "optional", - "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." - }, - "template": { - "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, - "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": [ - "Proposal Meta Template", - "Proposal Template", - "Proposal Comment Meta Template", - "Proposal Comment Template" - ], - "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." - }, - "type": { - "description": "The document TYPE.", - "exclusive": null, - "format": "Document Type", - "required": "yes", - "validation": "**MUST** be a known document type." - }, - "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, - "format": "Document Ver", - "required": "yes", - "validation": "The document version must always be >= the document ID." - } - }, - "metadataFormats": { - "Collaborators Reference List": { - "cddl": "collaborators", - "description": "A list of collaborators who can participate in drafting and submitting a document" - }, - "Document Id": { - "cddl": "document_id", - "description": "A unique document identifier" - }, - "Document Reference": { - "cddl": "document_ref", - "description": "A document reference identifier" - }, - "Document Type": { - "cddl": "document_type", - "description": "A document type identifier" - }, - "Document Ver": { - "cddl": "document_ver", - "description": "A unique chronological document version" - }, - "Section Reference": { - "cddl": "section_ref", - "description": "A document section reference identifier" - }, - "UUIDv4": { - "cddl": "uuid_v4", - "description": "Version 4 formatted UUID" - }, - "UUIDv7": { - "cddl": "uuid_v7", - "description": "Version 7 formatted UUID" - }, - "Version Revocations": { - "cddl": "revocations", - "description": "A list of all versions of this document which are 'revoked'." - } - }, - "metadata_order": [ - "type", - "id", - "ver", - "ref", - "template", - "reply", - "section", - "collaborators", - "revocations", - "parameters" - ], - "templateJsonSchemaDefs": { + "formTemplate": { "dropDownSingleSelect": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "contentMediaType": "text/plain", - "format": "dropDownSingleSelect", "pattern": "^.*$", "type": "string" }, @@ -2337,11 +2157,11 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "multiLineTextEntry": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "contentMediaType": "text/plain", "pattern": "^[\\S\\s]*$", "type": "string" @@ -2378,13 +2198,12 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "multiLineTextEntryListMarkdown": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "items": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "contentMediaType": "text/markdown", "minLength": 1, "pattern": "^[\\S\\s]*$", @@ -2440,11 +2259,11 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "multiLineTextEntryMarkdown": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "contentMediaType": "text/markdown", "pattern": "^[\\S\\s]*$", "type": "string" @@ -2481,14 +2300,12 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "multiSelect": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "items": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", - "contentMediaType": "text/plain", "pattern": "^.*$", "type": "string" }, @@ -2537,13 +2354,12 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "radioButtonSelect": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "contentMediaType": "text/plain", - "format": "radioButtonSelect", "pattern": "^.*$", "type": "string" }, @@ -2574,11 +2390,11 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "schemaReferenceNonUI": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "readOnly": true, "type": "string" }, @@ -2594,11 +2410,11 @@ "required": "yes", "type": "string" } - } + }, + "parent": "section" }, "section": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "additionalProperties": false, "type": "object" }, @@ -2906,7 +2722,6 @@ }, "segment": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "additionalProperties": false, "type": "object" }, @@ -3209,11 +3024,11 @@ "required": "yes", "type": "string" } - } + }, + "parent": "{}" }, "singleGroupedTagSelector": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "additionalProperties": false, "required": [ "group", @@ -3249,11 +3064,11 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "singleLineHttpsURLEntry": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "format": "uri", "pattern": "^https://[^\\s]+$", "type": "string" @@ -3290,13 +3105,12 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "singleLineHttpsURLEntryList": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "items": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "format": "uri", "minLength": 1, "pattern": "^https://[^\\s]+$", @@ -3352,12 +3166,11 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "singleLineTextEntry": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", - "contentMediaType": "text/plain", "pattern": "^.*$", "type": "string" }, @@ -3393,14 +3206,12 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" }, "singleLineTextEntryList": { "definition": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", "items": { - "$comment": "See the Template Schema Definition Dictionary for detailed documentation.", - "contentMediaType": "text/plain", "minLength": 1, "pattern": "^.*$", "type": "string" @@ -3455,7 +3266,186 @@ "required": "optional", "type": "string" } - } + }, + "parent": "section" } - } + }, + "linkAKA": { + "BROTLI": "RFC7932", + "CBOR": "RFC8949", + "CBOR Deterministic Encoding": "CBOR-LFD-ENCODING", + "CBOR Encoded IPLD Content Identifier": "CBOR-TAG-42", + "CDDL": "RFC8610", + "COSE": "RFC9052", + "COSE Header Parameters": "RFC9052-HeaderParameters", + "COSE Sign": "RFC9052-CoseSign", + "IPFS CID": "IPFS-CID", + "JSON": "RFC8259", + "RFC9165 - CDDL Additional Controls": "RFC9165", + "URI": "RFC3986", + "UTF-8": "RFC3629", + "UUID": "RFC9562", + "UUIDv4": "RFC9562-V4", + "UUIDv7": "RFC9562-V7" + }, + "metadata": { + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "exclusive": null, + "format": "Collaborators Reference List", + "required": "optional", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "exclusive": null, + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "exclusive": null, + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "optional", + "type": [ + "Brand Parameters", + "Campaign Parameters", + "Category Parameters", + "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": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "exclusive": null, + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "optional", + "type": [ + "Proposal Meta Template", + "Proposal Template", + "Proposal", + "Proposal Comment Meta Template", + "Proposal Comment Template", + "Proposal Comment", + "Proposal Submission Action", + "Proposal Moderation Action", + "Comment Moderation Action", + "Brand Parameters", + "Campaign Parameters", + "Category Parameters", + "Decision Parameters" + ], + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "exclusive": null, + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "optional", + "type": [ + "Proposal Comment" + ], + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "exclusive": null, + "format": "Version Revocations", + "required": "excluded", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "exclusive": null, + "format": "Section Reference", + "required": "optional", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "exclusive": null, + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "optional", + "type": [ + "Proposal Meta Template", + "Proposal Template", + "Proposal Comment Meta Template", + "Proposal Comment Template" + ], + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "exclusive": null, + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "exclusive": null, + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "metadataFormats": { + "Collaborators Reference List": { + "cddl": "collaborators", + "description": "A list of collaborators who can participate in drafting and submitting a document" + }, + "Document Id": { + "cddl": "document_id", + "description": "A unique document identifier" + }, + "Document Reference": { + "cddl": "document_ref", + "description": "A document reference identifier" + }, + "Document Type": { + "cddl": "document_type", + "description": "A document type identifier" + }, + "Document Ver": { + "cddl": "document_ver", + "description": "A unique chronological document version" + }, + "Section Reference": { + "cddl": "section_ref", + "description": "A document section reference identifier" + }, + "UUIDv4": { + "cddl": "uuid_v4", + "description": "Version 4 formatted UUID" + }, + "UUIDv7": { + "cddl": "uuid_v7", + "description": "Version 7 formatted UUID" + }, + "Version Revocations": { + "cddl": "revocations", + "description": "A list of all versions of this document which are 'revoked'." + } + }, + "metadata_order": [ + "type", + "id", + "ver", + "ref", + "template", + "reply", + "section", + "collaborators", + "revocations", + "parameters" + ] } From 9c99d7147c46d67c6680b34483422ab058993079 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 14 Jun 2025 23:11:39 +0700 Subject: [PATCH 14/42] fix(docs): remove lin to root ruff.toml which was impacting import sorting --- specs/generators/ruff.toml | 1 - 1 file changed, 1 deletion(-) delete mode 120000 specs/generators/ruff.toml diff --git a/specs/generators/ruff.toml b/specs/generators/ruff.toml deleted file mode 120000 index e768b4aa2c2..00000000000 --- a/specs/generators/ruff.toml +++ /dev/null @@ -1 +0,0 @@ -../../ruff.toml \ No newline at end of file From 33903687a4233bfb48336f8fe93696ae4e0ea924 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 14 Jun 2025 23:13:47 +0700 Subject: [PATCH 15/42] refactor(docs): Reorganize the doc generator into the new module structure --- .../08_concepts/signed_doc/.pages | 1 + .../schema/template_example.schema.json | 254 ++++++++++++ .../08_concepts/signed_doc/templates.md | 1 + specs/Justfile | 3 +- specs/gen_docs/.python-version | 1 - specs/gen_docs/README.md | 3 - specs/gen_docs/__init__.py | 2 - specs/gen_docs/pyproject.toml | 30 -- specs/gen_docs/uv.lock | 389 ------------------ specs/generators/pyproject.toml | 6 +- .../gen => generators/src/docs}/__init__.py | 2 +- .../gen => generators/src/docs}/cddl_file.py | 3 +- .../src/docs}/doc_generator.py | 0 .../src/docs}/doc_relationship_diagrams.py | 5 +- .../src/docs}/docs_page_md.py | 5 +- .../src/docs}/graphviz_doc_diagram.py | 0 .../{gen_docs => generators/src/docs}/main.py | 19 +- .../src/docs}/metadata_md.py | 5 +- .../gen => generators/src/docs}/spec_index.py | 4 +- .../gen => generators/src/docs}/spec_md.py | 5 +- .../src/docs/template_example_schema_json.py | 48 +++ specs/generators/src/docs/templates_md.py | 25 ++ .../gen => generators/src/docs}/types_md.py | 7 +- specs/generators/src/validator/main.py | 1 + 24 files changed, 369 insertions(+), 450 deletions(-) create mode 100644 docs/src/architecture/08_concepts/signed_doc/schema/template_example.schema.json create mode 100644 docs/src/architecture/08_concepts/signed_doc/templates.md delete mode 100644 specs/gen_docs/.python-version delete mode 100644 specs/gen_docs/README.md delete mode 100644 specs/gen_docs/__init__.py delete mode 100644 specs/gen_docs/pyproject.toml delete mode 100644 specs/gen_docs/uv.lock rename specs/{gen_docs/gen => generators/src/docs}/__init__.py (100%) rename specs/{gen_docs/gen => generators/src/docs}/cddl_file.py (98%) rename specs/{gen_docs/gen => generators/src/docs}/doc_generator.py (100%) rename specs/{gen_docs/gen => generators/src/docs}/doc_relationship_diagrams.py (97%) rename specs/{gen_docs/gen => generators/src/docs}/docs_page_md.py (97%) rename specs/{gen_docs/gen => generators/src/docs}/graphviz_doc_diagram.py (100%) rename specs/{gen_docs => generators/src/docs}/main.py (88%) rename specs/{gen_docs/gen => generators/src/docs}/metadata_md.py (96%) rename specs/{gen_docs/gen => generators/src/docs}/spec_index.py (88%) rename specs/{gen_docs/gen => generators/src/docs}/spec_md.py (98%) create mode 100644 specs/generators/src/docs/template_example_schema_json.py create mode 100644 specs/generators/src/docs/templates_md.py rename specs/{gen_docs/gen => generators/src/docs}/types_md.py (94%) diff --git a/docs/src/architecture/08_concepts/signed_doc/.pages b/docs/src/architecture/08_concepts/signed_doc/.pages index 176b5b0eb89..4e2718e919b 100644 --- a/docs/src/architecture/08_concepts/signed_doc/.pages +++ b/docs/src/architecture/08_concepts/signed_doc/.pages @@ -3,4 +3,5 @@ nav: - Specification: spec.md - Metadata Fields: metadata.md - Document Types: types.md + - Document Templates: templates.md - docs diff --git a/docs/src/architecture/08_concepts/signed_doc/schema/template_example.schema.json b/docs/src/architecture/08_concepts/signed_doc/schema/template_example.schema.json new file mode 100644 index 00000000000..68c3e6cd678 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/schema/template_example.schema.json @@ -0,0 +1,254 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema#", + "title": "Example Template Schema", + "description": "Example Template Schema showing all defined field types.", + "maintainers": [ + { + "name": "Catalyst Team", + "url": "https://projectcatalyst.io/" + } + ], + "$defs": { + "dropDownSingleSelect": { + "contentMediaType": "text/plain", + "pattern": "^.*$", + "type": "string" + }, + "multiLineTextEntry": { + "contentMediaType": "text/plain", + "pattern": "^[\\S\\s]*$", + "type": "string" + }, + "multiLineTextEntryListMarkdown": { + "items": { + "contentMediaType": "text/markdown", + "minLength": 1, + "pattern": "^[\\S\\s]*$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "multiLineTextEntryMarkdown": { + "contentMediaType": "text/markdown", + "pattern": "^[\\S\\s]*$", + "type": "string" + }, + "multiSelect": { + "items": { + "pattern": "^.*$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "radioButtonSelect": { + "contentMediaType": "text/plain", + "pattern": "^.*$", + "type": "string" + }, + "schemaReferenceNonUI": { + "readOnly": true, + "type": "string" + }, + "section": { + "additionalProperties": false, + "type": "object" + }, + "segment": { + "additionalProperties": false, + "type": "object" + }, + "singleGroupedTagSelector": { + "additionalProperties": false, + "required": [ + "group", + "tag" + ], + "type": "object" + }, + "singleLineHttpsURLEntry": { + "format": "uri", + "pattern": "^https://[^\\s]+$", + "type": "string" + }, + "singleLineHttpsURLEntryList": { + "items": { + "format": "uri", + "minLength": 1, + "pattern": "^https://[^\\s]+$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "singleLineTextEntry": { + "pattern": "^.*$", + "type": "string" + }, + "singleLineTextEntryList": { + "items": { + "minLength": 1, + "pattern": "^.*$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + } + }, + "type": "object", + "additionalProperties": false, + "properties": { + "dropDownSingleSelect": { + "exampleDropDownSingleSelect": { + "description": null, + "enum": null, + "title": null, + "x-guidance": null + }, + "$ref": "#/$defs/dropDownSingleSelect" + }, + "multiLineTextEntry": { + "exampleMultiLineTextEntry": { + "description": null, + "maxLength": null, + "minLength": null, + "title": null, + "x-guidance": null, + "x-placeholder": null + }, + "$ref": "#/$defs/multiLineTextEntry" + }, + "multiLineTextEntryListMarkdown": { + "exampleMultiLineTextEntryListMarkdown": { + "contains": null, + "default": null, + "description": null, + "maxItems": null, + "minItems": null, + "title": null, + "x-guidance": null, + "x-placeholder": null + }, + "$ref": "#/$defs/multiLineTextEntryListMarkdown" + }, + "multiLineTextEntryMarkdown": { + "exampleMultiLineTextEntryMarkdown": { + "description": null, + "maxLength": null, + "minLength": null, + "title": null, + "x-guidance": null, + "x-placeholder": null + }, + "$ref": "#/$defs/multiLineTextEntryMarkdown" + }, + "multiSelect": { + "exampleMultiSelect": { + "contains": null, + "default": null, + "description": null, + "maxItems": null, + "minItems": null, + "title": null, + "x-guidance": null + }, + "$ref": "#/$defs/multiSelect" + }, + "radioButtonSelect": { + "exampleRadioButtonSelect": { + "description": null, + "enum": null, + "title": null, + "x-guidance": null + }, + "$ref": "#/$defs/radioButtonSelect" + }, + "schemaReferenceNonUI": { + "exampleSchemaReferenceNonUI": { + "const": null, + "default": null + }, + "$ref": "#/$defs/schemaReferenceNonUI" + }, + "section": { + "exampleSection": { + "description": null, + "properties": null, + "required": null, + "title": null, + "x-icon": null, + "x-order": null + }, + "$ref": "#/$defs/section" + }, + "segment": { + "exampleSegment": { + "description": null, + "properties": null, + "required": null, + "title": null, + "x-icon": null, + "x-order": null + }, + "$ref": "#/$defs/segment" + }, + "singleGroupedTagSelector": { + "exampleSingleGroupedTagSelector": { + "description": null, + "oneOf_groupedTags": null, + "title": null, + "x-guidance": null + }, + "$ref": "#/$defs/singleGroupedTagSelector" + }, + "singleLineHttpsURLEntry": { + "exampleSingleLineHttpsURLEntry": { + "description": null, + "maxLength": null, + "minLength": null, + "title": null, + "x-guidance": null, + "x-placeholder": null + }, + "$ref": "#/$defs/singleLineHttpsURLEntry" + }, + "singleLineHttpsURLEntryList": { + "exampleSingleLineHttpsURLEntryList": { + "contains": null, + "default": null, + "description": null, + "maxItems": null, + "minItems": null, + "title": null, + "x-guidance": null, + "x-placeholder": null + }, + "$ref": "#/$defs/singleLineHttpsURLEntryList" + }, + "singleLineTextEntry": { + "exampleSingleLineTextEntry": { + "description": null, + "maxLength": null, + "minLength": null, + "title": null, + "x-guidance": null, + "x-placeholder": null + }, + "$ref": "#/$defs/singleLineTextEntry" + }, + "singleLineTextEntryList": { + "exampleSingleLineTextEntryList": { + "contains": null, + "default": null, + "description": null, + "maxItems": null, + "minItems": null, + "title": null, + "x-guidance": null, + "x-placeholder": null + }, + "$ref": "#/$defs/singleLineTextEntryList" + } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/templates.md b/docs/src/architecture/08_concepts/signed_doc/templates.md new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/templates.md @@ -0,0 +1 @@ + diff --git a/specs/Justfile b/specs/Justfile index 89ef29a9699..4562884abe9 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -30,7 +30,7 @@ regenerate-signed-doc-json: # Fix and Check Markdown files regenerate: check regenerate-signed-doc-json validate && validate-docs # Generate the markdown docs from the specification. - #cd gen_docs; ./main.py -g -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json + cd generators; uv run docs -g -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json # Validate the generated signed_docs.json is correct against the cue schema. validate: @@ -42,6 +42,7 @@ validate: # Validate the generated docs is correct against the signed_docs.json. validate-docs: # Check our validation code actually works properly + cd generators; uv run docs -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json #cd gen_docs; ./main.py -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json # Pre Push Checks - intended to be run by a git pre-push hook. diff --git a/specs/gen_docs/.python-version b/specs/gen_docs/.python-version deleted file mode 100644 index 24ee5b1be99..00000000000 --- a/specs/gen_docs/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.13 diff --git a/specs/gen_docs/README.md b/specs/gen_docs/README.md deleted file mode 100644 index fa54af18073..00000000000 --- a/specs/gen_docs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Signed Documents documentation generator - -Builds Markdown and other documentation files from the signed documents specifications. diff --git a/specs/gen_docs/__init__.py b/specs/gen_docs/__init__.py deleted file mode 100644 index 332939cbf4e..00000000000 --- a/specs/gen_docs/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Intentionally Empty -"""Doc Generation Program.""" diff --git a/specs/gen_docs/pyproject.toml b/specs/gen_docs/pyproject.toml deleted file mode 100644 index 5ac71cbe38c..00000000000 --- a/specs/gen_docs/pyproject.toml +++ /dev/null @@ -1,30 +0,0 @@ -[project] -name = "gen-docs" -version = "0.1.0" -description = "Generate Signed Document documentation files." -readme = "README.md" -requires-python = ">=3.13" -dependencies = [ - "jsonschema[format]>=4.23.0", - "pydantic>=2.11.4", - "pydot>=3.0.4", - "rich>=14.0.0", - "rich-argparse>=1.7.0", -] - -[tool.ruff] -# Extend the project wide `ruff.toml` file. -# Done so we can add known libraries to sorting. -extend = "../../ruff.toml" - -[tool.ruff.lint.isort] -known-third-party = [ - "pydantic", - "pydot", - "rich", - "rich-argparse" -] - -known-first-party = [ - "spec", -] diff --git a/specs/gen_docs/uv.lock b/specs/gen_docs/uv.lock deleted file mode 100644 index 06aaec055aa..00000000000 --- a/specs/gen_docs/uv.lock +++ /dev/null @@ -1,389 +0,0 @@ -version = 1 -revision = 2 -requires-python = ">=3.13" - -[[package]] -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" } -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" }, -] - -[[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]] -name = "gen-docs" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "jsonschema", extra = ["format"] }, - { name = "pydantic" }, - { name = "pydot" }, - { name = "rich" }, - { name = "rich-argparse" }, -] - -[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" -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" } -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" }, -] - -[[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" } -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" }, -] - -[[package]] -name = "pydantic" -version = "2.11.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "annotated-types" }, - { name = "pydantic-core" }, - { 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" } -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" }, -] - -[[package]] -name = "pydantic-core" -version = "2.33.2" -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" } -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" }, -] - -[[package]] -name = "pydot" -version = "3.0.4" -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" } -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" }, -] - -[[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" } -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" }, -] - -[[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" } -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" }, -] - -[[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]] -name = "rich" -version = "14.0.0" -source = { registry = "https://pypi.org/simple" } -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" } -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" }, -] - -[[package]] -name = "rich-argparse" -version = "1.7.0" -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" } -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" }, -] - -[[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" } -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" }, -] - -[[package]] -name = "typing-inspection" -version = "0.4.0" -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" } -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/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/generators/pyproject.toml b/specs/generators/pyproject.toml index f3cc2c7bdf8..0367d176bf8 100644 --- a/specs/generators/pyproject.toml +++ b/specs/generators/pyproject.toml @@ -13,6 +13,7 @@ dependencies = [ [project.scripts] validator = "validator.main:main" +docs = "docs.main:main" [tool.uv.workspace] members = [ @@ -25,11 +26,10 @@ spec = { workspace = true } [tool.ruff] # Extend the project wide `ruff.toml` file. # Done so we can add known libraries to sorting. -extend = "ruff.toml" +extend = "../../ruff.toml" [tool.ruff.lint.isort] -known-third-party = ["pydantic", "pydot", "rich", "rich-argparse"] - +#known-third-party = ["pydantic", "pydot", "rich", "rich-argparse"] known-first-party = ["spec"] [build-system] diff --git a/specs/gen_docs/gen/__init__.py b/specs/generators/src/docs/__init__.py similarity index 100% rename from specs/gen_docs/gen/__init__.py rename to specs/generators/src/docs/__init__.py index c41bcac355d..276224dced9 100644 --- a/specs/gen_docs/gen/__init__.py +++ b/specs/generators/src/docs/__init__.py @@ -1,2 +1,2 @@ -# Intentionally Empty """Doc Generator Module.""" +# Intentionally Empty diff --git a/specs/gen_docs/gen/cddl_file.py b/specs/generators/src/docs/cddl_file.py similarity index 98% rename from specs/gen_docs/gen/cddl_file.py rename to specs/generators/src/docs/cddl_file.py index c5a46af8b98..afd02dc7b2e 100644 --- a/specs/gen_docs/gen/cddl_file.py +++ b/specs/generators/src/docs/cddl_file.py @@ -4,9 +4,10 @@ import re import textwrap -from gen.doc_generator import DocGenerator from spec.signed_doc import SignedDoc +from .doc_generator import DocGenerator + def add_cddl_comments(comment: str) -> tuple[str, bool]: """Add cddl comment markers to lines. diff --git a/specs/gen_docs/gen/doc_generator.py b/specs/generators/src/docs/doc_generator.py similarity index 100% rename from specs/gen_docs/gen/doc_generator.py rename to specs/generators/src/docs/doc_generator.py diff --git a/specs/gen_docs/gen/doc_relationship_diagrams.py b/specs/generators/src/docs/doc_relationship_diagrams.py similarity index 97% rename from specs/gen_docs/gen/doc_relationship_diagrams.py rename to specs/generators/src/docs/doc_relationship_diagrams.py index 7f3c74fc3ed..bef78bcbe78 100644 --- a/specs/gen_docs/gen/doc_relationship_diagrams.py +++ b/specs/generators/src/docs/doc_relationship_diagrams.py @@ -3,12 +3,13 @@ import argparse import textwrap -from gen.doc_generator import DocGenerator -from gen.graphviz_doc_diagram import Cluster, DotFile, DotLink, DotLinkEnd, DotSignedDoc, FontTheme, TableRow from spec.metadata import Metadata from spec.optional import OptionalField from spec.signed_doc import HeaderType, SignedDoc +from .doc_generator import DocGenerator +from .graphviz_doc_diagram import Cluster, DotFile, DotLink, DotLinkEnd, DotSignedDoc, FontTheme, TableRow + class DocRelationshipFile(DocGenerator): """Generate a Document Relationship Diagram File.""" diff --git a/specs/gen_docs/gen/docs_page_md.py b/specs/generators/src/docs/docs_page_md.py similarity index 97% rename from specs/gen_docs/gen/docs_page_md.py rename to specs/generators/src/docs/docs_page_md.py index b07c17f4401..2d53714428b 100644 --- a/specs/gen_docs/gen/docs_page_md.py +++ b/specs/generators/src/docs/docs_page_md.py @@ -3,10 +3,11 @@ import argparse import typing -from gen.doc_generator import DocGenerator -from gen.doc_relationship_diagrams import DocRelationshipFile from spec.signed_doc import SignedDoc +from .doc_generator import DocGenerator +from .doc_relationship_diagrams import DocRelationshipFile + class IndividualDocMd(DocGenerator): """Generate the individual pages docs/.md file.""" diff --git a/specs/gen_docs/gen/graphviz_doc_diagram.py b/specs/generators/src/docs/graphviz_doc_diagram.py similarity index 100% rename from specs/gen_docs/gen/graphviz_doc_diagram.py rename to specs/generators/src/docs/graphviz_doc_diagram.py diff --git a/specs/gen_docs/main.py b/specs/generators/src/docs/main.py similarity index 88% rename from specs/gen_docs/main.py rename to specs/generators/src/docs/main.py index 521f49338fa..d71b3baa896 100755 --- a/specs/gen_docs/main.py +++ b/specs/generators/src/docs/main.py @@ -8,13 +8,15 @@ import rich from rich_argparse import RichHelpFormatter -from gen.docs_page_md import IndividualDocMd -from gen.metadata_md import MetadataMd -from gen.spec_index import SpecIndex -from gen.spec_md import SpecMd -from gen.types_md import TypesMd from spec.signed_doc import SignedDoc +from .docs_page_md import IndividualDocMd +from .metadata_md import MetadataMd +from .spec_index import SpecIndex +from .spec_md import SpecMd +from .templates_md import TemplatesMd +from .types_md import TypesMd + def check_is_dir(base_path: Path) -> bool: """Check if the path exists, and is a directory. @@ -62,8 +64,10 @@ def parse_args() -> argparse.Namespace: return args -def main(args: argparse.Namespace) -> None: +def main() -> None: """Generate Signed Document Specification documentation.""" + args = parse_args() + # Get the compiled documentation json file spec = SignedDoc.load(args.spec) @@ -76,6 +80,7 @@ def main(args: argparse.Namespace) -> None: good &= TypesMd(args, spec).save_or_validate() good &= MetadataMd(args, spec).save_or_validate() good &= IndividualDocMd.save_or_validate_all(args, spec) + good &= TemplatesMd(args, spec).save_or_validate() if not good: rich.print("File Comparisons Failed, Documentation is not current.") @@ -88,4 +93,4 @@ def main(args: argparse.Namespace) -> None: if __name__ == "__main__": - main(parse_args()) + main() diff --git a/specs/gen_docs/gen/metadata_md.py b/specs/generators/src/docs/metadata_md.py similarity index 96% rename from specs/gen_docs/gen/metadata_md.py rename to specs/generators/src/docs/metadata_md.py index 38bce8a4480..b8662543d4c 100644 --- a/specs/gen_docs/gen/metadata_md.py +++ b/specs/generators/src/docs/metadata_md.py @@ -5,10 +5,11 @@ import rich from rich.console import Console -from gen.cddl_file import CDDLFile -from gen.doc_generator import DocGenerator from spec.signed_doc import SignedDoc +from .cddl_file import CDDLFile +from .doc_generator import DocGenerator + console = Console() diff --git a/specs/gen_docs/gen/spec_index.py b/specs/generators/src/docs/spec_index.py similarity index 88% rename from specs/gen_docs/gen/spec_index.py rename to specs/generators/src/docs/spec_index.py index 56da19a4116..b7c9e893e73 100644 --- a/specs/gen_docs/gen/spec_index.py +++ b/specs/generators/src/docs/spec_index.py @@ -2,9 +2,10 @@ import argparse -from gen.doc_generator import DocGenerator from spec.signed_doc import SignedDoc +from .doc_generator import DocGenerator + class SpecIndex(DocGenerator): """Spec Index Generator.""" @@ -21,6 +22,7 @@ def generate(self) -> bool: - Specification: spec.md - Metadata Fields: metadata.md - Document Types: types.md + - Document Templates: templates.md - docs """ return super().generate() diff --git a/specs/gen_docs/gen/spec_md.py b/specs/generators/src/docs/spec_md.py similarity index 98% rename from specs/gen_docs/gen/spec_md.py rename to specs/generators/src/docs/spec_md.py index f70b4345ac6..ee53e51de4d 100644 --- a/specs/gen_docs/gen/spec_md.py +++ b/specs/generators/src/docs/spec_md.py @@ -2,10 +2,11 @@ import argparse -from gen.cddl_file import CDDLFile -from gen.doc_generator import DocGenerator from spec.signed_doc import HeaderType, SignedDoc +from .cddl_file import CDDLFile +from .doc_generator import DocGenerator + class SpecMd(DocGenerator): """Generate the spec.md file.""" diff --git a/specs/generators/src/docs/template_example_schema_json.py b/specs/generators/src/docs/template_example_schema_json.py new file mode 100644 index 00000000000..5181bf7fa94 --- /dev/null +++ b/specs/generators/src/docs/template_example_schema_json.py @@ -0,0 +1,48 @@ +"""Generate the template_example.schema.json file.""" + +import argparse +import json +from typing import Any + +import jsonschema + +from spec.signed_doc import SignedDoc + +from .doc_generator import DocGenerator + + +class TemplateExampleSchemaJson(DocGenerator): + """Generate the template_example.schema.json file.""" + + def __init__(self, args: argparse.Namespace, spec: SignedDoc) -> None: + """Initialise template_example.schema.json generator.""" + file_name = "schema/template_example.schema.json" + + super().__init__(args, spec, file_name) + + def generate(self) -> bool: + """Generate a `template_example.schema.json` file from the definitions.""" + schema: dict[str, Any] = { + "$schema": "https://json-schema.org/draft/2020-12/schema#", + "title": "Example Template Schema", + "description": "Example Template Schema showing all defined field types.", + "maintainers": [{"name": "Catalyst Team", "url": "https://projectcatalyst.io/"}], + "$defs": self._spec.form_template.json_definition, + "type": "object", + "additionalProperties": False, + "properties": self._spec.form_template.example, + } + + # "definitions": {{ + # {self._spec.template_json_schema_defs.json_definition} + # }}, + # }} + # """ + template_schema = json.dumps(schema, indent=4) + jsonschema.Draft202012Validator.check_schema(schema) + # validator = jsonschema.Draft7Validator(schema, format_checker=jsonschema.draft7_format_checker) # noqa: ERA001 + # validator.validate(schema) # noqa: ERA001 + + self._filedata = template_schema + + return super().generate() diff --git a/specs/generators/src/docs/templates_md.py b/specs/generators/src/docs/templates_md.py new file mode 100644 index 00000000000..905647cdfca --- /dev/null +++ b/specs/generators/src/docs/templates_md.py @@ -0,0 +1,25 @@ +"""Generate the templates.md file.""" + +import argparse + +from spec.signed_doc import SignedDoc + +from .doc_generator import DocGenerator +from .template_example_schema_json import TemplateExampleSchemaJson + + +class TemplatesMd(DocGenerator): + """Generate the templates.md file.""" + + def __init__(self, args: argparse.Namespace, spec: SignedDoc) -> None: + """Initialise Spec.md generator.""" + super().__init__(args, spec, "templates.md") + + def generate(self) -> bool: + """Generate a `templates.md` file from the definitions.""" + # Generate the example_template_schema.json file. + example_schema = TemplateExampleSchemaJson(self._args, self._spec) + if not example_schema.save_or_validate(): + return False + + return super().generate() diff --git a/specs/gen_docs/gen/types_md.py b/specs/generators/src/docs/types_md.py similarity index 94% rename from specs/gen_docs/gen/types_md.py rename to specs/generators/src/docs/types_md.py index 7c7f7da4bf5..69520a94044 100644 --- a/specs/gen_docs/gen/types_md.py +++ b/specs/generators/src/docs/types_md.py @@ -2,10 +2,11 @@ import argparse -from gen.doc_generator import DocGenerator -from gen.doc_relationship_diagrams import DocRelationshipFile from spec.signed_doc import SignedDoc +from .doc_generator import DocGenerator +from .doc_relationship_diagrams import DocRelationshipFile + class TypesMd(DocGenerator): """Generate the `types.md` File.""" @@ -30,7 +31,7 @@ def formatted_cbor_doc_types(self, name: str) -> str: type_names += self.uuid_as_cbor(sub_type) + ",
" return type_names[:-6] + "]" - def doc_type_summary(self) -> None: + def doc_type_summary(self) -> str: """Generate a Document Base Type Summary from the Document Specifications Data.""" doc_types = self._spec.base_document_types() diff --git a/specs/generators/src/validator/main.py b/specs/generators/src/validator/main.py index 685f6375c55..51ef671b6c0 100644 --- a/specs/generators/src/validator/main.py +++ b/specs/generators/src/validator/main.py @@ -7,6 +7,7 @@ from pydantic import ValidationError from rich.table import Table from rich_argparse import RichHelpFormatter + from spec.signed_doc import SignedDoc From 9f2d3e7fe8b3987e3d20e635014d2ab6c44f055b Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 16 Jun 2025 20:03:19 +0700 Subject: [PATCH 16/42] refactor(docs): Cleanup document specification data structure and methods --- .gitignore | 3 +- specs/Justfile | 1 - .../definitions/signed_docs/cose_headers.cue | 14 +- .../signed_docs/cose_signed_doc_cddl_defs.cue | 2 +- specs/definitions/signed_docs/metadata.cue | 15 +- .../packages/spec/src/spec/authors.py | 22 + .../packages/spec/src/spec/base_types.py | 58 ++ .../packages/spec/src/spec/cddl/cose.py | 127 +++++ .../packages/spec/src/spec/cddl/definition.py | 117 ++++ .../spec/src/spec/cddl_definitions.py | 14 - .../packages/spec/src/spec/content_types.py | 26 +- .../packages/spec/src/spec/cose_header.py | 17 - .../packages/spec/src/spec/doc_clusters.py | 40 +- .../packages/spec/src/spec/doc_types.py | 39 ++ .../packages/spec/src/spec/document.py | 72 ++- .../spec/src/spec/documentation_links.py | 41 ++ .../packages/spec/src/spec/metadata.py | 184 +++--- .../spec/src/spec/metadata_formats.py | 19 +- .../packages/spec/src/spec/signed_doc.py | 319 ++--------- specs/generators/src/docs/cddl_file.py | 26 +- specs/generators/src/docs/doc_generator.py | 34 +- .../src/docs/doc_relationship_diagrams.py | 25 +- specs/generators/src/docs/docs_page_md.py | 8 +- specs/generators/src/docs/markdown.py | 46 ++ specs/generators/src/docs/metadata_md.py | 26 +- specs/generators/src/docs/spec_md.py | 45 +- specs/generators/src/docs/types_md.py | 32 +- specs/signed_doc.json | 528 +++++++----------- 28 files changed, 1026 insertions(+), 874 deletions(-) create mode 100644 specs/generators/packages/spec/src/spec/authors.py create mode 100644 specs/generators/packages/spec/src/spec/base_types.py create mode 100644 specs/generators/packages/spec/src/spec/cddl/cose.py create mode 100644 specs/generators/packages/spec/src/spec/cddl/definition.py delete mode 100644 specs/generators/packages/spec/src/spec/cddl_definitions.py delete mode 100644 specs/generators/packages/spec/src/spec/cose_header.py create mode 100644 specs/generators/packages/spec/src/spec/doc_types.py create mode 100644 specs/generators/packages/spec/src/spec/documentation_links.py create mode 100644 specs/generators/src/docs/markdown.py diff --git a/.gitignore b/.gitignore index 10d3ca25f74..16f34110365 100644 --- a/.gitignore +++ b/.gitignore @@ -92,4 +92,5 @@ py.typed *.egg-info .venv .ruff_cache -dist \ No newline at end of file +dist +*.pyi \ No newline at end of file diff --git a/specs/Justfile b/specs/Justfile index 4562884abe9..d524c2c20cd 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -43,7 +43,6 @@ validate: validate-docs: # Check our validation code actually works properly cd generators; uv run docs -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json - #cd gen_docs; ./main.py -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json # Pre Push Checks - intended to be run by a git pre-push hook. pre-push: format-python-code lint-python regenerate validate diff --git a/specs/definitions/signed_docs/cose_headers.cue b/specs/definitions/signed_docs/cose_headers.cue index 9631edebb97..1fb8c1bd443 100644 --- a/specs/definitions/signed_docs/cose_headers.cue +++ b/specs/definitions/signed_docs/cose_headers.cue @@ -121,7 +121,7 @@ _allCoseHeaderNames: or([ for k in _coseHeaderNames {k}, ]) -coseHeaderFormats: #metadataFormats & { +cose: headerFormats: #metadataFormats & { "Media Type": { description: "A Media Type string which identifies the payload." cddl: "media_type" @@ -138,7 +138,7 @@ coseHeaderFormats: #metadataFormats & { // Types of a Metadata Fields #coseHeaderTypes: [ - for k, _ in coseHeaderFormats {k}, + for k, _ in cose.headerFormats {k}, ] // Constraint of Types of Cose Header Fields @@ -197,16 +197,16 @@ _coseSignatureHeaders: #coseHeaders & { } } -cose_headers: _coseHeaders -cose_headers: "content type": value: #allContentTypes +cose: headers: _coseHeaders +cose: headers: "content type": value: #allContentTypes // Preferred display order of cose header fields. // if header not listed, display after the listed fields, in alphabetical order. -cose_headers_order: list.UniqueItems -cose_headers_order: [ +cose: headersOrder: list.UniqueItems +cose: headersOrder: [ "content type", "content-encoding", ] // Headers defined for signatures. -cose_signature_headers: _coseSignatureHeaders +cose: signature_headers: _coseSignatureHeaders diff --git a/specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue b/specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue index c68d4ccf04a..67e7ee751f1 100644 --- a/specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue +++ b/specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue @@ -8,7 +8,7 @@ import ( ) // Formatted content strings to use in CDDL Definition. -_cddlContentTypes: "\"\(strings.Join(cose_headers."content type".value, "\" /\n \""))\"" +_cddlContentTypes: "\"\(strings.Join(cose.headers."content type".value, "\" /\n \""))\"" // Formatted CoAP content string to use in CDDL Definition. _cddlCoapTypes: "\(strings.Join(_allCoapTypesStr, " / "))" diff --git a/specs/definitions/signed_docs/metadata.cue b/specs/definitions/signed_docs/metadata.cue index 58a347cc13f..96ad8fe91cd 100644 --- a/specs/definitions/signed_docs/metadata.cue +++ b/specs/definitions/signed_docs/metadata.cue @@ -17,7 +17,7 @@ import ( } } -metadataFormats: #metadataFormats & { +metadata: formats: #metadataFormats & { "Document Reference": { description: "A document reference identifier" cddl: "document_ref" @@ -58,7 +58,7 @@ metadataFormats: #metadataFormats & { // Types of a Metadata Fields #metadataTypes: [ - for k, _ in metadataFormats {k}, + for k, _ in metadata.formats {k}, ] // Constraint of Types of Metadata Fields @@ -100,9 +100,6 @@ _allMetadataNames: or([ description: string | *"" // Optional notes about validating the field. validation: string | *null - - // Is the field exclusive of another field (ie can not exist with that other field in the same document) - exclusive: [..._allMetadataNames] | *null } // Metadata fields that are optional @@ -266,8 +263,8 @@ _metadata: #metadataStruct & { } // Note: we make all normally excluded fields optional at the global level, because they are globally optional -metadata: _metadata -metadata: { +metadata: headers: _metadata +metadata: headers: { ref: required: "optional" ref: type: _allDocNamesList template: required: "optional" @@ -282,8 +279,8 @@ metadata: { // Preferred display order // If metadata field not listed, then list them after the explicit ones, in alphabetical order. -metadata_order: list.UniqueItems -metadata_order: [..._allMetadataNames] & [ +metadata: order: list.UniqueItems +metadata: order: [..._allMetadataNames] & [ "type", "id", "ver", diff --git a/specs/generators/packages/spec/src/spec/authors.py b/specs/generators/packages/spec/src/spec/authors.py new file mode 100644 index 00000000000..09c1443a250 --- /dev/null +++ b/specs/generators/packages/spec/src/spec/authors.py @@ -0,0 +1,22 @@ +"""Change Log Entry Specification.""" + +from pydantic import RootModel + + +class Authors(RootModel[dict[str, str]]): + """Authors of the Specifications.""" + + root: dict[str, str] # name: email + + def combine(self, other: "Authors") -> "Authors": + """Combine Two Authors lists into a single Authors List.""" + combined = self.root | other.root + return self.model_validate(combined) + + def email(self, name: str) -> str: + """Get Email for authors name.""" + return self.root.get(name, "Unknown") + + def all(self) -> list[str]: + """Get All Authors.""" + return sorted(self.root.keys()) diff --git a/specs/generators/packages/spec/src/spec/base_types.py b/specs/generators/packages/spec/src/spec/base_types.py new file mode 100644 index 00000000000..3990fbdb690 --- /dev/null +++ b/specs/generators/packages/spec/src/spec/base_types.py @@ -0,0 +1,58 @@ +"""Base Document Type Identifiers.""" + +import typing + +from pydantic import RootModel, computed_field +from pydantic.types import UUID4 + + +class DocTypeId(RootModel[UUID4]): + """Document Type ID is a UUIDv4.""" + + root: UUID4 # name: uuid_str + + class Config: + frozen = True + + @computed_field + @property + def as_cbor(self) -> str: + """DocType in CBOR Diagnostic Notation.""" + return f"37(h'{self.root.hex}')" + + @computed_field + @property + def as_uuid_str(self) -> str: + """DocType in CBOR Diagnostic Notation.""" + return str(self.root) + + +class BaseTypes(RootModel[dict[str, DocTypeId]]): + """Authors of the Specifications.""" + + root: dict[str, DocTypeId] # name: uuid_str + + _for_uuid: dict[DocTypeId, str] # reverse lookup + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + # Set all the documents this references. + self._for_uuid = {} + for k, v in self.root.items(): + self._for_uuid[v] = k + + def uuid(self, name: str) -> DocTypeId: + """Get UUID for Base Type Name.""" + return self.root[name] + + def name(self, uuid: DocTypeId) -> str: + """Get Base Type Name for the given UUID.""" + return self._for_uuid[uuid] + + @computed_field + @property + def all(self) -> list[str]: + """Get All Base Types.""" + return sorted(self.root.keys()) diff --git a/specs/generators/packages/spec/src/spec/cddl/cose.py b/specs/generators/packages/spec/src/spec/cddl/cose.py new file mode 100644 index 00000000000..294655ddfc0 --- /dev/null +++ b/specs/generators/packages/spec/src/spec/cddl/cose.py @@ -0,0 +1,127 @@ +"""Cose CDDL Definitions.""" + +import typing +from enum import Enum +from functools import cached_property + +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, RootModel, computed_field + +from spec.metadata_formats import MetadataFormats +from spec.optional import OptionalField + + +class HeaderType(Enum): + """All header Types.""" + + DOCUMENT = 1 + SIGNATURE = 2 + METADATA = 3 + + +class GenericHeader(BaseModel): + """Generic Cose/Metadata header.""" + + cose_label: str | int | None = Field(default=None, alias="coseLabel") + description: str + required: OptionalField + format: str + + _name: str = PrivateAttr(default="Unknown") + + model_config = ConfigDict(extra="forbid") + + @computed_field + @property + def name(self) -> str: + """Get headers name.""" + return self._name + + @computed_field + @name.setter + def name(self, name: str) -> None: + """Set headers name.""" + self._name = name + + @computed_field + @property + def label(self) -> str: + """Get headers name.""" + if self.cose_label is None: + return f'"{self._name}"' + if isinstance(self.cose_label, str): + return f'"{self.cose_label}"' + return f"{self.cose_label}" + + +class CoseHeader(GenericHeader): + """Cose Header Deserialized Specification.""" + + value: str | list[str] | None = Field(default=None) + + model_config = ConfigDict(extra="forbid") + + +class CoseHeaders(RootModel[dict[str, CoseHeader]]): + """Cose Headers.""" + + root: dict[str, CoseHeader] + + _order: list[str] | None = PrivateAttr(default=None) + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + # Set Cose Header Names + for name, header in self.root.items(): + header.name = name + + def get(self, name: str) -> CoseHeader: + """Get a Cose Header by its name.""" + return self.root[name] + + @computed_field + @cached_property + def all(self) -> list[CoseHeader]: + """Get all Cose Headers sorted and in a list.""" + return [self.get(name) for name in self.names] + + @computed_field + @property + def names(self) -> list[str]: + """Get ordered list of all defined Cose Header Names.""" + if self._order is not None: + return self._order + return list(self.root.keys()) + + def order(self, order: list[str]) -> None: + """Set the order of fields.""" + tmp_order = order + # Add in any unlisted headers + for name in self.root: + if name not in tmp_order: + tmp_order.append(name) + self._order = [] + # remove any listed headers that are not used. + for name in tmp_order: + if name in self.root: + self._order.append(name) + + +class CoseDefinitions(BaseModel): + """Definitions of our COSE Format usage.""" + + header_formats: MetadataFormats = Field(alias="headerFormats") + headers: CoseHeaders + headers_order: list[str] = Field(alias="headersOrder") # dont use directly + signature_headers: CoseHeaders + + model_config = ConfigDict(extra="forbid") + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + # Set Cose Header Order + self.headers.order(self.headers_order) + self.signature_headers.order(self.headers_order) diff --git a/specs/generators/packages/spec/src/spec/cddl/definition.py b/specs/generators/packages/spec/src/spec/cddl/definition.py new file mode 100644 index 00000000000..c2a5ebf4cd1 --- /dev/null +++ b/specs/generators/packages/spec/src/spec/cddl/definition.py @@ -0,0 +1,117 @@ +"""CDDL Definition Specification.""" + +import re +import typing + +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, RootModel, computed_field + + +class CDDLDefinition(BaseModel): + """CDDL Definition Deserialized Specification.""" + + definition: str = Field(alias="def") + requires: list[str] + description: str | None = Field(default=None) + comment: str = Field(default_factory=str) + + _name: str = PrivateAttr(default="Unknown") + + model_config = ConfigDict(extra="forbid") + + @computed_field + def name(self) -> str: # type: ignore[obscured] + """Name Of the Parameter.""" + return self._name + + @name.setter # type: ignore[prop-decorator] + def name(self, val: str) -> None: + self._name = val + + +class CDDLDefinitions(RootModel[dict[str, CDDLDefinition]]): + """Template Json Schema Definitions.""" + + root: dict[str, CDDLDefinition] + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + for def_name, value in self.root.items(): + value.name = def_name + + def get(self, name: str) -> CDDLDefinition: + """Get a CDDL Definition.""" + return self.root[name] + + def add(self, definition: CDDLDefinition | list[CDDLDefinition]) -> None: + """Add (or change) a definitions to the CDDL Definitions.""" + if isinstance(definition, CDDLDefinition): + definition = [definition] + for this_def in definition: + self.root[this_def.name] = this_def + + @staticmethod + def _add_cddl_comments(comment: str) -> tuple[str, bool]: + """Add cddl comment markers to lines. + + Returns True if more than 1 line. + """ + comment = comment.strip() + comment_lines = comment.splitlines() + comment = "" + for line in comment_lines: + comment += f"; {line}\n" + comment = comment.strip() + + return comment, len(comment_lines) > 0 + + def _nested_cddl(self, name: str, found: list[str]) -> tuple[str, list[str]]: + """Get the CDDL for a names definition, recursively.""" + this_cddl = "" + this_def = self.get(name) + cddl_def = this_def.definition.strip() + cddl_def_multiline = len(cddl_def.splitlines()) > 1 + + # Add required definitions to this one (recursive) + for requires in this_def.requires: + if requires not in found: + next_cddl, found = self._nested_cddl(requires, found) + found.append(requires) + this_cddl += next_cddl + + comment: str = this_def.comment + leading_comment = "" + if len(comment) > 0: + comment, multiline = self._add_cddl_comments(comment) + if multiline or cddl_def_multiline: + leading_comment = comment + comment = "\n" # Adds a blank line after defs with multiline comments + + this_cddl = f""" +{leading_comment} +{name} = {cddl_def} {comment} + +{this_cddl} +""" + + return this_cddl, found + + def cddl_file(self, root: str) -> str: + """Get the CDDL File for a root definition with a given name.""" + cddl_data = self._nested_cddl(root, [])[0] + description = self.get(root).description + if description is None: + description = root + description = self._add_cddl_comments(description)[0] + + # Remove double line breaks, + # so we only ever have 1 between definitions + cddl_data = re.sub(r"\n\n[\n]+", "\n\n", cddl_data) + + return f""" +{description} + + +{cddl_data.strip()} +""" diff --git a/specs/generators/packages/spec/src/spec/cddl_definitions.py b/specs/generators/packages/spec/src/spec/cddl_definitions.py deleted file mode 100644 index 42276fa99b4..00000000000 --- a/specs/generators/packages/spec/src/spec/cddl_definitions.py +++ /dev/null @@ -1,14 +0,0 @@ -"""CDDL Definition Specification.""" - -from pydantic import BaseModel, ConfigDict, Field - - -class CDDLDefinition(BaseModel): - """CDDL Definition Deserialized Specification.""" - - definition: str = Field(alias="def") - requires: list[str] - description: str | None = Field(default=None) - comment: str | None = Field(default=None) - - model_config = ConfigDict(extra="forbid") diff --git a/specs/generators/packages/spec/src/spec/content_types.py b/specs/generators/packages/spec/src/spec/content_types.py index 0efb7ae1581..6dcdab8189e 100644 --- a/specs/generators/packages/spec/src/spec/content_types.py +++ b/specs/generators/packages/spec/src/spec/content_types.py @@ -1,9 +1,9 @@ """Content Types Specification.""" -from pydantic import BaseModel, ConfigDict, Field +from pydantic import BaseModel, ConfigDict, Field, RootModel -class ContentTypes(BaseModel): +class ContentType(BaseModel): """Content Types Deserialized Specification.""" description: str @@ -12,9 +12,29 @@ class ContentTypes(BaseModel): model_config = ConfigDict(extra="forbid") -class EncodingTypes(BaseModel): +class ContentTypes(RootModel[dict[str, ContentType]]): + """Content Types Deserialized Specification.""" + + root: dict[str, ContentType] + + def description(self, name: str) -> str: + """Get description of the Content Type.""" + return self.root[name].description + + +class EncodingType(BaseModel): """Encoding Types Deserialized Specification.""" description: str model_config = ConfigDict(extra="forbid") + + +class EncodingTypes(RootModel[dict[str, EncodingType]]): + """Content Types Deserialized Specification.""" + + root: dict[str, EncodingType] + + def description(self, name: str) -> str: + """Get description of the Encoding Type.""" + return self.root[name].description diff --git a/specs/generators/packages/spec/src/spec/cose_header.py b/specs/generators/packages/spec/src/spec/cose_header.py deleted file mode 100644 index 17ef085e49b..00000000000 --- a/specs/generators/packages/spec/src/spec/cose_header.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Cose Header Specification.""" - -from pydantic import BaseModel, ConfigDict, Field - -from spec.optional import OptionalField - - -class CoseHeader(BaseModel): - """Cose Header Deserialized Specification.""" - - cose_label: str | int = Field(alias="coseLabel") - description: str - required: OptionalField - format: str - value: str | list[str] | None = Field(default=None) - - model_config = ConfigDict(extra="forbid") diff --git a/specs/generators/packages/spec/src/spec/doc_clusters.py b/specs/generators/packages/spec/src/spec/doc_clusters.py index d5c0e1f92d4..b926407a2f5 100644 --- a/specs/generators/packages/spec/src/spec/doc_clusters.py +++ b/specs/generators/packages/spec/src/spec/doc_clusters.py @@ -1,16 +1,17 @@ """CDDL Definition Specification.""" +import typing from collections import Counter from functools import cached_property -from pydantic import BaseModel, ConfigDict, PrivateAttr +from pydantic import BaseModel, ConfigDict, PrivateAttr, RootModel class DocCluster(BaseModel): """Document Cluster Deserialized Specification.""" docs: list[str] - _name: str | None = PrivateAttr(default=None) + _name: str = PrivateAttr(default="Unknown") model_config = ConfigDict(extra="forbid") @@ -30,3 +31,38 @@ def set_name(self, name: str) -> None: def name(self) -> str: """Name.""" return self._name + + +class DocClusters(RootModel[dict[str, DocCluster]]): + """All Document Clusters.""" + + root: dict[str, DocCluster] + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + # Set the name in each cluster. + for cluster, value in self.root.items(): + value.set_name(cluster) + + def for_ref(self, ref: list[str]) -> DocCluster | None: + """Get the cluster a document is in, if any.""" + for cluster in self.root.values(): + if cluster.is_cluster(ref): + return cluster + return None + + def get(self, doc_name: str) -> DocCluster | None: + """Is the named document in a cluster.""" + for cluster in self.root.values(): + if cluster.is_in_cluster(doc_name): + return cluster + return None + + def name(self, doc_name: str) -> str | None: + """Is the named document in a cluster of what name.""" + for cluster in self.root.values(): + if cluster.is_in_cluster(doc_name): + return cluster.name + return None diff --git a/specs/generators/packages/spec/src/spec/doc_types.py b/specs/generators/packages/spec/src/spec/doc_types.py new file mode 100644 index 00000000000..9563d67f4e3 --- /dev/null +++ b/specs/generators/packages/spec/src/spec/doc_types.py @@ -0,0 +1,39 @@ +"""Document Types.""" + +from pydantic import RootModel + +from spec.base_types import BaseTypes, DocTypeId + + +class DocType(RootModel[list[DocTypeId]]): + """A Document Type.""" + + root: list[DocTypeId] + + _base_types: BaseTypes + + def set_base_types(self, types: BaseTypes) -> None: + """Save a local copy of the Base Types.""" + self._base_types = types + + def formatted_names(self, *, prefix: str = "", separator: str = "/", suffix: str = "") -> str: + """Return a formatted doc types entry.""" + type_names: list[str] = [self._base_types.name(sub_type) for sub_type in self.root] + return f"{prefix}{separator.join(type_names)}{suffix}" + + def formatted_ids( + self, + *, + prefix: str = "[", + separator: str = ",", + start_quote: str = "", + end_quote: str = "", + suffix: str = "]", + cbor: bool = True, + ) -> str: + """Return doc types formatted optionally as cbor.""" + id_strings: list[str] = ( + [uuid.as_cbor for uuid in self.root] if cbor else [uuid.as_uuid_str for uuid in self.root] + ) + id_strings = [f"{start_quote}{id}{end_quote}" for id in id_strings] + return f"{prefix}{separator.join(id_strings)}{suffix}" diff --git a/specs/generators/packages/spec/src/spec/document.py b/specs/generators/packages/spec/src/spec/document.py index c9c54143470..dbf9db7de85 100644 --- a/specs/generators/packages/spec/src/spec/document.py +++ b/specs/generators/packages/spec/src/spec/document.py @@ -1,12 +1,16 @@ """Individual Document Specification.""" import typing +from functools import cached_property -from pydantic import BaseModel, ConfigDict, Field, PrivateAttr +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, RootModel, computed_field +from spec.authors import Authors +from spec.base_types import BaseTypes +from spec.cddl.cose import CoseHeaders from spec.change_log_entry import ChangeLogEntry -from spec.cose_header import CoseHeader -from spec.metadata import Metadata +from spec.doc_types import DocType +from spec.metadata import MetadataHeaders from spec.payload import Payload from spec.signers import Signers @@ -28,18 +32,18 @@ def empty_string_list() -> list[str]: class Document(BaseModel): """Document Data Definition.""" - type: list[str] + type: DocType description: str | None = Field(default=None) validation: str | None = Field(default=None) business_logic: DocumentBusinessLogic = Field( default_factory=DocumentBusinessLogic, ) notes: list[str] - headers: dict[str, CoseHeader] - metadata: dict[str, Metadata] + headers: CoseHeaders + metadata: MetadataHeaders payload: Payload | None = Field(default=None) signers: Signers - authors: dict[str, str] + authors: Authors versions: list[ChangeLogEntry] _name: str | None = PrivateAttr(default=None) @@ -56,17 +60,20 @@ def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 # Set all the documents this references. all_refs: list[str] = [] - for meta in self.metadata.values(): + for name in self.metadata.names: + meta = self.metadata.get(name) if meta.format == "Document Reference": all_refs.extend(meta.type) self._all_refs = list(set(all_refs)) + def set_base_types(self, types: BaseTypes) -> None: + """Save a local copy of the Base Types.""" + self.type.set_base_types(types) + def set_name(self, doc_name: str) -> None: """Set the name properties.""" self.doc_name = doc_name - - for name, meta in self.metadata.items(): - meta.set_name(name, doc_name) + self.metadata.set_name(doc_name) def add_referer(self, doc_name: str) -> None: """Set the name properties.""" @@ -92,8 +99,41 @@ def all_docs_referencing(self) -> list[str]: 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 + if content_type.value is None: + return "Undefined" + return content_type.value + + +class Documents(RootModel[dict[str, Document]]): + """All Documents.""" + + root: dict[str, Document] + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + # Set the name and references for each document. + for name, doc in self.root.items(): + doc.set_name(name) + for ref_doc in doc.all_references: + self.root[ref_doc].add_referer(name) + + def set_base_types(self, types: BaseTypes) -> None: + """Save a local copy of the Base Types.""" + for doc in self.root.values(): + doc.set_base_types(types) + + def get(self, name: str) -> Document: + """Get a document by its name.""" + return self.root[name] + + @computed_field + @cached_property + def names(self) -> list[str]: + """Get all documents.""" + return list(self.root.keys()) + + def type(self, doc_name: str) -> DocType: + """Get the types for a specific document.""" + return self.root[doc_name].type diff --git a/specs/generators/packages/spec/src/spec/documentation_links.py b/specs/generators/packages/spec/src/spec/documentation_links.py new file mode 100644 index 00000000000..20b38809816 --- /dev/null +++ b/specs/generators/packages/spec/src/spec/documentation_links.py @@ -0,0 +1,41 @@ +"""Documentation Links.""" + +from pydantic import HttpUrl, RootModel, computed_field + + +class LinkAKA(RootModel[dict[str, str]]): + """Link AKA.""" + + root: dict[str, str] + + +class DocumentationLinks(RootModel[dict[str, HttpUrl]]): + """Documentation Links.""" + + root: dict[str, HttpUrl] + + _aka: LinkAKA + + def set_link_aka(self, aka: LinkAKA) -> None: + """Associate the Link AKA with the main documentation Links.""" + self._aka = aka + + def aka(self, link_name: str) -> str | None: + """Get a Link AKA for a link name, or None if it doesn't exist.""" + return self._aka.root.get(link_name) + + @computed_field + @property + def all(self) -> list[str]: + """Get a list of ALL link names, including AKAs. + + Sorted from longest Link name to shortest. + """ + link_aka: list[str] = list(self._aka.root.keys()) + primary_links: list[str] = list(self.root.keys()) + + return sorted(link_aka + primary_links, key=lambda x: -len(x)) + + def link(self, link_name: str) -> str: + """Get a link for a link name.""" + return f"{self.root[link_name]}" diff --git a/specs/generators/packages/spec/src/spec/metadata.py b/specs/generators/packages/spec/src/spec/metadata.py index 8109545c2c7..27bfbb31f46 100644 --- a/specs/generators/packages/spec/src/spec/metadata.py +++ b/specs/generators/packages/spec/src/spec/metadata.py @@ -1,26 +1,27 @@ """Metadata Field Specification.""" +import textwrap +import typing from functools import cached_property -from pydantic import BaseModel, ConfigDict, Field, computed_field +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, RootModel, computed_field +from spec.cddl.cose import GenericHeader +from spec.cddl.definition import CDDLDefinition +from spec.document import DocType +from spec.metadata_formats import MetadataFormats from spec.optional import OptionalField -class Metadata(BaseModel): +class MetadataHeader(GenericHeader): """Metadata Spec Data Definition.""" - description: str - raw_exclusive: list[str] | None = Field(alias="exclusive") - format: str - required: OptionalField validation: str | None raw_type: str | list[str] | None = Field(alias="type", default=None) multiple: bool = Field(default=False) raw_linked_refs: list[str] | None = Field(alias="linked_refs", default=None) # Not deserialized, must be supplied. - name: str | None = Field(default=None) # Comes from `new`. doc_name: str | None = Field(default=None) model_config = ConfigDict(extra="forbid") @@ -39,12 +40,6 @@ def fix_list(fix: str | list[str] | None) -> list[str]: fix = [fix] return fix - @computed_field() - @cached_property - def exclusive(self) -> list[str]: - """Exclusive.""" - return self.fix_list(self.raw_exclusive) - @computed_field() @cached_property def type(self) -> list[str]: @@ -57,66 +52,10 @@ def linked_refs(self) -> list[str]: """Linked Refs.""" return self.fix_list(self.raw_linked_refs) - @staticmethod - def doc_ref_link(name: str, depth: int = 0, *, html: bool = False) -> str: - """Metadata Document Reference link.""" - link = name.lower().replace(" ", "_") - - if html: - link += "/" - else: - link += ".md" - - if depth == 0: - link = f"./docs/{link}" - else: - maxdepth = 0 if html else 1 - while depth > maxdepth: - link = f"../{link}" - depth -= 1 - - if html: - return link - return f"[{name}]({link})" - - @staticmethod - def format_link(name: str, depth: int = 0) -> str: - """Metadata Format link.""" - link = f"metadata.md#{name.lower().replace(' ', '-')}" - - while depth > 0: - link = f"../{link}" - depth -= 1 - - return f"[{name}]({link})" - - @staticmethod - def field_link(name: str, depth: int = 0) -> str: - """Metadata Field link.""" - link = f"metadata.md#{name.lower().replace('`', '')}" - - while depth > 0: - link = f"../{link}" - depth -= 1 - - return f"[`{name}`]({link})" - def get_validation(self) -> str: """Get the Validation documentation (enhanced from the data itself).""" # Adds text to the validation description, so get it here. - validation = self.validation - - # Add notes about exclusive field relationships. - if len(self.exclusive) > 0: - exclusive_def = f"\n`{self.exclusive[0]}`" - if len(self.exclusive) > 1: - if len(self.exclusive) > 2: # noqa: PLR2004 - for exclude in self.exclusive[1:-1]: - # We break the line so it doesn't get too long. - exclusive_def += f"\n, `{exclude}`" - - exclusive_def += f"\nand `{self.exclusive[-1]}`" - validation += f"\n* MUST NOT be present in any document that contains {exclusive_def} metadata." + validation = self.validation if self.validation is not None else "" for ref in self.linked_refs: validation += f""" @@ -130,7 +69,7 @@ def is_excluded(self) -> bool: """Is this metadata excluded from the specs definition. (must not be present).""" return self.required == "excluded" - def metadata_as_markdown(self, *, doc_types: list[str] | None = None) -> str: + def metadata_as_markdown(self, *, doc_types: DocType | None = None) -> str: """Generate Markdown of Metadata fields for the default set, or a specific document.""" field_title_level = "###" @@ -147,8 +86,10 @@ def metadata_as_markdown(self, *, doc_types: list[str] | None = None) -> str: if self.name == "type" and doc_types is not None: # Display the actual documents type values - monospace_types = [f"`{doc_type}`" for doc_type in doc_types] - field_display += f"| Type | {',
'.join(monospace_types)} |\n" + formatted_id = doc_types.formatted_ids( + prefix="", start_quote="`", end_quote="`", separator=",
", suffix="", cbor=False + ) + field_display += f"| Type | {formatted_id} |\n" if self.multiple: field_display += f"| Multiple References | {self.multiple} |\n" @@ -163,11 +104,6 @@ def metadata_as_markdown(self, *, doc_types: list[str] | None = None) -> str: field_display += f"| {ref_heading} | [`{ref_field}`](#{ref_field}) |\n" ref_heading = "" - exclusive_title = "Exclusive" - for ref in self.exclusive: - field_display += f"| {exclusive_title} | `{ref}` |\n" - exclusive_title = "" - field_display += f""" {self.description} @@ -176,3 +112,95 @@ def metadata_as_markdown(self, *, doc_types: list[str] | None = None) -> str: {self.get_validation()} """ return field_display + + +class MetadataHeaders(RootModel[dict[str, MetadataHeader]]): + """All Metadata Headers.""" + + root: dict[str, MetadataHeader] + + _order: list[str] | None = PrivateAttr(default=None) + _doc_name: str | None = PrivateAttr(default=None) + + def get(self, name: str) -> MetadataHeader: + """Get a Metadata Header by its name.""" + return self.root[name] + + @computed_field + @property + def names(self) -> list[str]: + """Get ordered list of all defined Metadata Header Names.""" + if self._order is not None: + return self._order + return list(self.root.keys()) + + @computed_field + @property + def all(self) -> typing.Sequence[MetadataHeader]: + """Get all metadata headers, in order.""" + return [self.root[header] for header in self.names] + + def order(self, order: list[str]) -> None: + """Set the order of fields.""" + tmp_order = order + # Add in any unlisted headers + for name in self.root: + if name not in tmp_order: + tmp_order.append(name) + self._order = [] + # remove any listed headers that are not used. + for name in tmp_order: + if name in self.root: + self._order.append(name) + + def set_name(self, doc_name: str | None = None) -> None: + """Set the name properties.""" + self._doc_name = doc_name + for name, header in self.root.items(): + header.set_name(name, doc_name) + + +class Metadata(BaseModel): + """Metadata Fields in the COSE Document.""" + + headers: MetadataHeaders + formats: MetadataFormats + order: list[str] + + _doc_name: str | None = PrivateAttr(default=None) + + model_config = ConfigDict(extra="forbid") + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + # Set Header Order + self.headers.order(self.order) + + def set_name(self, doc_name: str | None = None) -> None: + """Set the name properties.""" + self._doc_name = doc_name + self.headers.set_name(doc_name) + + @staticmethod + def custom_metadata_header( + cddl_def: CDDLDefinition, headers: typing.Sequence[GenericHeader], formats: MetadataFormats + ) -> CDDLDefinition: + """Generate a synthetic cddl def for this type. + + Needs to be generated from Metadata definitions. + """ + new_def = cddl_def.model_copy() + new_def.requires = [] + new_cddl: str = "" + + for header in headers: + optional = "" if header.required == OptionalField.required else "?" + cddl_type = formats.get(header.format).cddl + new_cddl += f"{optional}{header.label} => {cddl_type}\n" + if cddl_type not in new_def.requires: + new_def.requires.append(cddl_type) + + new_def.definition = f"(\n{textwrap.indent(new_cddl, ' ')})" + return new_def diff --git a/specs/generators/packages/spec/src/spec/metadata_formats.py b/specs/generators/packages/spec/src/spec/metadata_formats.py index 87a3fb925f9..86eb349cfb0 100644 --- a/specs/generators/packages/spec/src/spec/metadata_formats.py +++ b/specs/generators/packages/spec/src/spec/metadata_formats.py @@ -1,12 +1,27 @@ """Metadata Formats Specification.""" -from pydantic import BaseModel, ConfigDict +from pydantic import BaseModel, ConfigDict, RootModel -class MetadataFormats(BaseModel): +class MetadataFormat(BaseModel): """Metadata Formats Deserialized Specification.""" description: str cddl: str model_config = ConfigDict(extra="forbid") + + +class MetadataFormats(RootModel[dict[str, MetadataFormat]]): + """Metadata Formats Deserialized Specification.""" + + root: dict[str, MetadataFormat] + + @property + def all(self) -> list[str]: + """Get names of all metadata formats.""" + return list(self.root.keys()) + + def get(self, name: str) -> MetadataFormat: + """Get named metadata format.""" + return self.root[name] diff --git a/specs/generators/packages/spec/src/spec/signed_doc.py b/specs/generators/packages/spec/src/spec/signed_doc.py index 43d47d0aa0d..fdf301e28e6 100644 --- a/specs/generators/packages/spec/src/spec/signed_doc.py +++ b/specs/generators/packages/spec/src/spec/signed_doc.py @@ -4,73 +4,41 @@ import datetime import json -import textwrap import typing -from enum import Enum from pathlib import Path -from pydantic import BaseModel, ConfigDict, Field, HttpUrl, PrivateAttr +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr -from spec.cddl_definitions import CDDLDefinition +from spec.authors import Authors +from spec.base_types import BaseTypes +from spec.cddl.cose import CoseDefinitions +from spec.cddl.definition import CDDLDefinitions from spec.change_log_entry import ChangeLogEntry from spec.content_types import ContentTypes, EncodingTypes from spec.copyright import Copyright -from spec.cose_header import CoseHeader -from spec.doc_clusters import DocCluster -from spec.document import Document +from spec.doc_clusters import DocClusters +from spec.document import Documents +from spec.documentation_links import DocumentationLinks, LinkAKA from spec.forms.template import FormTemplate -from spec.metadata import Metadata -from spec.metadata_formats import MetadataFormats +from spec.metadata import Metadata, MetadataHeader from spec.optional import OptionalField -class HeaderType(Enum): - """All header Types.""" - - DOCUMENT = 1 - SIGNATURE = 2 - METADATA = 3 - - -HEADERS: dict[str, dict[str, str]] = { - HeaderType.DOCUMENT.name: { - "headers": "cose_headers", - "order": "cose_headers_order", - "format": "coseHeaderFormats", - }, - HeaderType.SIGNATURE.name: { - "headers": "cose_signature_headers", - "order": "cose_signature_headers_order", - "format": "coseHeaderFormats", - }, - HeaderType.METADATA.name: { - "headers": "metadata", - "order": "metadata_order", - "format": "metadataFormats", - }, -} - - class SignedDoc(BaseModel): """Signed Doc Deserialized Specification.""" - authors: dict[str, str] - base_types: dict[str, str] - cddl_definitions: dict[str, CDDLDefinition] = Field(alias="cddlDefinitions") - content_types: dict[str, ContentTypes] = Field(alias="contentTypes") + authors: Authors + base_types: BaseTypes + cddl_definitions: CDDLDefinitions = Field(alias="cddlDefinitions") + content_types: ContentTypes = Field(alias="contentTypes") copyright: Copyright - cose_header_formats: dict[str, MetadataFormats] = Field(alias="coseHeaderFormats") - cose_headers: dict[str, CoseHeader] - cose_headers_order: list[str] - cose_signature_headers: dict[str, CoseHeader] - doc_clusters: dict[str, DocCluster] - docs: dict[str, Document] - documentation_links: dict[str, HttpUrl] = Field(alias="documentationLinks") - encoding_types: dict[str, EncodingTypes] = Field(alias="encodingTypes") - link_aka: dict[str, str] = Field(alias="linkAKA") - metadata: dict[str, Metadata] - metadata_formats: dict[str, MetadataFormats] = Field(alias="metadataFormats") - metadata_order: list[str] + cose: CoseDefinitions + doc_clusters: DocClusters + docs: Documents + documentation_links: DocumentationLinks = Field(alias="documentationLinks") + encoding_types: EncodingTypes = Field(alias="encodingTypes") + link_aka_dont_use: LinkAKA = Field(alias="linkAKA") # dont use directly + metadata: Metadata form_template: FormTemplate = Field(alias="formTemplate") _data: dict[str, typing.Any] = PrivateAttr(default_factory=dict[str, typing.Any]) @@ -93,189 +61,42 @@ def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 """Extra setup after we deserialize.""" super().model_post_init(context) - # Set the name in each cluster. - for cluster, value in self.doc_clusters.items(): - value.set_name(cluster) - - # Set the name and references for each document. - for name, doc in self.docs.items(): - doc.set_name(name) - for ref_doc in doc.all_references: - self.docs[ref_doc].add_referer(name) - - def ref_in_cluster(self, ref: list[str]) -> DocCluster | None: - """Get the cluster a document is in, if any.""" - for cluster in self.doc_clusters.values(): - if cluster.is_cluster(ref): - return cluster - return None - - def doc_in_cluster(self, doc_name: str) -> DocCluster | None: - """Is the named document in a cluster.""" - for cluster in self.doc_clusters.values(): - if cluster.is_in_cluster(doc_name): - return cluster - return None - - def doc_in_cluster_name(self, doc_name: str) -> str | None: - """Is the named document in a cluster of what name.""" - for cluster in self.doc_clusters.values(): - if cluster.is_in_cluster(doc_name): - return cluster.name - return None + # Put Base Document Types inside the individual doc types for easy reference. + self.docs.set_base_types(self.base_types) + self.metadata.set_name(None) + + # Associate the Link AKA with documentation links. + self.documentation_links.set_link_aka(self.link_aka_dont_use) + + # Build dynamic CDDL Definitions from the defined headers. + self.cddl_definitions.add( + [ + Metadata.custom_metadata_header( + self.cddl_definitions.get("Signed_Document_Metadata_Headers"), + self.metadata.headers.all, + self.metadata.formats, + ), + Metadata.custom_metadata_header( + self.cddl_definitions.get("COSE_Document_Standard_Headers"), + self.cose.headers.all, + self.cose.header_formats, + ), + Metadata.custom_metadata_header( + self.cddl_definitions.get("COSE_Signature_Standard_Headers"), + self.cose.signature_headers.all, + self.cose.header_formats, + ), + ] + ) 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 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[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.""" - return self.link_aka.get(link_name) - - def link_names(self) -> list[str]: - """Get a list of ALL link names, including AKAs. - - Sorted from longest Link name to shortest. - """ - link_aka: list[str] = list(self.link_aka.keys()) - primary_links: list[str] = list(self.documentation_links.keys()) - - return sorted(link_aka + primary_links, key=lambda x: -len(x)) - - def link_for_link_name(self, link_name: str) -> str: - """Get a link for a link name.""" - return f"{self.documentation_links[link_name]}" - - 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] - - def content_type_description(self, content_type: str) -> str: - """Get a description for a known content type.""" - return self.content_types[content_type].description - - 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[str, typing.Any], list[str], str]: - """Get headers and their ordering for a header_type.""" - headers_key = HEADERS[header_type.name]["headers"] - header_order_key = HEADERS[header_type.name]["order"] - formats = HEADERS[header_type.name]["format"] - - 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: - if header not in header_order: - header_order.append(header) - - return (headers, header_order, formats) - - def all_headers(self, header_type: HeaderType = HeaderType.DOCUMENT) -> list[str]: - """Return a list of sorted Cose headers.""" - _, header_order, _ = self.headers_and_order(header_type) - return header_order - - 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) - - cddl_def = headers.get(name) - if cddl_def is not None: - cddl_def = cddl_def.get("format") - if cddl_def is not None: - 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[str, typing.Any] | None: # noqa: C901 - """Get a cddl definition by name.""" - - 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: list[str] = [] - - headers, header_names, _ = self.headers_and_order(header_type) - - for header in header_names: - header_data = headers[header] - optional = "" if header_data["required"] == "yes" else "?" - - exclusive: list[str] | None = header_data.get("exclusive") - if exclusive is not None: - exclusive.append(header) - exclusive.sort() - 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 requires: - requires.append(cddl_type) - defs["requires"] = requires - for exclusive_set in exclusives: - # Exclusive sets are never required - 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) - if isinstance(field_name, str): - field_name = f'"{field_name}"' - exclusive_fields.append(f"{field_name} => {cddl_type}") - if cddl_type not in defs["requires"]: - defs["requires"].append(cddl_type) - - cddl_def += f"""? ( - {" //\n ".join(exclusive_fields)} -) -""".strip() - defs["def"] = f"(\n{textwrap.indent(cddl_def, ' ')})" - return defs - - defs = self._data.get("cddlDefinitions") - if defs is not None: - defs = defs.get(name) - if name == "Signed_Document_Metadata_Headers": - defs = synthetic_headers(defs, HeaderType.METADATA) - elif name == "COSE_Document_Standard_Headers": - defs = synthetic_headers(defs, HeaderType.DOCUMENT) - elif name == "COSE_Signature_Standard_Headers": - defs = synthetic_headers(defs, HeaderType.SIGNATURE) - return defs - def get_copyright( self, document_name: str | None, - ) -> tuple[dict[str, str], Copyright, list[ChangeLogEntry], datetime.date]: + ) -> tuple[Authors, Copyright, list[ChangeLogEntry], datetime.date]: """Get copyright information from the spec.""" def get_latest_file_change( @@ -298,8 +119,8 @@ def get_latest_file_change( doc_versions = None if document_name is not None: - doc = self.docs[document_name] - authors = doc.authors | authors + doc = self.docs.get(document_name) + authors = doc.authors.combine(authors) doc_versions = doc.versions latest_change = get_latest_file_change(versions, doc_versions) @@ -308,53 +129,23 @@ def get_latest_file_change( return (authors, copyright_data, versions, latest_change) - def base_document_types(self) -> dict[str, str]: - """Get the base document types.""" - return self.base_types - - def document_type(self, doc_name: str) -> list[str]: - """Get the types for a specific document.""" - return self.docs[doc_name].type - - def doc_name_for_type(self, uuid: str) -> str: - """Get the name for a document base type, given its uuid.""" - doc_types = self.base_document_types() - for k, v in doc_types.items(): - if v == uuid: - return k - return "Unknown" - - def get_document(self, doc_name: str) -> Document: - """Get a named document.""" - doc = self.docs[doc_name] - doc.set_name(doc_name) - return doc - - def get_metadata(self, metadata_name: str, doc_name: str | None = None) -> Metadata: + def get_metadata(self, metadata_name: str, doc_name: str | None = None) -> MetadataHeader: """Get a metadata definition by name, and optionally for a document.""" if doc_name is None: - raw_metadata_def = self.metadata[metadata_name] + raw_metadata_def = self.metadata.headers.get(metadata_name) else: - raw_metadata_def = self.docs[doc_name].metadata[metadata_name] + raw_metadata_def = self.docs.get(doc_name).metadata.get(metadata_name) raw_metadata_def.set_name(metadata_name, doc_name) return raw_metadata_def - def get_all_metadata_formats(self) -> list[str]: - """Get a list of all metadata formats defined.""" - return self._data["metadataFormats"].keys() - - def get_metadata_format(self, format_name: str) -> MetadataFormats: - """Get a metadata format definition by name.""" - return self.metadata_formats[format_name] - def get_metadata_as_markdown(self, doc_name: str | None = None) -> str: """Get metadata definitions in a markdown format.""" - fields = self.all_headers(HeaderType.METADATA) + fields = self.metadata.headers.names field_display = "" for field in fields: doc_types = None if doc_name is not None: - doc_types = self.get_document(doc_name).type + doc_types = self.docs.type(doc_name) metadata_def = self.get_metadata(field, doc_name) if doc_name is None or metadata_def.required != OptionalField.excluded: field_display += metadata_def.metadata_as_markdown( diff --git a/specs/generators/src/docs/cddl_file.py b/specs/generators/src/docs/cddl_file.py index afd02dc7b2e..2269638f6b7 100644 --- a/specs/generators/src/docs/cddl_file.py +++ b/specs/generators/src/docs/cddl_file.py @@ -1,7 +1,6 @@ """Generate CDDL Files.""" import argparse -import re import textwrap from spec.signed_doc import SignedDoc @@ -9,7 +8,7 @@ from .doc_generator import DocGenerator -def add_cddl_comments(comment: str) -> tuple[str, bool]: +def x_add_cddl_comments(comment: str) -> tuple[str, bool]: """Add cddl comment markers to lines. Returns True if more than 1 line. @@ -34,18 +33,18 @@ def __init__(self, args: argparse.Namespace, spec: SignedDoc, cddl_root: str) -> super().__init__(args, spec, file_name, flags=self.NO_FLAGS) self._cddl_root = cddl_root - def get_cddl(self, name: str, found: list[str] | None = None) -> tuple[str, list[str]]: + def x_get_cddl(self, name: str, found: list[str] | None = None) -> tuple[str, list[str]]: """Get the CDDL for a metadatum.""" if found is None: found = [] this_cddl = "" - this_def = self._spec.cddl_def(name) - cddl_def: str = this_def["def"].strip() + this_def = self._spec.cddl_definitions.get(name) + cddl_def = this_def.definition.strip() cddl_def_multiline = len(cddl_def.splitlines()) > 1 # Add required definitions to this one (recursive) - for requires in this_def["requires"]: + for requires in this_def.requires: if requires not in found: next_cddl, found = self.get_cddl(requires, found) found.append(requires) @@ -91,19 +90,6 @@ def markdown_reference(self, *, indent: int = 0, relative_doc: DocGenerator | No def generate(self) -> bool: """Generate a CDDL File.""" - cddl_data, _ = self.get_cddl(self._cddl_root) - defs = self._spec.cddl_def(self._cddl_root) + self._filedata = self._spec.cddl_definitions.cddl_file(self._cddl_root) - description, _ = add_cddl_comments(defs.get("description", f"{self._cddl_root}")) - - # Remove double line breaks, - # so we only ever have 1 between definitions - cddl_data = re.sub(r"\n\n[\n]+", "\n\n", cddl_data) - - self._filedata = f""" -{description} - - -{cddl_data.strip()} -""" return super().generate() diff --git a/specs/generators/src/docs/doc_generator.py b/specs/generators/src/docs/doc_generator.py index aebfc401ba6..e7024c27fb4 100644 --- a/specs/generators/src/docs/doc_generator.py +++ b/specs/generators/src/docs/doc_generator.py @@ -11,8 +11,8 @@ import rich import rich.markdown -from spec.metadata import Metadata -from spec.signed_doc import HeaderType, SignedDoc +from docs.markdown import MarkdownHelpers +from spec.signed_doc import SignedDoc class DocGenerator: @@ -45,11 +45,6 @@ def __init__( # Make sure any destination directory exists. self._filepath.parent.mkdir(parents=True, exist_ok=True) - @staticmethod - def uuid_as_cbor(uuid: str) -> str: - """UUID in CBOR Diagnostic Notation.""" - return f"37(h'{uuid.replace('-', '')}')" - @staticmethod def name_to_spec_link(name: str, ref: str | None = None) -> str: """Create a link to a document type, and an optional ref inside the document.""" @@ -93,8 +88,8 @@ def add_doc_ref_links(self, *, primary_source: bool = False) -> None: All Document References in text must be as `` or they will not be linked. """ self.add_generic_markdown_links( - self._spec.document_names(), - Metadata.doc_ref_link, + self._spec.docs.names, + MarkdownHelpers.doc_ref_link, primary_source=primary_source, ) @@ -103,10 +98,9 @@ def add_metadata_links(self) -> None: All metadata fields in text must be as `` or they will not be linked. """ - _, metadata_names, _ = self._spec.headers_and_order(header_type=HeaderType.METADATA) self.add_generic_markdown_links( - metadata_names, - Metadata.field_link, + self._spec.metadata.headers.names, + MarkdownHelpers.field_link, primary_source=self._is_metadata_primary_source, ) @@ -116,8 +110,8 @@ def add_metadata_format_links(self) -> None: All metadata formats in text must be as `` or they will not be linked. """ self.add_generic_markdown_links( - self._spec.format_names(header_type=HeaderType.METADATA), - Metadata.format_link, + self._spec.metadata.formats.all, + MarkdownHelpers.format_link, primary_source=self._is_metadata_primary_source, ) @@ -168,13 +162,11 @@ def add_reference_links(self) -> None: self.strip_end_whitespace() - actual_link_names = self._spec.link_names() - actual_links_used: dict[str, str] = {} - for link_name in actual_link_names: + for link_name in self._spec.documentation_links.all: esc_link_name = re.escape(link_name) link_name_regex = f"(^|\\s)({esc_link_name})(\\.|\\s|$)" - aka = self._spec.link_name_aka(link_name) + aka = self._spec.documentation_links.aka(link_name) if aka is not None: replacement = f"\\1[\\2][{aka}]\\3" link_name = aka # noqa: PLW2901 @@ -185,7 +177,7 @@ def add_reference_links(self) -> None: link_name_regex, replacement, ): - actual_links_used[link_name] = self._spec.link_for_link_name(link_name) + actual_links_used[link_name] = self._spec.documentation_links.link(link_name) for link, actual in actual_links_used.items(): self._filedata += f"\n[{link}]: {actual}" @@ -242,8 +234,8 @@ def insert_copyright(self, *, changelog: bool = True) -> str: ) author_title = " Authors " - for author in sorted(authors): - copyright_notice += f"|{author_title}| {author} <{authors[author]}> |\n" + for author in authors.all(): + copyright_notice += f"|{author_title}| {author} <{authors.email(author)}> |\n" author_title = " " if changelog: diff --git a/specs/generators/src/docs/doc_relationship_diagrams.py b/specs/generators/src/docs/doc_relationship_diagrams.py index bef78bcbe78..b64cb8a50fc 100644 --- a/specs/generators/src/docs/doc_relationship_diagrams.py +++ b/specs/generators/src/docs/doc_relationship_diagrams.py @@ -3,9 +3,9 @@ import argparse import textwrap -from spec.metadata import Metadata +from docs.markdown import MarkdownHelpers from spec.optional import OptionalField -from spec.signed_doc import HeaderType, SignedDoc +from spec.signed_doc import SignedDoc from .doc_generator import DocGenerator from .graphviz_doc_diagram import Cluster, DotFile, DotLink, DotLinkEnd, DotSignedDoc, FontTheme, TableRow @@ -46,7 +46,7 @@ def markdown_reference( def generate(self) -> bool: # noqa: C901 """Generate a Document Relationship Diagram File.""" - doc_names = self._spec.document_names() if self._document_name is None else [self._document_name] + doc_names = self._spec.docs.names if self._document_name is None else [self._document_name] file_id = self._document_name if self._document_name is not None else "All" file_title = textwrap.fill(f"{file_id} Document Relationships", width=30) @@ -58,19 +58,20 @@ def generate(self) -> bool: # noqa: C901 all_dst_refs: list[str] = [] for doc in doc_names: - cluster = Cluster.from_doc_cluster(self._spec.doc_in_cluster(doc)) + cluster = Cluster.from_doc_cluster(self._spec.doc_clusters.get(doc)) doc_table = DotSignedDoc( table_id=doc, - title_href=Metadata.doc_ref_link(doc, self._depth, html=True), + title_href=MarkdownHelpers.doc_ref_link(doc, self._depth, html=True), cluster=cluster, ) - doc_data = self._spec.get_document(doc) + doc_data = self._spec.docs.get(doc) + doc_type = doc_data.type.formatted_ids(prefix="", separator="
", suffix="", cbor=False) # Add content type explicitely to table. 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): + for meta in self._spec.metadata.headers.names: doc_metadata = self._spec.get_metadata(meta, doc) # Skip excluded metadata. if doc_metadata.required == OptionalField.excluded: @@ -80,7 +81,7 @@ def generate(self) -> bool: # noqa: C901 doc_table.add_row( TableRow( name=meta, - value=doc_data.type, + value=doc_type, value_theme=FontTheme(face="Courier", bold=True, italic=True), ) ) @@ -96,10 +97,10 @@ def generate(self) -> bool: # noqa: C901 dst_dir = "n" if doc == link_dst else "w" # Add dummy destination table, in case we don't have it in our docs. - ref_cluster = Cluster.from_doc_cluster(self._spec.doc_in_cluster(link_dst)) + ref_cluster = Cluster.from_doc_cluster(self._spec.doc_clusters.get(link_dst)) dummy_table = DotSignedDoc( table_id=link_dst, - title_href=Metadata.doc_ref_link( + title_href=MarkdownHelpers.doc_ref_link( link_dst, depth=self._depth, html=True, @@ -132,10 +133,10 @@ def generate(self) -> bool: # noqa: C901 for ref_doc in doc_data.all_docs_referencing: if ref_doc not in doc_names: # Then we need to create a dummy doc and link. - ref_cluster = Cluster.from_doc_cluster(self._spec.doc_in_cluster(ref_doc)) + ref_cluster = Cluster.from_doc_cluster(self._spec.doc_clusters.get(ref_doc)) ref_doc_table = DotSignedDoc( table_id=ref_doc, - title_href=Metadata.doc_ref_link(ref_doc, self._depth, html=True), + title_href=MarkdownHelpers.doc_ref_link(ref_doc, self._depth, html=True), cluster=ref_cluster, ) dot_file.add_table(ref_doc_table) diff --git a/specs/generators/src/docs/docs_page_md.py b/specs/generators/src/docs/docs_page_md.py index 2d53714428b..b1b546707c1 100644 --- a/specs/generators/src/docs/docs_page_md.py +++ b/specs/generators/src/docs/docs_page_md.py @@ -25,14 +25,14 @@ def __init__(self, args: argparse.Namespace, spec: SignedDoc, doc_name: str) -> super().__init__(args, spec, file_name, flags=self.HAS_MARKDOWN_LINKS) self._document_name = doc_name - self._doc = self._spec.get_document(doc_name) + self._doc = self._spec.docs.get(doc_name) self._depth = 1 @classmethod def save_or_validate_all(cls, args: argparse.Namespace, spec: SignedDoc) -> bool: """Save or Validate all documentation pages.""" good = True - for doc_name in spec.document_names(): + for doc_name in spec.docs.names: good &= cls(args, spec, doc_name).save_or_validate() return good @@ -47,8 +47,8 @@ def header_parameter_summary(self) -> str: """Generate concrete Cose header parameter settings for a specific document.""" headers = self._doc.headers header_docs = "" - for header, value in headers.items(): - value = value.value # noqa: PLW2901 + for header in headers.names: + value = headers.get(header).value if isinstance(value, list): value = f"[{','.join(value)}]" # noqa: PLW2901 link = f"../spec.md#{header.replace(' ', '-')}" diff --git a/specs/generators/src/docs/markdown.py b/specs/generators/src/docs/markdown.py new file mode 100644 index 00000000000..4f098d79da5 --- /dev/null +++ b/specs/generators/src/docs/markdown.py @@ -0,0 +1,46 @@ +"""Markdown Helper and Formatting Functions.""" + + +class MarkdownHelpers: + """Markdown Helper and Formatting Functions.""" + + @staticmethod + def format_link(name: str, depth: int = 0, *, file: str = "metadata.md", monospace: bool = False) -> str: + """Format link.""" + link = f"{file}#{name.lower().replace(' ', '-')}" + + while depth > 0: + link = f"../{link}" + depth -= 1 + + if monospace: + name = f"`{name}`" + + return f"[{name}]({link})" + + @staticmethod + def doc_ref_link(name: str, depth: int = 0, *, html: bool = False) -> str: + """Metadata Document Reference link.""" + link = name.lower().replace(" ", "_") + + if html: + link += "/" + else: + link += ".md" + + if depth == 0: + link = f"./docs/{link}" + else: + maxdepth = 0 if html else 1 + while depth > maxdepth: + link = f"../{link}" + depth -= 1 + + if html: + return link + return f"[{name}]({link})" + + @staticmethod + def field_link(name: str, depth: int = 0) -> str: + """Metadata Field link.""" + return MarkdownHelpers.format_link(name, depth, monospace=True) diff --git a/specs/generators/src/docs/metadata_md.py b/specs/generators/src/docs/metadata_md.py index b8662543d4c..4256b315a5a 100644 --- a/specs/generators/src/docs/metadata_md.py +++ b/specs/generators/src/docs/metadata_md.py @@ -29,8 +29,8 @@ def metadata_types(self) -> str: """Generate the metadata types documentation.""" metadata_types = "" - for format_name in self._spec.get_all_metadata_formats(): - format_def = self._spec.get_metadata_format(format_name) + for format_name in self._spec.metadata.formats.all: + format_def = self._spec.metadata.formats.get(format_name) cddl_def = CDDLFile(self._args, self._spec, format_def.cddl) if not cddl_def.save_or_validate(): @@ -70,25 +70,3 @@ def generate(self) -> bool: console.print_exception() return False return super().generate() - - @staticmethod - def format_link(name: str, depth: int = 0) -> str: - """Metadata Format link.""" - link = f"metadata.md#{name.lower().replace(' ', '-')}" - - while depth > 0: - link = f"../{link}" - depth -= 1 - - return f"[{name}]({link})" - - @staticmethod - def field_link(name: str, depth: int = 0) -> str: - """Metadata Field link.""" - link = f"metadata.md#{name.lower().replace('`', '')}" - - while depth > 0: - link = f"../{link}" - depth -= 1 - - return f"[`{name}`]({link})" diff --git a/specs/generators/src/docs/spec_md.py b/specs/generators/src/docs/spec_md.py index ee53e51de4d..8432d2de483 100644 --- a/specs/generators/src/docs/spec_md.py +++ b/specs/generators/src/docs/spec_md.py @@ -2,7 +2,8 @@ import argparse -from spec.signed_doc import HeaderType, SignedDoc +from spec.cddl.cose import CoseHeader, HeaderType +from spec.signed_doc import SignedDoc from .cddl_file import CDDLFile from .doc_generator import DocGenerator @@ -15,26 +16,22 @@ def __init__(self, args: argparse.Namespace, spec: SignedDoc) -> None: """Initialise Spec.md generator.""" super().__init__(args, spec, "spec.md") - def header_parameter_doc(self, header: str, header_type: HeaderType) -> str: + def header_parameter_doc(self, header: CoseHeader) -> str: """Create documentation for a single cose header.""" - options = self._spec.header(header, header_type=header_type) - label = options.get("coseLabel") - custom_header = "***Custom Header***" - if not isinstance(label, str): + if not isinstance(header.cose_label, str): custom_header = "" - header_format = options["format"] - 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 = f"{header.format}" + if isinstance(header.value, list) and len(header.value) > 0: header_format_display += "\n * Supported Values:" - for value in header_value: + for value in header.value: value_entry = f"\n * {value}" description = None - if header_format == "Media Type": - description = self._spec.content_type_description(value) - if header_format == "HTTP Content Encoding": - description = self._spec.encoding_type_description(value) + if header.format == "Media Type": + description = self._spec.content_types.description(value) + if header.format == "HTTP Content Encoding": + description = self._spec.encoding_types.description(value) if description is not None: value_entry += f" : {description.replace('\n', '\n ')}" @@ -42,21 +39,27 @@ def header_parameter_doc(self, header: str, header_type: HeaderType) -> str: header_format_display += value_entry return f""" -#### `{header}` +#### `{header.name}` -{options.get("description")} +{header.description} -* Required : {options["required"]} -* Cose Label : {label} {custom_header} +* Required : {header.required.value} +* Cose Label : {header.cose_label} {custom_header} * Format : {header_format_display} """ def cose_header_parameters(self, header_type: HeaderType) -> str: """Insert details about Cose header Parameters that are defined for use.""" - headers = self._spec.all_headers(header_type) + if header_type == HeaderType.DOCUMENT: + headers = self._spec.cose.headers.all + elif header_type == HeaderType.SIGNATURE: + headers = self._spec.cose.signature_headers.all + else: + return "" # No Cose Headers in metadata. + header_parameters_doc = "" for header in headers: - header_parameters_doc += self.header_parameter_doc(header, header_type=header_type) + header_parameters_doc += self.header_parameter_doc(header) return header_parameters_doc.strip() diff --git a/specs/generators/src/docs/types_md.py b/specs/generators/src/docs/types_md.py index 69520a94044..68b1ab907ca 100644 --- a/specs/generators/src/docs/types_md.py +++ b/specs/generators/src/docs/types_md.py @@ -15,51 +15,33 @@ def __init__(self, args: argparse.Namespace, spec: SignedDoc) -> None: """Initialize.""" super().__init__(args, spec, "types.md") - def formatted_doc_types(self, name: str) -> str: - """Return a formatted doc types entry.""" - types = self._spec.document_type(name) - type_names = "" - for sub_type in types: - type_names += f"{self._spec.doc_name_for_type(sub_type)}/" - return type_names[:-1] - - def formatted_cbor_doc_types(self, name: str) -> str: - """Return doc types formatted as cbor.""" - types = self._spec.document_type(name) - type_names = "[" - for sub_type in types: - type_names += self.uuid_as_cbor(sub_type) + ",
" - return type_names[:-6] + "]" - def doc_type_summary(self) -> str: """Generate a Document Base Type Summary from the Document Specifications Data.""" - doc_types = self._spec.base_document_types() - doc_type_summary = """ | Base Type | UUID | CBOR | | :--- | :--- | :--- | """ - for k, v in doc_types.items(): - doc_type_summary += f"| {k} | `{v}` | `{self.uuid_as_cbor(v)}` |\n" + for type_name in self._spec.base_types.all: + uuid = self._spec.base_types.uuid(type_name) + doc_type_summary += f"| {type_name} | `{uuid.as_uuid_str}` | `{uuid.as_cbor}` |\n" return doc_type_summary.strip() def doc_type_details(self) -> str: """Generate a Document Type Detailed Summary from the Document Specifications Data.""" - docs = self._spec.document_names() - doc_type_details = """ | Document Type | Base Types | CBOR | | :--- | :--- | :--- | """ - for k in docs: + for k in self._spec.docs.names: + doc_type = self._spec.docs.type(k) doc_type_details += ( f"| [{k}]({self.name_to_spec_link(k)}) |" - f" {self.formatted_doc_types(k)} |" - f" {self.formatted_cbor_doc_types(k)} |\n" + f" {doc_type.formatted_names()} |" + f" {doc_type.formatted_ids(separator=',
')} |\n" ) doc_type_details += "" diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 211fcd87716..02e96775771 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -261,53 +261,55 @@ } ] }, - "coseHeaderFormats": { - "Catalyst ID": { - "cddl": "catalyst_id_kid", - "description": "KID (Catalyst ID URI)" - }, - "HTTP Content Encoding": { - "cddl": "http_content_encoding", - "description": "Encoding if any on the payload." + "cose": { + "headerFormats": { + "Catalyst ID": { + "cddl": "catalyst_id_kid", + "description": "KID (Catalyst ID URI)" + }, + "HTTP Content Encoding": { + "cddl": "http_content_encoding", + "description": "Encoding if any on the payload." + }, + "Media Type": { + "cddl": "media_type", + "description": "A Media Type string which identifies the payload." + } }, - "Media Type": { - "cddl": "media_type", - "description": "A Media Type string which identifies the payload." - } - }, - "cose_headers": { - "content type": { - "coseLabel": 3, - "description": "Media Type/s allowed in the Payload", - "format": "Media Type", - "required": "yes", - "value": [ - "application/json", - "application/schema+json", - "application/cbor", - "application/cddl" - ] + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": [ + "application/json", + "application/schema+json", + "application/cbor", + "application/cddl" + ] + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", - "format": "HTTP Content Encoding", - "required": "optional", - "value": [ - "br" - ] - } - }, - "cose_headers_order": [ - "content type", - "content-encoding" - ], - "cose_signature_headers": { - "kid": { - "coseLabel": 4, - "description": "Catalyst ID URI identifying the Public Key.\n\nThe `kid` is a UTF-8 encoded Catalyst ID URI.\nAny `kid` URI which conforms to the Catalyst ID specification may be used.\nThe Catalyst ID unambiguously defines both the signing keys and signing algorithm\nused to sign the protected portion of the document.\t\t\t", - "format": "Catalyst ID", - "required": "yes" + "headersOrder": [ + "content type", + "content-encoding" + ], + "signature_headers": { + "kid": { + "coseLabel": 4, + "description": "Catalyst ID URI identifying the Public Key.\n\nThe `kid` is a UTF-8 encoded Catalyst ID URI.\nAny `kid` URI which conforms to the Catalyst ID specification may be used.\nThe Catalyst ID unambiguously defines both the signing keys and signing algorithm\nused to sign the protected portion of the document.\t\t\t", + "format": "Catalyst ID", + "required": "yes" + } } }, "doc_clusters": { @@ -344,70 +346,60 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "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": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -459,21 +451,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -483,49 +472,42 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -582,21 +564,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -606,49 +585,42 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -705,28 +677,24 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "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": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -738,42 +706,36 @@ }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -827,21 +789,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -855,49 +814,42 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -960,21 +912,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "optional", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": [ "template" @@ -990,35 +939,30 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "optional", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -1028,14 +972,12 @@ }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1101,21 +1043,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": [ "ref", @@ -1132,7 +1071,6 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -1142,7 +1080,6 @@ }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -1152,21 +1089,18 @@ }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "optional", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "optional", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -1176,14 +1110,12 @@ }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1245,21 +1177,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -1273,49 +1202,42 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1381,21 +1303,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -1409,35 +1328,30 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -1447,14 +1361,12 @@ }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1518,21 +1430,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -1546,49 +1455,42 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1653,28 +1555,24 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "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": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -1684,42 +1582,36 @@ }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1777,21 +1669,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": [ "ref" @@ -1807,7 +1696,6 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": true, @@ -1817,42 +1705,36 @@ }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1978,21 +1860,18 @@ "metadata": { "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, "format": "Collaborators Reference List", "required": "excluded", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, "format": "Document Id", "required": "yes", "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "parameters": { "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, "format": "Document Reference", "linked_refs": [ "template" @@ -2008,35 +1887,30 @@ }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { "description": "Reference to a Comment document type being referred to.", - "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, "format": "Version Revocations", "required": "excluded", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, "format": "Section Reference", "required": "excluded", "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." }, "template": { "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, "format": "Document Reference", "linked_refs": null, "multiple": false, @@ -2046,14 +1920,12 @@ }, "type": { "description": "The document TYPE.", - "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -3289,163 +3161,155 @@ "UUIDv7": "RFC9562-V7" }, "metadata": { - "collaborators": { - "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", - "exclusive": null, - "format": "Collaborators Reference List", - "required": "optional", - "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." - }, - "id": { - "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", - "exclusive": null, - "format": "Document Id", - "required": "yes", - "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." - }, - "parameters": { - "description": "A reference to the Parameters Document this document lies under.", - "exclusive": null, - "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": [ - "Brand Parameters", - "Campaign Parameters", - "Category Parameters", - "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": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", - "exclusive": null, - "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": [ - "Proposal Meta Template", - "Proposal Template", - "Proposal", - "Proposal Comment Meta Template", - "Proposal Comment Template", - "Proposal Comment", - "Proposal Submission Action", - "Proposal Moderation Action", - "Comment Moderation Action", - "Brand Parameters", - "Campaign Parameters", - "Category Parameters", - "Decision Parameters" - ], - "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." - }, - "reply": { - "description": "Reference to a Comment document type being referred to.", - "exclusive": null, - "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": [ - "Proposal Comment" - ], - "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." - }, - "revocations": { - "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", - "exclusive": null, - "format": "Version Revocations", - "required": "excluded", - "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." - }, - "section": { - "description": "A Reference to the original document, or the comment being replied to.", - "exclusive": null, - "format": "Section Reference", - "required": "optional", - "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." - }, - "template": { - "description": "Reference to the template used to create and/or validate this document.", - "exclusive": null, - "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": [ - "Proposal Meta Template", - "Proposal Template", - "Proposal Comment Meta Template", - "Proposal Comment Template" - ], - "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." - }, - "type": { - "description": "The document TYPE.", - "exclusive": null, - "format": "Document Type", - "required": "yes", - "validation": "**MUST** be a known document type." - }, - "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", - "exclusive": null, - "format": "Document Ver", - "required": "yes", - "validation": "The document version must always be >= the document ID." - } - }, - "metadataFormats": { - "Collaborators Reference List": { - "cddl": "collaborators", - "description": "A list of collaborators who can participate in drafting and submitting a document" - }, - "Document Id": { - "cddl": "document_id", - "description": "A unique document identifier" - }, - "Document Reference": { - "cddl": "document_ref", - "description": "A document reference identifier" - }, - "Document Type": { - "cddl": "document_type", - "description": "A document type identifier" - }, - "Document Ver": { - "cddl": "document_ver", - "description": "A unique chronological document version" - }, - "Section Reference": { - "cddl": "section_ref", - "description": "A document section reference identifier" - }, - "UUIDv4": { - "cddl": "uuid_v4", - "description": "Version 4 formatted UUID" + "formats": { + "Collaborators Reference List": { + "cddl": "collaborators", + "description": "A list of collaborators who can participate in drafting and submitting a document" + }, + "Document Id": { + "cddl": "document_id", + "description": "A unique document identifier" + }, + "Document Reference": { + "cddl": "document_ref", + "description": "A document reference identifier" + }, + "Document Type": { + "cddl": "document_type", + "description": "A document type identifier" + }, + "Document Ver": { + "cddl": "document_ver", + "description": "A unique chronological document version" + }, + "Section Reference": { + "cddl": "section_ref", + "description": "A document section reference identifier" + }, + "UUIDv4": { + "cddl": "uuid_v4", + "description": "Version 4 formatted UUID" + }, + "UUIDv7": { + "cddl": "uuid_v7", + "description": "Version 7 formatted UUID" + }, + "Version Revocations": { + "cddl": "revocations", + "description": "A list of all versions of this document which are 'revoked'." + } }, - "UUIDv7": { - "cddl": "uuid_v7", - "description": "Version 7 formatted UUID" + "headers": { + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "optional", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "optional", + "type": [ + "Brand Parameters", + "Campaign Parameters", + "Category Parameters", + "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": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "optional", + "type": [ + "Proposal Meta Template", + "Proposal Template", + "Proposal", + "Proposal Comment Meta Template", + "Proposal Comment Template", + "Proposal Comment", + "Proposal Submission Action", + "Proposal Moderation Action", + "Comment Moderation Action", + "Brand Parameters", + "Campaign Parameters", + "Category Parameters", + "Decision Parameters" + ], + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "optional", + "type": [ + "Proposal Comment" + ], + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "excluded", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "optional", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "optional", + "type": [ + "Proposal Meta Template", + "Proposal Template", + "Proposal Comment Meta Template", + "Proposal Comment Template" + ], + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } }, - "Version Revocations": { - "cddl": "revocations", - "description": "A list of all versions of this document which are 'revoked'." - } - }, - "metadata_order": [ - "type", - "id", - "ver", - "ref", - "template", - "reply", - "section", - "collaborators", - "revocations", - "parameters" - ] + "order": [ + "type", + "id", + "ver", + "ref", + "template", + "reply", + "section", + "collaborators", + "revocations", + "parameters" + ] + } } From fe5576a271083ee4f833e11ecc3459d228ce6849 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 16 Jun 2025 20:18:49 +0700 Subject: [PATCH 17/42] refactor(docs): Remove last remnants of direct dict accesses. --- .../signed_doc/docs/brand_parameters.md | 2 +- .../signed_doc/docs/campaign_parameters.md | 2 +- .../signed_doc/docs/category_parameters.md | 2 +- .../docs/comment_moderation_action.md | 2 +- .../signed_doc/docs/decision_parameters.md | 2 +- .../08_concepts/signed_doc/docs/proposal.md | 2 +- .../signed_doc/docs/proposal_comment.md | 2 +- .../docs/proposal_comment_meta_template.md | 2 +- .../docs/proposal_comment_template.md | 2 +- .../signed_doc/docs/proposal_meta_template.md | 2 +- .../docs/proposal_moderation_action.md | 2 +- .../docs/proposal_submission_action.md | 2 +- .../signed_doc/docs/proposal_template.md | 2 +- .../packages/spec/src/spec/signed_doc.py | 8 ------- .../packages/spec/src/spec/signers.py | 2 +- specs/generators/src/docs/docs_page_md.py | 21 +++++++++++-------- 16 files changed, 26 insertions(+), 31 deletions(-) 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 8f2571f9e8d..1d6502d5644 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 @@ -98,7 +98,7 @@ This section will be included and updated in future iterations. ## Signers -The following user roles may sign documents of this type: +The following User roles may sign documents of this type: * Registered 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 8836c1999aa..a0280cb6169 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 @@ -116,7 +116,7 @@ This section will be included and updated in future iterations. ## Signers -The following user roles may sign documents of this type: +The following User roles may sign documents of this type: * Registered 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 7f123e98fcf..dcc4b79bb83 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 @@ -116,7 +116,7 @@ This section will be included and updated in future iterations. ## Signers -The following user roles may sign documents of this type: +The following User roles may sign documents of this type: * Registered 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 e8bd4caf859..d10c42d0030 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 @@ -139,7 +139,7 @@ This section will be included and updated in future iterations. ## Signers -The following user roles may sign documents of this type: +The following User roles may sign documents of this type: * Registered 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 dc128901baf..e4afd30cecc 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 @@ -118,7 +118,7 @@ This section will be included and updated in future iterations. ## Signers -The following user roles may sign documents of this type: +The following User roles may sign documents of this type: * Registered 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 70bffb13653..6b94c1c6b28 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md @@ -211,7 +211,7 @@ Must be valid according to the schema contained within the ## Signers -The following user roles may sign documents of this type: +The following User roles may sign documents of this type: * Proposer 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 984dd48cf34..03e1ba8bd67 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 @@ -247,7 +247,7 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Signers -The following user roles may sign documents of this type: +The following User roles may sign documents of this type: * Registered 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 73280ae4f79..237dd69341c 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 @@ -126,7 +126,7 @@ Must be a valid according to . ## Signers -The following admin roles may sign documents of this type: +The following Admin roles may sign documents of this type: * Root Admin * Brand Admin 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 ff64f268527..c745e396174 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 @@ -139,7 +139,7 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Signers -The following admin roles may sign documents of this type: +The following Admin roles may sign documents of this type: * Brand Admin * Campaign Admin 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 dd91bf81851..bf2fb508bbf 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 @@ -126,7 +126,7 @@ Must be a valid according to . ## Signers -The following admin roles may sign documents of this type: +The following Admin roles may sign documents of this type: * Root Admin * Brand Admin 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 8792ac43684..2c114548600 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 @@ -139,7 +139,7 @@ This section will be included and updated in future iterations. ## Signers -The following user roles may sign documents of this type: +The following User roles may sign documents of this type: * Registered 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 e15b76b4be6..13669d7ce39 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 @@ -302,7 +302,7 @@ States: ## Signers -The following user roles may sign documents of this type: +The following User roles may sign documents of this type: * Proposer 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 53ac87aff1b..973f081c251 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 @@ -143,7 +143,7 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Signers -The following admin roles may sign documents of this type: +The following Admin roles may sign documents of this type: * Brand Admin * Campaign Admin diff --git a/specs/generators/packages/spec/src/spec/signed_doc.py b/specs/generators/packages/spec/src/spec/signed_doc.py index fdf301e28e6..30cfc01dfde 100644 --- a/specs/generators/packages/spec/src/spec/signed_doc.py +++ b/specs/generators/packages/spec/src/spec/signed_doc.py @@ -3,7 +3,6 @@ # Autogenerate Documentation Pages from the formal specification import datetime -import json import typing from pathlib import Path @@ -41,7 +40,6 @@ class SignedDoc(BaseModel): metadata: Metadata form_template: FormTemplate = Field(alias="formTemplate") - _data: dict[str, typing.Any] = PrivateAttr(default_factory=dict[str, typing.Any]) _file: str = PrivateAttr(default="Uninitialized") model_config = ConfigDict(extra="forbid") @@ -52,8 +50,6 @@ def load(cls, spec_file: str) -> typing.Self: with Path(spec_file).open("r") as f: raw_json = f.read() doc = cls.model_validate_json(raw_json, strict=True) - data: dict[str, typing.Any] = json.loads(raw_json) - doc._data = data # noqa: SLF001 doc._file = spec_file # noqa: SLF001 return doc @@ -89,10 +85,6 @@ def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 ] ) - def data(self) -> dict[str, typing.Any]: - """Return the raw spec data.""" - return self._data - def get_copyright( self, document_name: str | None, diff --git a/specs/generators/packages/spec/src/spec/signers.py b/specs/generators/packages/spec/src/spec/signers.py index e594d589ab5..475984fb967 100644 --- a/specs/generators/packages/spec/src/spec/signers.py +++ b/specs/generators/packages/spec/src/spec/signers.py @@ -27,6 +27,6 @@ class Signers(BaseModel): roles: AllowedRoles referenced: bool = Field(default=False) - update: AllowedUpdaters + update: dict[str, bool] model_config = ConfigDict(extra="forbid") diff --git a/specs/generators/src/docs/docs_page_md.py b/specs/generators/src/docs/docs_page_md.py index b1b546707c1..7223fb0e596 100644 --- a/specs/generators/src/docs/docs_page_md.py +++ b/specs/generators/src/docs/docs_page_md.py @@ -50,7 +50,7 @@ def header_parameter_summary(self) -> str: for header in headers.names: value = headers.get(header).value if isinstance(value, list): - value = f"[{','.join(value)}]" # noqa: PLW2901 + value = f"[{','.join(value)}]" link = f"../spec.md#{header.replace(' ', '-')}" header_docs += f"* [{header}]({link}) = `{value}`\n" return header_docs.strip() @@ -64,21 +64,24 @@ def document_payload(self) -> str: def document_signers(self) -> str: """Generate documentation about who may sign this documents.""" - signers = self._spec.data()["docs"][self._document_name]["signers"] - signers_doc = "" + signers = self._spec.docs.get(self._document_name).signers + signers_doc: str = "" - for role_group in signers["roles"]: - roles = signers["roles"][role_group] - if roles: - signers_doc += f"\nThe following {role_group} roles may sign documents of this type:\n\n" + def add_role_group(name: str, roles: list[str]) -> None: + nonlocal signers_doc + if len(roles) > 0: + signers_doc += f"\nThe following {name} roles may sign documents of this type:\n\n" for role in roles: signers_doc += f"* {role}\n" + add_role_group("User", signers.roles.user) + add_role_group("Admin", signers.roles.admin) + signers_doc = signers_doc.strip() signers_doc += "\n\nNew versions of this document may be published by:\n\n" - for updater in signers["update"]: - if signers["update"][updater]: + for updater in signers.update: + if signers.update[updater]: signers_doc += f"* {updater}\n" return signers_doc.strip() From f9b35dbf58c54a2857b4d27d8465f1ab94eb539c Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 16 Jun 2025 21:03:43 +0700 Subject: [PATCH 18/42] refactor(docs): remove code obsoleted by refactor --- specs/generators/src/docs/cddl_file.py | 49 -------------------------- 1 file changed, 49 deletions(-) diff --git a/specs/generators/src/docs/cddl_file.py b/specs/generators/src/docs/cddl_file.py index 2269638f6b7..fb4517542fc 100644 --- a/specs/generators/src/docs/cddl_file.py +++ b/specs/generators/src/docs/cddl_file.py @@ -8,21 +8,6 @@ from .doc_generator import DocGenerator -def x_add_cddl_comments(comment: str) -> tuple[str, bool]: - """Add cddl comment markers to lines. - - Returns True if more than 1 line. - """ - comment = comment.strip() - comment_lines = comment.splitlines() - comment = "" - for line in comment_lines: - comment += f"; {line}\n" - comment = comment.strip() - - return comment, len(comment_lines) > 0 - - class CDDLFile(DocGenerator): """Generate a CDDL File.""" @@ -33,40 +18,6 @@ def __init__(self, args: argparse.Namespace, spec: SignedDoc, cddl_root: str) -> super().__init__(args, spec, file_name, flags=self.NO_FLAGS) self._cddl_root = cddl_root - def x_get_cddl(self, name: str, found: list[str] | None = None) -> tuple[str, list[str]]: - """Get the CDDL for a metadatum.""" - if found is None: - found = [] - - this_cddl = "" - this_def = self._spec.cddl_definitions.get(name) - cddl_def = this_def.definition.strip() - cddl_def_multiline = len(cddl_def.splitlines()) > 1 - - # Add required definitions to this one (recursive) - for requires in this_def.requires: - if requires not in found: - next_cddl, found = self.get_cddl(requires, found) - found.append(requires) - this_cddl += next_cddl - - comment: str = this_def.get("comment", "") - leading_comment = "" - if len(comment) > 0: - comment, multiline = add_cddl_comments(comment) - if multiline or cddl_def_multiline: - leading_comment = comment - comment = "\n" # Adds a blank line after defs with multiline comments - - this_cddl = f""" -{leading_comment} -{name} = {cddl_def} {comment} - -{this_cddl} -""" - - return this_cddl, found - def markdown_reference(self, *, indent: int = 0, relative_doc: DocGenerator | None = None) -> str: """Create a Markdown formatted reference for the CDDL file.""" file_path = self.file_path(relative_doc) From b61fb3805429d4be9e1181eb9a7ee3c2a62be2a7 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 19 Jun 2025 21:57:58 +0700 Subject: [PATCH 19/42] refactor(docs): large cue refactor to stuff that should be common --- .config/dictionaries/project.dic | 3 + .../signed_doc/cddl/signed_document.cddl | 17 +- .../docs/proposal_comment_meta_template.md | 4 +- .../docs/proposal_comment_template.md | 4 +- .../signed_doc/docs/proposal_meta_template.md | 4 +- .../signed_doc/docs/proposal_template.md | 4 +- .../schema/template_example.schema.json | 10 +- .../08_concepts/signed_doc/spec.md | 94 ++++++++-- specs/definitions/documentation/link_aka.cue | 61 +++++++ specs/definitions/documentation/links.cue | 69 ++++++++ specs/definitions/form_template/choices.cue | 6 +- specs/definitions/form_template/field.cue | 5 +- .../fields/drop_down_single_select.cue | 7 +- .../fields/multi_line_text_entry.cue | 7 +- .../fields/multi_line_text_entry_markdown.cue | 9 +- .../fields/radio_button_select.cue | 7 +- .../fields/single_line_https_url_entry.cue | 7 +- .../fields/single_line_text_entry.cue | 7 +- specs/definitions/form_template/patterns.cue | 6 - specs/definitions/generic/url.cue | 15 ++ specs/definitions/media_types/content.cue | 135 ++++++++++++++ specs/definitions/media_types/encoding.cue | 18 ++ specs/definitions/regex/def.cue | 41 +++++ specs/definitions/regex/regex.cue | 14 ++ specs/definitions/signed_docs/cddl_defs.cue | 15 +- .../definitions/signed_docs/cose_headers.cue | 103 +---------- .../signed_docs/cose_signed_doc_cddl_defs.cue | 5 +- .../signed_docs/docs/brand_parameters.cue | 2 + .../signed_docs/docs/campaign_parameters.cue | 1 + .../signed_docs/docs/category_parameters.cue | 2 + .../docs/comment_moderation_action.cue | 1 + .../signed_docs/docs/decision_parameters.cue | 1 + .../definitions/signed_docs/docs/proposal.cue | 1 + .../signed_docs/docs/proposal_comment.cue | 3 + .../docs/proposal_moderation_action.cue | 1 + .../docs/proposal_submission_action.cue | 3 + .../definitions/signed_docs/documentation.cue | 16 ++ .../signed_docs/documentation_links.cue | 53 ------ .../spec/src/spec/documentation_links.py | 22 ++- .../packages/spec/src/spec/signed_doc.py | 8 +- specs/generators/pyproject.toml | 4 +- specs/generators/src/docs/doc_generator.py | 20 ++- specs/generators/src/docs/spec_md.py | 5 +- specs/generators/uv.lock | 89 ++++++++++ specs/signed_doc.json | 166 ++++++++++++------ 45 files changed, 796 insertions(+), 279 deletions(-) create mode 100644 specs/definitions/documentation/link_aka.cue create mode 100644 specs/definitions/documentation/links.cue delete mode 100644 specs/definitions/form_template/patterns.cue create mode 100644 specs/definitions/generic/url.cue create mode 100644 specs/definitions/media_types/content.cue create mode 100644 specs/definitions/media_types/encoding.cue create mode 100644 specs/definitions/regex/def.cue create mode 100644 specs/definitions/regex/regex.cue create mode 100644 specs/definitions/signed_docs/documentation.cue delete mode 100644 specs/definitions/signed_docs/documentation_links.cue diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index b92e54d10ba..7977585af58 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -4,6 +4,7 @@ ABNF addrr addrs adminer +admon anypolicy apskhem Arissara @@ -160,6 +161,8 @@ ltail maindbname mapref markdownlint +mdformat +mdit mdlint mdns MEMMAP diff --git a/docs/src/architecture/08_concepts/signed_doc/cddl/signed_document.cddl b/docs/src/architecture/08_concepts/signed_doc/cddl/signed_document.cddl index 8e913b368e6..56776f67508 100644 --- a/docs/src/architecture/08_concepts/signed_doc/cddl/signed_document.cddl +++ b/docs/src/architecture/08_concepts/signed_doc/cddl/signed_document.cddl @@ -37,14 +37,23 @@ COSE_Document_Standard_Headers = ( ) ; Supported Content Media Types. -; If uint is used, only CoAP Content Formats that match the string format are allowed. +; If the Media Type is supported by COAP, then the `uint` CoAP encoded +; version of the media type must be used, in preference to the string. media_type = ( - (uint .eq (50 / 60)) / + (uint .eq (0 / 50 / 60 / 20000)) / (tstr .eq ( + "application/cbor" / + "application/cddl" / "application/json" / "application/schema+json" / - "application/cbor" / - "application/cddl" + "text/css; charset=utf-8" / + "text/css; charset=utf-8; template=handlebars" / + "text/html; charset=utf-8" / + "text/html; charset=utf-8; template=handlebars" / + "text/markdown; charset=utf-8" / + "text/markdown; charset=utf-8; template=handlebars" / + "text/plain; charset=utf-8" / + "text/plain; charset=utf-8; template=handlebars" )) ) 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 237dd69341c..e6849b7326c 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 @@ -116,7 +116,7 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Payload -[JSON Schema] document which ensures the minimum required functional requirements +[JSON Schema][JSON Schema-2020-12] document which ensures the minimum required functional requirements of the Proposal Comment Template are met. This ensures that payloads can be reliably interpreted by business logic processes, @@ -156,6 +156,6 @@ New versions of this document may be published by: * Use generalized parameters. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[JSON Schema]: https://json-schema.org/draft-07 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode [RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md index c745e396174..199b7712ce8 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 @@ -135,7 +135,7 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Payload -[JSON Schema] document which defines the content of the Proposal Comments. +[JSON Schema][JSON Schema-2020-12] document which defines the content of the Proposal Comments. ## Signers @@ -169,6 +169,6 @@ New versions of this document may be published by: * Use generalized parameters. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[JSON Schema]: https://json-schema.org/draft-07 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode [RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md index bf2fb508bbf..548fc99844c 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 @@ -116,7 +116,7 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Payload -[JSON Schema] document which ensures the minimum required functional requirements +[JSON Schema][JSON Schema-2020-12] document which ensures the minimum required functional requirements of the Proposal Template are met. This ensures that payloads can be reliably interpreted by business logic processes, @@ -156,6 +156,6 @@ New versions of this document may be published by: * Use generalized parameters. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[JSON Schema]: https://json-schema.org/draft-07 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode [RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md index 973f081c251..babbed81734 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 @@ -139,7 +139,7 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Payload -[JSON Schema] document which defines the valid contents of a proposal document. +[JSON Schema][JSON Schema-2020-12] document which defines the valid contents of a proposal document. ## Signers @@ -173,6 +173,6 @@ New versions of this document may be published by: * Use generalized parameters. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[JSON Schema]: https://json-schema.org/draft-07 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode [RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/schema/template_example.schema.json b/docs/src/architecture/08_concepts/signed_doc/schema/template_example.schema.json index 68c3e6cd678..29bd6010ed6 100644 --- a/docs/src/architecture/08_concepts/signed_doc/schema/template_example.schema.json +++ b/docs/src/architecture/08_concepts/signed_doc/schema/template_example.schema.json @@ -11,7 +11,7 @@ "$defs": { "dropDownSingleSelect": { "contentMediaType": "text/plain", - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "multiLineTextEntry": { @@ -36,7 +36,7 @@ }, "multiSelect": { "items": { - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "type": "array", @@ -44,7 +44,7 @@ }, "radioButtonSelect": { "contentMediaType": "text/plain", - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "schemaReferenceNonUI": { @@ -83,13 +83,13 @@ "uniqueItems": true }, "singleLineTextEntry": { - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "singleLineTextEntryList": { "items": { "minLength": 1, - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "type": "array", diff --git a/docs/src/architecture/08_concepts/signed_doc/spec.md b/docs/src/architecture/08_concepts/signed_doc/spec.md index 222eff96a07..b61bcb00a20 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec.md +++ b/docs/src/architecture/08_concepts/signed_doc/spec.md @@ -98,15 +98,78 @@ Media Type/s allowed in the Payload * [Cose][RFC9052] Label : 3 * Format : Media Type * Supported Values: - * [application/json] : [JSON][RFC8259] Document - * [application/schema+json] : [JSON Schema] Draft 7 Document; Note: - * This is currently an unofficial media type. - * Draft 7 is used because of its wide support by tooling. - * [application/cbor] : [RFC8949] Binary [CBOR][RFC8949] Encoded Document - * application/cddl : [CDDL][RFC8610] Document; Note: + * [application/cbor] : + An [RFC8949] Binary [CBOR][RFC8949] Encoded Document. + * [application/cddl][RFC8610] : + A [CDDL][RFC8610] Document. + + Note: + * This is an unofficial media type * [RFC9165] Additional Control Operators for [CDDL][RFC8610] are supported. * Must not have Modules, schema must be self-contained. + * [application/json] : + [JSON][RFC8259] Document + * [application/schema+json][JSON Schema-2020-12] : + A [JSON Schema Draft 2020-12][JSON Schema-2020-12] Document. + + Note: + + * This is currently an unofficial media type. + * [text/css;][text/css] [charset=utf-8][RFC3629] : + [CSS] Content used for styling [HTML][HTML5]. + [CSS] should use the least set of features possible to achieve + the desired presentation to ensure the broadest compatibility. + * [text/css;][text/css] [charset=utf-8;][RFC3629] [template=handlebars][Handlebars] : + [CSS] Content used for styling [HTML][HTML5]. + [CSS] should use the least set of features possible to achieve + the desired presentation to ensure the broadest compatibility. + + The text includes [Handlebars] type template fields that need + processing and replacement prior to display. + * [text/html;][HTML5] [charset=utf-8][RFC3629] : + Formatted text using [HTML5] markup for rich text. + Only [HTML5] syntax is supported. + * [text/html;][HTML5] [charset=utf-8;][RFC3629] [template=handlebars][Handlebars] : + Formatted text using [HTML5] markup for rich text. + Only [HTML5] syntax is supported. + + The text includes [Handlebars] type template fields that need + processing and replacement prior to display. + * [text/markdown;][CommonMark] [charset=utf-8][RFC3629] : + Formatted text using [Markdown][CommonMark] for rich text. + [Markdown][CommonMark] formatting is as defined by [CommonMark]. + + IF the document includes HTML, then [HTML5] syntax only is supported. + + The following [Markdown][CommonMark] Extensions are also supported: + + * None + * [text/markdown;][CommonMark] [charset=utf-8;][RFC3629] [template=handlebars][Handlebars] : + Formatted text using [Markdown][CommonMark] for rich text. + [Markdown][CommonMark] formatting is as defined by [CommonMark]. + + IF the document includes HTML, then [HTML5] syntax only is supported. + + The following [Markdown][CommonMark] Extensions are also supported: + + * None + + The text includes [Handlebars] type template fields that need + processing and replacement prior to display. + * [text/plain;][text/plain] [charset=utf-8][RFC3629] : + Plain Text with no markup or special formatting. + Multiline Plain Text *MUST* always interpret ` + ` + as a hard line break. + * [text/plain;][text/plain] [charset=utf-8;][RFC3629] [template=handlebars][Handlebars] : + Plain Text with no markup or special formatting. + Multiline Plain Text *MUST* always interpret ` + ` + as a hard line break. + + The text includes [Handlebars] type template fields that need + processing and replacement prior to display. #### `content-encoding` @@ -117,12 +180,12 @@ If no compression or encoding is used, then this field must not be present. * [Cose][RFC9052] Label : content-encoding ***Custom Header*** * Format : HTTP Content Encoding * Supported Values: - * [br] : [BROTLI][RFC7932] Compression + * [br] : + [BROTLI][RFC7932] Compression ### Metadata -Catalyst Signed Documents extend the Header Parameters with a series of Metadata fields. -These fields are defined [here](./metadata.md). +Catalyst Signed Documents extend the Header Parameters with a series of [Metadata fields](./metadata.md). ### Signing Catalyst Signed Documents @@ -181,19 +244,24 @@ used to sign the protected portion of the document. * 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/ +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[Handlebars]: https://handlebarsjs.com/ +[RFC8610]: https://www.rfc-editor.org/rfc/rfc8610 [application/cbor]: https://www.iana.org/assignments/media-types/application/cbor [application/json]: https://www.iana.org/assignments/media-types/application/json -[JSON Schema]: https://json-schema.org/draft-07 +[RFC3629]: https://datatracker.ietf.org/doc/html/rfc3629 +[CommonMark]: https://spec.commonmark.org/0.31.2/ +[text/plain]: https://www.rfc-editor.org/rfc/rfc2046.html +[HTML5]: https://html.spec.whatwg.org/multipage/syntax.html#syntax [RFC9052-CoseSign]: https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si +[text/css]: https://www.rfc-editor.org/rfc/rfc2318.html [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode [RFC8949]: https://www.rfc-editor.org/rfc/rfc8949.html [RFC9165]: https://www.rfc-editor.org/rfc/rfc9165 [RFC7932]: https://www.rfc-editor.org/rfc/rfc7932 -[RFC3629]: https://datatracker.ietf.org/doc/html/rfc3629 -[RFC8610]: https://www.rfc-editor.org/rfc/rfc8610 [RFC9052]: https://datatracker.ietf.org/doc/html/rfc9052 [RFC8259]: https://www.rfc-editor.org/rfc/rfc8259.html [RFC3986]: https://datatracker.ietf.org/doc/html/rfc3986 +[CSS]: https://www.w3.org/Style/CSS/ [br]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br diff --git a/specs/definitions/documentation/link_aka.cue b/specs/definitions/documentation/link_aka.cue new file mode 100644 index 00000000000..cb6d59f82b4 --- /dev/null +++ b/specs/definitions/documentation/link_aka.cue @@ -0,0 +1,61 @@ +package documentation + +import ( + "list" +) + +#linkAKAName: string + +linkAKA: [#linkAKAName]: #allLinkNames + +// Known aliases for links. Lets us automatically create [Named Link][Reference Link] +linkAKA: { + UUIDv7: "RFC9562-V7" + UUIDv4: "RFC9562-V4" + UUID: "RFC9562" + URI: "RFC3986" + "UTF-8": "RFC3629" + "CBOR Encoded IPLD Content Identifier": "CBOR-TAG-42" + "IPFS CID": "IPFS-CID" + "CBOR Deterministic Encoding": "CBOR-LFD-ENCODING" + BROTLI: "RFC7932" + JSON: "RFC8259" + CDDL: "RFC8610" + CBOR: "RFC8949" + COSE: "RFC9052" + "COSE Sign": "RFC9052-CoseSign" + "COSE Header Parameters": "RFC9052-HeaderParameters" + "RFC9165 - CDDL Additional Controls": "RFC9165" + "text/plain;": "text/plain" + "text/markdown;": "CommonMark" + "text/html;": "HTML5" + "text/css;": "text/css" + "charset=utf-8": "RFC3629" + "charset=utf-8;": "RFC3629" + "template=handlebars": "Handlebars" + "application/schema+json": "JSON Schema-2020-12" + "application/cddl": "RFC8610" + "JSON Schema Draft 2020-12": "JSON Schema-2020-12" + Markdown: "CommonMark" + HTML: "HTML5" + "JSON Schema": "JSON Schema-2020-12" +} + +all_aka_names: list.UniqueItems +all_aka_names: list.Sort([ + for k, _ in linkAKA {k}, +], list.Ascending) + +// Reports incompatible list length if we have a link name match an aka name. +aka_not_in_names: [] +aka_not_in_names: [ + for n in all_aka_names if list.Contains(all_link_names, n) {n}, +] + +all_link_and_aka_names: list.UniqueItems +all_link_and_aka_names: list.Sort( + list.Concat( + [all_link_names, all_aka_names], + ), list.Ascending) + +#allLinkAndAKANames: or(all_link_and_aka_names) diff --git a/specs/definitions/documentation/links.cue b/specs/definitions/documentation/links.cue new file mode 100644 index 00000000000..6e2676455c2 --- /dev/null +++ b/specs/definitions/documentation/links.cue @@ -0,0 +1,69 @@ +// External Documentation related definitions +// Links +package documentation + +import ( + "list" + "strings" + "github.com/input-output-hk/catalyst-libs/specs/generic:url" +) + +// A named Link to an external document, this would be encoded into markdown as: +// [name]: url +#docLinks: [string]: url.#absHttpsUrl + +links: #docLinks & { + "application/json": "https://www.iana.org/assignments/media-types/application/json" + "application/cbor": "https://www.iana.org/assignments/media-types/application/cbor" + br: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br" + "JSON Schema-draft7": "https://json-schema.org/draft-07" + "JSON Schema-2020-12": "https://json-schema.org/draft/2020-12" + RFC7932: "https://www.rfc-editor.org/rfc/rfc7932" // Brotli + RFC8259: "https://www.rfc-editor.org/rfc/rfc8259.html" // JSON + RFC8610: "https://www.rfc-editor.org/rfc/rfc8610" // CDDL + RFC8949: "https://www.rfc-editor.org/rfc/rfc8949.html" // CBOR + RFC9052: "https://datatracker.ietf.org/doc/html/rfc9052" // COSE + "RFC9052-CoseSign": "https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si" // COSE Multiple Signers + "RFC9052-HeaderParameters": "https://www.rfc-editor.org/rfc/rfc8152#section-3.1" // COSE Header Parameters + RFC9165: "https://www.rfc-editor.org/rfc/rfc9165" // CDDL Additional Controls + CommonMark: "https://spec.commonmark.org/0.31.2/" + 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 + Handlebars: "https://handlebarsjs.com/" + Mustache: "https://mustache.github.io/mustache.5.html" + HTML5: "https://html.spec.whatwg.org/multipage/syntax.html#syntax" + CSS: "https://www.w3.org/Style/CSS/" + "text/plain": "https://www.rfc-editor.org/rfc/rfc2046.html" + "text/css": "https://www.rfc-editor.org/rfc/rfc2318.html" +} + +// Constrains the URLs being linked to be unique +#uniqueLinkValues: list.UniqueItems +#uniqueLinkValues: [...url.#absHttpsUrl] & [ + for _, v in links {v}, +] + +all_links: list.UniqueItems +all_links: [...url.#absHttpsUrl] & list.Sort([ + for _, v in links {v}, +], list.Ascending) + +#allLinks: or(all_links) + +#linkName: string +#linkName: strings.MinRunes(2) + +all_link_names: list.UniqueItems +all_link_names: [...#linkName] & list.Sort([ + for k, _ in links {k}, +], list.Ascending) + +#allLinkNames: or(all_link_names) diff --git a/specs/definitions/form_template/choices.cue b/specs/definitions/form_template/choices.cue index 54b91c542c8..0c8a991c2da 100644 --- a/specs/definitions/form_template/choices.cue +++ b/specs/definitions/form_template/choices.cue @@ -18,11 +18,11 @@ _allFormats: list.Sort([ _allContentMediaTypes: list.UniqueItems _allContentMediaTypes: list.Sort([ "text/plain", - "text/plain; template=mustache", + "text/plain; template=handlebars", "text/markdown", - "text/markdown; template=mustache", + "text/markdown; template=handlebars", "text/html", - "text/html; template=mustache", + "text/html; template=handlebars", ], list.Ascending) #contentMediaTypeChoices: or(_allContentMediaTypes) diff --git a/specs/definitions/form_template/field.cue b/specs/definitions/form_template/field.cue index d679d06ac7a..ad42a6e406b 100644 --- a/specs/definitions/form_template/field.cue +++ b/specs/definitions/form_template/field.cue @@ -2,7 +2,8 @@ package form_template import ( - "regexp" + "github.com/input-output-hk/catalyst-libs/specs/regex" + ) // Schema Definition for the Form Element. @@ -44,7 +45,7 @@ import ( if type == "string" { format?: #formatChoices contentMediaType?: #contentMediaTypeChoices - pattern?: regexp.Valid + pattern?: regex.#regex minLength?: int // Only to enforce that the field can not be empty (such as when used in lists) } diff --git a/specs/definitions/form_template/fields/drop_down_single_select.cue b/specs/definitions/form_template/fields/drop_down_single_select.cue index a21d0cc7c64..7744d4793f7 100644 --- a/specs/definitions/form_template/fields/drop_down_single_select.cue +++ b/specs/definitions/form_template/fields/drop_down_single_select.cue @@ -2,6 +2,11 @@ package form_template +import ( + "github.com/input-output-hk/catalyst-libs/specs/regex" + +) + dictionary: #formTemplate & { dropDownSingleSelect: { description: """ @@ -14,7 +19,7 @@ dictionary: #formTemplate & { definition: { type: "string" contentMediaType: "text/plain" - pattern: _regexTextSingleLine + pattern: regex.def.singleLine.pattern } parameters: { title: {} diff --git a/specs/definitions/form_template/fields/multi_line_text_entry.cue b/specs/definitions/form_template/fields/multi_line_text_entry.cue index 2840e760e9d..f9db14d945d 100644 --- a/specs/definitions/form_template/fields/multi_line_text_entry.cue +++ b/specs/definitions/form_template/fields/multi_line_text_entry.cue @@ -1,6 +1,11 @@ // Single Line Text Entry package form_template +import ( + "github.com/input-output-hk/catalyst-libs/specs/regex" + +) + dictionary: #formTemplate & { multiLineTextEntry: { description: """ @@ -14,7 +19,7 @@ dictionary: #formTemplate & { definition: { type: "string" contentMediaType: "text/plain" - pattern: _regexTextMultiLine + pattern: regex.def.multiLine.pattern } parameters: { title: {} diff --git a/specs/definitions/form_template/fields/multi_line_text_entry_markdown.cue b/specs/definitions/form_template/fields/multi_line_text_entry_markdown.cue index 3d06bd7ca04..5a231e9a189 100644 --- a/specs/definitions/form_template/fields/multi_line_text_entry_markdown.cue +++ b/specs/definitions/form_template/fields/multi_line_text_entry_markdown.cue @@ -1,12 +1,17 @@ // Single Line Text Entry package form_template +import ( + "github.com/input-output-hk/catalyst-libs/specs/regex" + +) + dictionary: #formTemplate & { multiLineTextEntryMarkdown: { description: """ UI - Multiline text entry with Markdown content. Use Markdown formatting for rich text. - Markdown formatting is as defined by + Markdown formatting is as defined by CommonMark. The following Markdown Extensions are also supported: @@ -15,7 +20,7 @@ dictionary: #formTemplate & { definition: { type: "string" contentMediaType: "text/markdown" - pattern: _regexTextMultiLine + pattern: regex.def.multiLine.pattern } parent: "section" parameters: { diff --git a/specs/definitions/form_template/fields/radio_button_select.cue b/specs/definitions/form_template/fields/radio_button_select.cue index 4c28c4c3818..f45547c9a4c 100644 --- a/specs/definitions/form_template/fields/radio_button_select.cue +++ b/specs/definitions/form_template/fields/radio_button_select.cue @@ -2,6 +2,11 @@ package form_template +import ( + "github.com/input-output-hk/catalyst-libs/specs/regex" + +) + dictionary: #formTemplate & { radioButtonSelect: { description: """ @@ -15,7 +20,7 @@ dictionary: #formTemplate & { definition: { type: "string" contentMediaType: "text/plain" - pattern: _regexTextSingleLine + pattern: regex.def.singleLine.pattern } parameters: { title: {} diff --git a/specs/definitions/form_template/fields/single_line_https_url_entry.cue b/specs/definitions/form_template/fields/single_line_https_url_entry.cue index f9fd59be6a9..4d3cc7118ea 100644 --- a/specs/definitions/form_template/fields/single_line_https_url_entry.cue +++ b/specs/definitions/form_template/fields/single_line_https_url_entry.cue @@ -1,6 +1,11 @@ // Single Line HTTPS URL Text Entry package form_template +import ( + "github.com/input-output-hk/catalyst-libs/specs/regex" + +) + dictionary: #formTemplate & { singleLineHttpsURLEntry: { description: """ @@ -15,7 +20,7 @@ dictionary: #formTemplate & { definition: { type: "string" format: "uri" - pattern: _regexHTTPSUrl + pattern: regex.def.httpsUrl.pattern } parameters: { title: {} diff --git a/specs/definitions/form_template/fields/single_line_text_entry.cue b/specs/definitions/form_template/fields/single_line_text_entry.cue index d79b8b397cf..cd9a0899eec 100644 --- a/specs/definitions/form_template/fields/single_line_text_entry.cue +++ b/specs/definitions/form_template/fields/single_line_text_entry.cue @@ -1,6 +1,11 @@ // Single Line Text Entry package form_template +import ( + "github.com/input-output-hk/catalyst-libs/specs/regex" + +) + dictionary: #formTemplate & { singleLineTextEntry: { description: """ @@ -12,7 +17,7 @@ dictionary: #formTemplate & { definition: { type: "string" - pattern: _regexTextSingleLine + pattern: regex.def.singleLine.pattern } parameters: { title: {} diff --git a/specs/definitions/form_template/patterns.cue b/specs/definitions/form_template/patterns.cue deleted file mode 100644 index 3079fea973e..00000000000 --- a/specs/definitions/form_template/patterns.cue +++ /dev/null @@ -1,6 +0,0 @@ -// Regex patterns that are defined. -package form_template - -_regexTextSingleLine: #"^.*$"# -_regexTextMultiLine: #"^[\S\s]*$"# -_regexHTTPSUrl: #"^https://[^\s]+$"# diff --git a/specs/definitions/generic/url.cue b/specs/definitions/generic/url.cue new file mode 100644 index 00000000000..fec80fa13fc --- /dev/null +++ b/specs/definitions/generic/url.cue @@ -0,0 +1,15 @@ +package url + +import ( + "net" + "github.com/input-output-hk/catalyst-libs/specs/regex" +) + +#absUrl: string +#absUrl: net.AbsURL + +#absHttpsUrl: #absUrl +#absHttpsUrl: =~regex.def.httpsUrl.pattern + +#relativeUrl: string +#relativeUrl: net.URL diff --git a/specs/definitions/media_types/content.cue b/specs/definitions/media_types/content.cue new file mode 100644 index 00000000000..0650303f189 --- /dev/null +++ b/specs/definitions/media_types/content.cue @@ -0,0 +1,135 @@ +// Content and Encoding Types +package media_types + +import ( + "list" +) + +// Content Type name : Description +#contentTypes: { + [string]: { + description: string // description of the content type + coap_type?: int + } +} + +_plaintext_description: """ + Plain Text with no markup or special formatting. + Multiline Plain Text *MUST* always interpret `\n` + as a hard line break. + """ + +_markdown_description: """ + Formatted text using Markdown for rich text. + Markdown formatting is as defined by CommonMark. + + IF the document includes HTML, then HTML5 syntax only is supported. + + The following Markdown Extensions are also supported: + + * None + """ + +_html_description: """ + Formatted text using HTML5 markup for rich text. + Only HTML5 syntax is supported. + """ + +_css_description: """ + CSS Content used for styling HTML. + CSS should use the least set of features possible to achieve + the desired presentation to ensure the broadest compatibility. + """ + +_handlebars_template_description: """ + The text includes Handlebars type template fields that need + processing and replacement prior to display. + """ + +contentTypes: #contentTypes & { + "application/json": { + description: "JSON Document" + coap_type: 50 + } + "application/schema+json": description: """ + A JSON Schema Draft 2020-12 Document. + + Note: + + * This is currently an unofficial media type. + """ + "application/cbor": { + description: "An RFC8949 Binary CBOR Encoded Document." + coap_type: 60 + } + "application/cddl": description: """ + A CDDL Document. + + Note: + + * This is an unofficial media type + * RFC9165 Additional Control Operators for CDDL are supported. + * Must not have Modules, schema must be self-contained. + """ + "text/plain; charset=utf-8": { + description: """ + \(_plaintext_description) + """ + coap_type: 0 + } + "text/plain; charset=utf-8; template=handlebars": description: """ + \(_plaintext_description) + + \(_handlebars_template_description) + """ + "text/markdown; charset=utf-8": description: """ + \(_markdown_description) + """ + "text/markdown; charset=utf-8; template=handlebars": description: """ + \(_markdown_description) + + \(_handlebars_template_description) + """ + "text/html; charset=utf-8": description: """ + \(_html_description) + """ + "text/html; charset=utf-8; template=handlebars": description: """ + \(_html_description) + + \(_handlebars_template_description) + """ + "text/css; charset=utf-8": { + description: """ + \(_css_description) + """ + coap_type: 20000 + } + "text/css; charset=utf-8; template=handlebars": description: """ + \(_css_description) + + \(_handlebars_template_description) + """ +} + +allContentTypes: list.Sort([ + for k, _ in contentTypes {k}, +], list.Ascending) + +#contentType: or(allContentTypes) + +coapTypes: { + for k, v in contentTypes + if v.coap_type != _|_ { + "\(v.coap_type)": k + } +} + +allCoapTypes: list.UniqueItems +allCoapTypes: list.Sort([ + for _, v in contentTypes if v.coap_type != _|_ {v.coap_type}, +], list.Ascending) + +#allCoapTypes: or(allCoapTypes) + +allCoapTypesStr: [...string] +allCoapTypesStr: [for v in allCoapTypes {"\(v)"}] diff --git a/specs/definitions/media_types/encoding.cue b/specs/definitions/media_types/encoding.cue new file mode 100644 index 00000000000..c813a241ed1 --- /dev/null +++ b/specs/definitions/media_types/encoding.cue @@ -0,0 +1,18 @@ +// Content and Encoding Types +package media_types + +import ( + "list" +) + +// Content Encoding Type name : Description +encodingTypes: { + [string]: { + description: string // description of the content type + } +} +encodingTypes: br: description: "BROTLI Compression" + +allContentEncoding: list.Sort([ + for k, _ in encodingTypes {k}, +], list.Ascending) diff --git a/specs/definitions/regex/def.cue b/specs/definitions/regex/def.cue new file mode 100644 index 00000000000..37b660e6b23 --- /dev/null +++ b/specs/definitions/regex/def.cue @@ -0,0 +1,41 @@ +// Regex Definitions +package regex + +def: #def & { + singleLine: { + pattern: #"^[^\n]*$"# + description: "Single Line of Text" + } + multiLine: { + pattern: #"^[\S\s]*$"# + description: "Multiline Text" + } + httpsUrl: { + pattern: #"^https://[^\s]+$"# + description: "A URL that must begin with https://" + } +} + +// Every definition above MUST have at least one test below +// for the positive and negative match. +positive_match: true + +positive_match: "" =~ def.singleLine.pattern +positive_match: "single line" =~ def.singleLine.pattern + +positive_match: "single line" =~ def.multiLine.pattern +positive_match: "multi\nline" =~ def.multiLine.pattern +positive_match: "" =~ def.multiLine.pattern + +positive_match: "https://www.iana.org/assignments" =~ def.httpsUrl.pattern + +// Negative match (where possible to test) +negative_match: false + +negative_match: "multi\nline" =~ def.singleLine.pattern + +// No negative multiline regex cases. Regex too simple. + +negative_match: "" =~ def.httpsUrl.pattern +negative_match: "not a url" =~ def.httpsUrl.pattern +negative_match: "http://www.iana.org/assignments" =~ def.httpsUrl.pattern diff --git a/specs/definitions/regex/regex.cue b/specs/definitions/regex/regex.cue new file mode 100644 index 00000000000..049b6c61950 --- /dev/null +++ b/specs/definitions/regex/regex.cue @@ -0,0 +1,14 @@ +// Regex Definitions +package regex + +import ( + "regexp" +) + +#regex: string +#regex: regexp.Valid + +#def: [string]: { + pattern: #regex + description: string +} diff --git a/specs/definitions/signed_docs/cddl_defs.cue b/specs/definitions/signed_docs/cddl_defs.cue index 79300ed7c85..8d92d9fac1e 100644 --- a/specs/definitions/signed_docs/cddl_defs.cue +++ b/specs/definitions/signed_docs/cddl_defs.cue @@ -18,8 +18,8 @@ cddlDefinitions: #cddlDefinitions & { def: "#6.37(bytes .size 16)" description: """ Version 7 UUID - See: \(documentationLinks."RFC9562-V7") - \(documentationLinks."CBOR-TAG-37") + See: \(documentation.links."RFC9562-V7") + \(documentation.links."CBOR-TAG-37") """ comment: "UUIDv7" } @@ -27,8 +27,8 @@ cddlDefinitions: #cddlDefinitions & { def: "#6.37(bytes .size 16)" description: """ Version 4 UUID - See: \(documentationLinks."RFC9562-V4") - \(documentationLinks."CBOR-TAG-37") + See: \(documentation.links."RFC9562-V4") + \(documentation.links."CBOR-TAG-37") """ comment: "UUIDv4" } @@ -60,8 +60,8 @@ cddlDefinitions: #cddlDefinitions & { description: """ IPLD content identifier. Also known as an IPFS CID - See: \(documentationLinks."IPFS-CID") - \(documentationLinks."CBOR-TAG-42") + See: \(documentation.links."IPFS-CID") + \(documentation.links."CBOR-TAG-42") """ comment: """ IPLD content identifier @@ -122,7 +122,8 @@ cddlDefinitions: #cddlDefinitions & { """ comment: """ Supported Content Media Types. - If uint is used, only CoAP Content Formats that match the string format are allowed. + If the Media Type is supported by COAP, then the `uint` CoAP encoded + version of the media type must be used, in preference to the string. """ } http_content_encoding: { diff --git a/specs/definitions/signed_docs/cose_headers.cue b/specs/definitions/signed_docs/cose_headers.cue index 1fb8c1bd443..0027b77fb20 100644 --- a/specs/definitions/signed_docs/cose_headers.cue +++ b/specs/definitions/signed_docs/cose_headers.cue @@ -6,104 +6,9 @@ package signed_docs import ( "list" "github.com/input-output-hk/catalyst-libs/specs/generic:optional" + "github.com/input-output-hk/catalyst-libs/specs/media_types" ) -// Content Type name : Description -_contentTypes: { - [string]: { - description: string // description of the content type - coap_type?: int - } -} -_contentTypes: { - "application/json": { - description: "JSON Document" - coap_type: 50 - } - "application/schema+json": description: """ - JSON Schema Draft 7 Document; Note: - * This is currently an unofficial media type. - * Draft 7 is used because of its wide support by tooling. - """ - "application/cbor": { - description: "RFC8949 Binary CBOR Encoded Document" - coap_type: 60 - } - "application/cddl": description: """ - CDDL Document; Note: - * This is an unofficial media type - * RFC9165 Additional Control Operators for CDDL are supported. - * Must not have Modules, schema must be self-contained. - """ -} - -contentTypes: _contentTypes - -// Content Encoding Type name : Description -_encodingTypes: { - [string]: { - description: string // description of the content type - } -} -_encodingTypes: br: description: "BROTLI Compression" - -encodingTypes: _encodingTypes - -documentationLinks: { - "application/json": "https://www.iana.org/assignments/media-types/application/json" - "application/schema+json": "https://datatracker.ietf.org/doc/draft-bhutton-json-schema/" - "application/cbor": "https://www.iana.org/assignments/media-types/application/cbor" - br: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br" - "JSON Schema": "https://json-schema.org/draft-07" - RFC7932: "https://www.rfc-editor.org/rfc/rfc7932" // Brotli - RFC8259: "https://www.rfc-editor.org/rfc/rfc8259.html" // JSON - RFC8610: "https://www.rfc-editor.org/rfc/rfc8610" // CDDL - RFC8949: "https://www.rfc-editor.org/rfc/rfc8949.html" // CBOR - RFC9052: "https://datatracker.ietf.org/doc/html/rfc9052" // COSE - "RFC9052-CoseSign": "https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si" // COSE Multiple Signers - "RFC9052-HeaderParameters": "https://www.rfc-editor.org/rfc/rfc8152#section-3.1" // COSE Header Parameters - RFC9165: "https://www.rfc-editor.org/rfc/rfc9165" // CDDL Additional Controls -} - -// Known aliases for links. Lets us automatically create [Named Link][Reference Link] -linkAKA: { - BROTLI: "RFC7932" - JSON: "RFC8259" - CDDL: "RFC8610" - CBOR: "RFC8949" - COSE: "RFC9052" - "COSE Sign": "RFC9052-CoseSign" - "COSE Header Parameters": "RFC9052-HeaderParameters" - "RFC9165 - CDDL Additional Controls": "RFC9165" -} - -#allContentTypes: [ - for k, _ in _contentTypes {k}, -] - -_allCoapTypes: [ - for _, v in _contentTypes if v.coap_type != _|_ {v.coap_type}, -] - -_allCoapTypesStr: [ - for v in _allCoapTypes {"\(v)"}, -] - -_allCoapTypes: list.UniqueItems - -#contentTypesConstraint: or(#allContentTypes) - -// Supported Content Types (list of values) -//#contentType: #allContentTypes | *"application/json" -#contentType: #contentTypesConstraint | *#allContentTypes[0] - -// Supported content encodings (list of values) -// All documents support content encoding, this defines the supported encoding types. -// Documents may also not encode data, and will omit this field. -#contentEncoding: ["br"] - -#contentEncodings: [...#contentEncoding] - // Canonical List of COSE header names _coseHeaderNames: list.UniqueItems _coseHeaderNames: [ @@ -150,11 +55,11 @@ cose: headerFormats: #metadataFormats & { required: optional.#field | *"yes" format: #coseHeaderTypesConstraint if format == "Media Type" { - value: #contentType | [...#contentType] + value: media_types.#contentType | [...media_types.#contentType] } if format == "HTTP Content Encoding" { - value: #contentEncoding + value: media_types.allContentEncoding } } @@ -198,7 +103,7 @@ _coseSignatureHeaders: #coseHeaders & { } cose: headers: _coseHeaders -cose: headers: "content type": value: #allContentTypes +cose: headers: "content type": value: media_types.allContentTypes // Preferred display order of cose header fields. // if header not listed, display after the listed fields, in alphabetical order. diff --git a/specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue b/specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue index 67e7ee751f1..94d78fec069 100644 --- a/specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue +++ b/specs/definitions/signed_docs/cose_signed_doc_cddl_defs.cue @@ -5,13 +5,14 @@ package signed_docs import ( "strings" + "github.com/input-output-hk/catalyst-libs/specs/media_types" ) // Formatted content strings to use in CDDL Definition. _cddlContentTypes: "\"\(strings.Join(cose.headers."content type".value, "\" /\n \""))\"" // Formatted CoAP content string to use in CDDL Definition. -_cddlCoapTypes: "\(strings.Join(_allCoapTypesStr, " / "))" +_cddlCoapTypes: "\(strings.Join(media_types.allCoapTypesStr, " / "))" cddlDefinitions: #cddlDefinitions & { signed_document: { @@ -24,7 +25,7 @@ cddlDefinitions: #cddlDefinitions & { used by the Catalyst project to encapsulate and authenticate documents used within the system. - See: \(documentationLinks."RFC9052-CoseSign") + See: \(documentation.links."RFC9052-CoseSign") """ comment: """ Catalyst Signed Document data object. diff --git a/specs/definitions/signed_docs/docs/brand_parameters.cue b/specs/definitions/signed_docs/docs/brand_parameters.cue index 75deb70f29f..d8499e7735e 100644 --- a/specs/definitions/signed_docs/docs/brand_parameters.cue +++ b/specs/definitions/signed_docs/docs/brand_parameters.cue @@ -9,6 +9,8 @@ docs: #DocumentDefinitions & { Parameters which define this brand within the system. """ + headers: "content type": value: "application/json" + versions: [ { version: "0.01" diff --git a/specs/definitions/signed_docs/docs/campaign_parameters.cue b/specs/definitions/signed_docs/docs/campaign_parameters.cue index d63f14e943c..8fb1fd93e0a 100644 --- a/specs/definitions/signed_docs/docs/campaign_parameters.cue +++ b/specs/definitions/signed_docs/docs/campaign_parameters.cue @@ -7,6 +7,7 @@ docs: #DocumentDefinitions & { description: """ Parameters which define a Campaign within a Brand in the system. """ + headers: "content type": value: "application/json" metadata: parameters: { required: "yes" diff --git a/specs/definitions/signed_docs/docs/category_parameters.cue b/specs/definitions/signed_docs/docs/category_parameters.cue index b1dd3099597..eaee58ca392 100644 --- a/specs/definitions/signed_docs/docs/category_parameters.cue +++ b/specs/definitions/signed_docs/docs/category_parameters.cue @@ -9,6 +9,8 @@ docs: #DocumentDefinitions & { Parameters which define a Category withing a Campaign under a Brand in the system. """ + headers: "content type": value: "application/json" + metadata: parameters: { required: "yes" type: "Campaign Parameters" diff --git a/specs/definitions/signed_docs/docs/comment_moderation_action.cue b/specs/definitions/signed_docs/docs/comment_moderation_action.cue index 6e1fb9764c0..0633e75d2e6 100644 --- a/specs/definitions/signed_docs/docs/comment_moderation_action.cue +++ b/specs/definitions/signed_docs/docs/comment_moderation_action.cue @@ -7,6 +7,7 @@ docs: #DocumentDefinitions & { description: """ A Moderation Action performed on any Comment. """ + headers: "content type": value: "application/json" metadata: ref: { required: "yes" diff --git a/specs/definitions/signed_docs/docs/decision_parameters.cue b/specs/definitions/signed_docs/docs/decision_parameters.cue index 5edf8a813a3..16bc7e5c25a 100644 --- a/specs/definitions/signed_docs/docs/decision_parameters.cue +++ b/specs/definitions/signed_docs/docs/decision_parameters.cue @@ -7,6 +7,7 @@ docs: #DocumentDefinitions & { description: """ Parameters which define an individual voting event. """ + headers: "content type": value: "application/json" metadata: parameters: { required: "yes" diff --git a/specs/definitions/signed_docs/docs/proposal.cue b/specs/definitions/signed_docs/docs/proposal.cue index c6c4c2ee3f5..f78d3093999 100644 --- a/specs/definitions/signed_docs/docs/proposal.cue +++ b/specs/definitions/signed_docs/docs/proposal.cue @@ -54,6 +54,7 @@ docs: #DocumentDefinitions & { * That the document has been signed validly according to the [validation](#validation) rules. """ } + headers: "content type": value: "application/json" metadata: { template: { diff --git a/specs/definitions/signed_docs/docs/proposal_comment.cue b/specs/definitions/signed_docs/docs/proposal_comment.cue index 335147324d0..b0fe9cb1e6c 100644 --- a/specs/definitions/signed_docs/docs/proposal_comment.cue +++ b/specs/definitions/signed_docs/docs/proposal_comment.cue @@ -38,6 +38,9 @@ docs: #DocumentDefinitions & { and the integrity of the `ref` and `reply` metadata fields is correct. """ } + + headers: "content type": value: "application/json" + metadata: { ref: { required: "yes" diff --git a/specs/definitions/signed_docs/docs/proposal_moderation_action.cue b/specs/definitions/signed_docs/docs/proposal_moderation_action.cue index a91a356705c..63abeb5376e 100644 --- a/specs/definitions/signed_docs/docs/proposal_moderation_action.cue +++ b/specs/definitions/signed_docs/docs/proposal_moderation_action.cue @@ -8,6 +8,7 @@ docs: #DocumentDefinitions & { description: """ A Moderation action performed on a Proposal. """ + headers: "content type": value: "application/json" metadata: ref: { required: "yes" diff --git a/specs/definitions/signed_docs/docs/proposal_submission_action.cue b/specs/definitions/signed_docs/docs/proposal_submission_action.cue index 03518f9a42a..8115e5ecb0b 100644 --- a/specs/definitions/signed_docs/docs/proposal_submission_action.cue +++ b/specs/definitions/signed_docs/docs/proposal_submission_action.cue @@ -62,6 +62,9 @@ docs: #DocumentDefinitions & { is not considered `final` and will not be considered in the category it was being submitted to. """ } + + headers: "content type": value: "application/json" + metadata: { ref: { type: "Proposal" diff --git a/specs/definitions/signed_docs/documentation.cue b/specs/definitions/signed_docs/documentation.cue new file mode 100644 index 00000000000..c13f1041220 --- /dev/null +++ b/specs/definitions/signed_docs/documentation.cue @@ -0,0 +1,16 @@ +// Links to external documentation + +package signed_docs + +import ( + docs "github.com/input-output-hk/catalyst-libs/specs/documentation" + "github.com/input-output-hk/catalyst-libs/specs/media_types" +) + +documentation: { + links: docs.links + linkAKA: docs.linkAKA +} + +contentTypes: media_types.contentTypes +encodingTypes: media_types.encodingTypes diff --git a/specs/definitions/signed_docs/documentation_links.cue b/specs/definitions/signed_docs/documentation_links.cue deleted file mode 100644 index 590e4e4c9bb..00000000000 --- a/specs/definitions/signed_docs/documentation_links.cue +++ /dev/null @@ -1,53 +0,0 @@ -// Links to external documentation - -package signed_docs - -import ( - "list" -) - -// A named Link to an external document, this would be encoded into markdown as: -// [name]: url -#metadataStruct: { - [_allMetadataNames]: #metadataField -} - -#namedLink: [string]: string - -// Constrains the URLs being linked to be unique -#uniqueLinkValues: list.UniqueItems -#uniqueLinkValues: [...string] & [ - for _, v in documentationLinks {v}, -] - -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/" // 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([ - for k, _ in documentationLinks {k}, -]) - -linkAKA: [string]: #allLinkNames - -// Known aliases for links. Lets us automatically create [Named Link][Reference Link] -linkAKA: { - UUIDv7: "RFC9562-V7" - UUIDv4: "RFC9562-V4" - UUID: "RFC9562" - URI: "RFC3986" - "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/generators/packages/spec/src/spec/documentation_links.py b/specs/generators/packages/spec/src/spec/documentation_links.py index 20b38809816..89419eba13e 100644 --- a/specs/generators/packages/spec/src/spec/documentation_links.py +++ b/specs/generators/packages/spec/src/spec/documentation_links.py @@ -1,6 +1,8 @@ """Documentation Links.""" -from pydantic import HttpUrl, RootModel, computed_field +import typing + +from pydantic import BaseModel, ConfigDict, Field, HttpUrl, RootModel, computed_field class LinkAKA(RootModel[dict[str, str]]): @@ -9,7 +11,7 @@ class LinkAKA(RootModel[dict[str, str]]): root: dict[str, str] -class DocumentationLinks(RootModel[dict[str, HttpUrl]]): +class Links(RootModel[dict[str, HttpUrl]]): """Documentation Links.""" root: dict[str, HttpUrl] @@ -39,3 +41,19 @@ def all(self) -> list[str]: def link(self, link_name: str) -> str: """Get a link for a link name.""" return f"{self.root[link_name]}" + + +class Documentation(BaseModel): + """Documentation Information.""" + + links: Links + link_aka: LinkAKA = Field(alias="linkAKA") + + model_config = ConfigDict(extra="forbid") + + def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 + """Extra setup after we deserialize.""" + super().model_post_init(context) + + # Associate the Link AKA with documentation links. + self.links.set_link_aka(self.link_aka) diff --git a/specs/generators/packages/spec/src/spec/signed_doc.py b/specs/generators/packages/spec/src/spec/signed_doc.py index 30cfc01dfde..82860e4ff1b 100644 --- a/specs/generators/packages/spec/src/spec/signed_doc.py +++ b/specs/generators/packages/spec/src/spec/signed_doc.py @@ -17,7 +17,7 @@ from spec.copyright import Copyright from spec.doc_clusters import DocClusters from spec.document import Documents -from spec.documentation_links import DocumentationLinks, LinkAKA +from spec.documentation_links import Documentation from spec.forms.template import FormTemplate from spec.metadata import Metadata, MetadataHeader from spec.optional import OptionalField @@ -34,9 +34,8 @@ class SignedDoc(BaseModel): cose: CoseDefinitions doc_clusters: DocClusters docs: Documents - documentation_links: DocumentationLinks = Field(alias="documentationLinks") + documentation: Documentation encoding_types: EncodingTypes = Field(alias="encodingTypes") - link_aka_dont_use: LinkAKA = Field(alias="linkAKA") # dont use directly metadata: Metadata form_template: FormTemplate = Field(alias="formTemplate") @@ -61,9 +60,6 @@ def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 self.docs.set_base_types(self.base_types) self.metadata.set_name(None) - # Associate the Link AKA with documentation links. - self.documentation_links.set_link_aka(self.link_aka_dont_use) - # Build dynamic CDDL Definitions from the defined headers. self.cddl_definitions.add( [ diff --git a/specs/generators/pyproject.toml b/specs/generators/pyproject.toml index 0367d176bf8..0ad23be3423 100644 --- a/specs/generators/pyproject.toml +++ b/specs/generators/pyproject.toml @@ -4,6 +4,8 @@ version = "0.1.0" requires-python = ">=3.13" dependencies = [ "jsonschema[format]>=4.24.0", + "mdformat>=0.7.22", + "mdformat-mkdocs>=4.3.0", "pydantic>=2.11.6", "pydot>=4.0.0", "rich>=14.0.0", @@ -37,4 +39,4 @@ requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] -packages = ["src/validator", "packages/spec"] \ No newline at end of file +packages = ["src/validator", "packages/spec"] diff --git a/specs/generators/src/docs/doc_generator.py b/specs/generators/src/docs/doc_generator.py index e7024c27fb4..968f63f737a 100644 --- a/specs/generators/src/docs/doc_generator.py +++ b/specs/generators/src/docs/doc_generator.py @@ -163,10 +163,10 @@ def add_reference_links(self) -> None: self.strip_end_whitespace() actual_links_used: dict[str, str] = {} - for link_name in self._spec.documentation_links.all: + for link_name in self._spec.documentation.links.all: esc_link_name = re.escape(link_name) link_name_regex = f"(^|\\s)({esc_link_name})(\\.|\\s|$)" - aka = self._spec.documentation_links.aka(link_name) + aka = self._spec.documentation.links.aka(link_name) if aka is not None: replacement = f"\\1[\\2][{aka}]\\3" link_name = aka # noqa: PLW2901 @@ -177,7 +177,7 @@ def add_reference_links(self) -> None: link_name_regex, replacement, ): - actual_links_used[link_name] = self._spec.documentation_links.link(link_name) + actual_links_used[link_name] = self._spec.documentation.links.link(link_name) for link, actual in actual_links_used.items(): self._filedata += f"\n[{link}]: {actual}" @@ -268,6 +268,20 @@ def generate(self) -> bool: # Remove any leading or trailing newlines and add a single newline at the end/ # Helps make clean markdown files. + # if self.file_name().endswith(".md"): + # because mdformat turns `*` list markers into `-` and it can't be configured + # tell mdlint that in these files it should be "consistent" which will allow + # the formatted markdown to pass lints. + # self._filedata = f""" + # + # {self._filedata}""" + # self._filedata = mdformat.text( # type: ignore # noqa: PGH003 + # self._filedata, options={"number": True, "wrap": "keep"}, extensions=["mkdocs"] + # ) + # else: self.strip_end_whitespace() return True diff --git a/specs/generators/src/docs/spec_md.py b/specs/generators/src/docs/spec_md.py index 8432d2de483..f30c0bef7b6 100644 --- a/specs/generators/src/docs/spec_md.py +++ b/specs/generators/src/docs/spec_md.py @@ -34,7 +34,7 @@ def header_parameter_doc(self, header: CoseHeader) -> str: description = self._spec.encoding_types.description(value) if description is not None: - value_entry += f" : {description.replace('\n', '\n ')}" + value_entry += f" : {f'\n{description}'.replace('\n', '\n ')}" header_format_display += value_entry @@ -157,8 +157,7 @@ def generate(self) -> bool: ### Metadata -Catalyst Signed Documents extend the Header Parameters with a series of Metadata fields. -These fields are defined [here](./metadata.md). +Catalyst Signed Documents extend the Header Parameters with a series of [Metadata fields](./metadata.md). ### Signing Catalyst Signed Documents diff --git a/specs/generators/uv.lock b/specs/generators/uv.lock index d681470c72c..b8c82da9e47 100644 --- a/specs/generators/uv.lock +++ b/specs/generators/uv.lock @@ -54,6 +54,8 @@ version = "0.1.0" source = { editable = "." } dependencies = [ { name = "jsonschema", extra = ["format"] }, + { name = "mdformat" }, + { name = "mdformat-mkdocs" }, { name = "pydantic" }, { name = "pydot" }, { name = "rich" }, @@ -64,6 +66,8 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "jsonschema", extras = ["format"], specifier = ">=4.24.0" }, + { name = "mdformat", specifier = ">=0.7.22" }, + { name = "mdformat-mkdocs", specifier = ">=4.3.0" }, { name = "pydantic", specifier = ">=2.11.6" }, { name = "pydot", specifier = ">=4.0.0" }, { name = "rich", specifier = ">=14.0.0" }, @@ -152,6 +156,73 @@ 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" }, ] +[[package]] +name = "mdformat" +version = "0.7.22" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/eb/b5cbf2484411af039a3d4aeb53a5160fae25dd8c84af6a4243bc2f3fedb3/mdformat-0.7.22.tar.gz", hash = "sha256:eef84fa8f233d3162734683c2a8a6222227a229b9206872e6139658d99acb1ea", size = 34610, upload-time = "2025-01-30T18:00:51.418Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f2/6f/94a7344f6d634fe3563bea8b33bccedee37f2726f7807e9a58440dc91627/mdformat-0.7.22-py3-none-any.whl", hash = "sha256:61122637c9e1d9be1329054f3fa216559f0d1f722b7919b060a8c2a4ae1850e5", size = 34447, upload-time = "2025-01-30T18:00:48.708Z" }, +] + +[[package]] +name = "mdformat-gfm" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "mdformat" }, + { name = "mdformat-tables" }, + { name = "mdit-py-plugins" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e5/db/873bad63b36e390a33bc0cf7222442010997d3ccf29a1889f24d28fdeddd/mdformat_gfm-0.4.1.tar.gz", hash = "sha256:e189e728e50cfb15746abc6b3178ca0e2bebbb7a8d3d98fbc9e24bc1a4c65564", size = 7528, upload-time = "2024-12-13T09:21:27.212Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/09/ba/3d4c680a2582593b8ba568ab60b119d93542fa39d757d65aae3c4f357e29/mdformat_gfm-0.4.1-py3-none-any.whl", hash = "sha256:63c92cfa5102f55779d4e04b16a79a6a5171e658c6c479175c0955fb4ca78dde", size = 8750, upload-time = "2024-12-13T09:21:25.158Z" }, +] + +[[package]] +name = "mdformat-mkdocs" +version = "4.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdformat" }, + { name = "mdformat-gfm" }, + { name = "mdit-py-plugins" }, + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1b/85/735e11fe6a410c5005b4fb06bc2c75df56cbbcea84ad6dc101e5edae67f9/mdformat_mkdocs-4.3.0.tar.gz", hash = "sha256:d4d9b381d13900a373c1673bd72175a28d712e5ec3d9688d09e66ab4174c493c", size = 27996, upload-time = "2025-05-31T02:15:21.208Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/25/cd4edbe9e5f96048999afbd42d0c030c66c2d45f2119002e7de208e6d43a/mdformat_mkdocs-4.3.0-py3-none-any.whl", hash = "sha256:13e9512b9461c9af982c3b9e1640791d38b0835549e5f8a7ee641926feae4d58", size = 31422, upload-time = "2025-05-31T02:15:20.182Z" }, +] + +[[package]] +name = "mdformat-tables" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdformat" }, + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/64/fc/995ba209096bdebdeb8893d507c7b32b7e07d9a9f2cdc2ec07529947794b/mdformat_tables-1.0.0.tar.gz", hash = "sha256:a57db1ac17c4a125da794ef45539904bb8a9592e80557d525e1f169c96daa2c8", size = 6106, upload-time = "2024-08-23T23:41:33.413Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/37/d78e37d14323da3f607cd1af7daf262cb87fe614a245c15ad03bb03a2706/mdformat_tables-1.0.0-py3-none-any.whl", hash = "sha256:94cd86126141b2adc3b04c08d1441eb1272b36c39146bab078249a41c7240a9a", size = 5104, upload-time = "2024-08-23T23:41:31.863Z" }, +] + +[[package]] +name = "mdit-py-plugins" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542, upload-time = "2024-09-09T20:27:49.564Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/f7/7782a043553ee469c1ff49cfa1cdace2d6bf99a1f333cf38676b3ddf30da/mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636", size = 55316, upload-time = "2024-09-09T20:27:48.397Z" }, +] + [[package]] name = "mdurl" version = "0.1.2" @@ -161,6 +232,15 @@ 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" }, ] +[[package]] +name = "more-itertools" +version = "10.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/a0/834b0cebabbfc7e311f30b46c8188790a37f89fc8d756660346fe5abfd09/more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3", size = 127671, upload-time = "2025-04-22T14:17:41.838Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/9f/7ba6f94fc1e9ac3d2b853fdff3035fb2fa5afbed898c4a72b8a020610594/more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e", size = 65278, upload-time = "2025-04-22T14:17:40.49Z" }, +] + [[package]] name = "pydantic" version = "2.11.6" @@ -393,6 +473,15 @@ 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 = "wcwidth" +version = "0.2.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, +] + [[package]] name = "webcolors" version = "24.11.1" diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 02e96775771..1179c8f468b 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -179,8 +179,8 @@ "requires": [] }, "media_type": { - "comment": "Supported Content Media Types.\nIf uint is used, only CoAP Content Formats that match the string format are allowed.", - "def": "(\n (uint .eq (50 / 60)) / \n (tstr .eq (\n \"application/json\" /\n \"application/schema+json\" /\n \"application/cbor\" /\n \"application/cddl\"\n ))\n)", + "comment": "Supported Content Media Types.\nIf the Media Type is supported by COAP, then the `uint` CoAP encoded\nversion of the media type must be used, in preference to the string.", + "def": "(\n (uint .eq (0 / 50 / 60 / 20000)) / \n (tstr .eq (\n \"application/cbor\" /\n \"application/cddl\" /\n \"application/json\" /\n \"application/schema+json\" /\n \"text/css; charset=utf-8\" /\n \"text/css; charset=utf-8; template=handlebars\" /\n \"text/html; charset=utf-8\" /\n \"text/html; charset=utf-8; template=handlebars\" /\n \"text/markdown; charset=utf-8\" /\n \"text/markdown; charset=utf-8; template=handlebars\" /\n \"text/plain; charset=utf-8\" /\n \"text/plain; charset=utf-8; template=handlebars\"\n ))\n)", "requires": [] }, "revocations": { @@ -221,17 +221,43 @@ "contentTypes": { "application/cbor": { "coap_type": 60, - "description": "RFC8949 Binary CBOR Encoded Document" + "description": "An RFC8949 Binary CBOR Encoded Document." }, "application/cddl": { - "description": "CDDL Document; Note: \n* This is an unofficial media type\n* RFC9165 Additional Control Operators for CDDL are supported. \n* Must not have Modules, schema must be self-contained." + "description": "A CDDL Document.\n\nNote: \n\n* This is an unofficial media type\n* RFC9165 Additional Control Operators for CDDL are supported. \n* Must not have Modules, schema must be self-contained." }, "application/json": { "coap_type": 50, "description": "JSON Document" }, "application/schema+json": { - "description": "JSON Schema Draft 7 Document; Note: \n* This is currently an unofficial media type.\n* Draft 7 is used because of its wide support by tooling." + "description": "A JSON Schema Draft 2020-12 Document.\n\nNote: \n\n* This is currently an unofficial media type." + }, + "text/css; charset=utf-8": { + "coap_type": 20000, + "description": "CSS Content used for styling HTML.\nCSS should use the least set of features possible to achieve\nthe desired presentation to ensure the broadest compatibility." + }, + "text/css; charset=utf-8; template=handlebars": { + "description": "CSS Content used for styling HTML.\nCSS should use the least set of features possible to achieve\nthe desired presentation to ensure the broadest compatibility.\n\nThe text includes Handlebars type template fields that need\nprocessing and replacement prior to display." + }, + "text/html; charset=utf-8": { + "description": "Formatted text using HTML5 markup for rich text. \nOnly HTML5 syntax is supported." + }, + "text/html; charset=utf-8; template=handlebars": { + "description": "Formatted text using HTML5 markup for rich text. \nOnly HTML5 syntax is supported.\n\nThe text includes Handlebars type template fields that need\nprocessing and replacement prior to display." + }, + "text/markdown; charset=utf-8": { + "description": "Formatted text using Markdown for rich text. \nMarkdown formatting is as defined by CommonMark.\n\nIF the document includes HTML, then HTML5 syntax only is supported.\n\nThe following Markdown Extensions are also supported:\n\n* None" + }, + "text/markdown; charset=utf-8; template=handlebars": { + "description": "Formatted text using Markdown for rich text. \nMarkdown formatting is as defined by CommonMark.\n\nIF the document includes HTML, then HTML5 syntax only is supported.\n\nThe following Markdown Extensions are also supported:\n\n* None\n\nThe text includes Handlebars type template fields that need\nprocessing and replacement prior to display." + }, + "text/plain; charset=utf-8": { + "coap_type": 0, + "description": "Plain Text with no markup or special formatting.\nMultiline Plain Text *MUST* always interpret `\n` \nas a hard line break." + }, + "text/plain; charset=utf-8; template=handlebars": { + "description": "Plain Text with no markup or special formatting.\nMultiline Plain Text *MUST* always interpret `\n` \nas a hard line break.\n\nThe text includes Handlebars type template fields that need\nprocessing and replacement prior to display." } }, "copyright": { @@ -283,10 +309,18 @@ "format": "Media Type", "required": "yes", "value": [ + "application/cbor", + "application/cddl", "application/json", "application/schema+json", - "application/cbor", - "application/cddl" + "text/css; charset=utf-8", + "text/css; charset=utf-8; template=handlebars", + "text/html; charset=utf-8", + "text/html; charset=utf-8; template=handlebars", + "text/markdown; charset=utf-8", + "text/markdown; charset=utf-8; template=handlebars", + "text/plain; charset=utf-8", + "text/plain; charset=utf-8; template=handlebars" ] }, "content-encoding": { @@ -1965,30 +1999,70 @@ ] } }, - "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", - "IPFS-CID": "https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid", - "JSON Schema": "https://json-schema.org/draft-07", - "RFC3629": "https://datatracker.ietf.org/doc/html/rfc3629", - "RFC3986": "https://datatracker.ietf.org/doc/html/rfc3986", - "RFC7932": "https://www.rfc-editor.org/rfc/rfc7932", - "RFC8259": "https://www.rfc-editor.org/rfc/rfc8259.html", - "RFC8610": "https://www.rfc-editor.org/rfc/rfc8610", - "RFC8949": "https://www.rfc-editor.org/rfc/rfc8949.html", - "RFC9052": "https://datatracker.ietf.org/doc/html/rfc9052", - "RFC9052-CoseSign": "https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si", - "RFC9052-HeaderParameters": "https://www.rfc-editor.org/rfc/rfc8152#section-3.1", - "RFC9165": "https://www.rfc-editor.org/rfc/rfc9165", - "RFC9562": "https://www.rfc-editor.org/rfc/rfc9562.html", - "RFC9562-V4": "https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-4", - "RFC9562-V7": "https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7", - "application/cbor": "https://www.iana.org/assignments/media-types/application/cbor", - "application/json": "https://www.iana.org/assignments/media-types/application/json", - "application/schema+json": "https://datatracker.ietf.org/doc/draft-bhutton-json-schema/", - "br": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br" + "documentation": { + "linkAKA": { + "BROTLI": "RFC7932", + "CBOR": "RFC8949", + "CBOR Deterministic Encoding": "CBOR-LFD-ENCODING", + "CBOR Encoded IPLD Content Identifier": "CBOR-TAG-42", + "CDDL": "RFC8610", + "COSE": "RFC9052", + "COSE Header Parameters": "RFC9052-HeaderParameters", + "COSE Sign": "RFC9052-CoseSign", + "HTML": "HTML5", + "IPFS CID": "IPFS-CID", + "JSON": "RFC8259", + "JSON Schema": "JSON Schema-2020-12", + "JSON Schema Draft 2020-12": "JSON Schema-2020-12", + "Markdown": "CommonMark", + "RFC9165 - CDDL Additional Controls": "RFC9165", + "URI": "RFC3986", + "UTF-8": "RFC3629", + "UUID": "RFC9562", + "UUIDv4": "RFC9562-V4", + "UUIDv7": "RFC9562-V7", + "application/cddl": "RFC8610", + "application/schema+json": "JSON Schema-2020-12", + "charset=utf-8": "RFC3629", + "charset=utf-8;": "RFC3629", + "template=handlebars": "Handlebars", + "text/css;": "text/css", + "text/html;": "HTML5", + "text/markdown;": "CommonMark", + "text/plain;": "text/plain" + }, + "links": { + "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", + "CSS": "https://www.w3.org/Style/CSS/", + "CommonMark": "https://spec.commonmark.org/0.31.2/", + "HTML5": "https://html.spec.whatwg.org/multipage/syntax.html#syntax", + "Handlebars": "https://handlebarsjs.com/", + "IPFS-CID": "https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid", + "JSON Schema-2020-12": "https://json-schema.org/draft/2020-12", + "JSON Schema-draft7": "https://json-schema.org/draft-07", + "Mustache": "https://mustache.github.io/mustache.5.html", + "RFC3629": "https://datatracker.ietf.org/doc/html/rfc3629", + "RFC3986": "https://datatracker.ietf.org/doc/html/rfc3986", + "RFC7932": "https://www.rfc-editor.org/rfc/rfc7932", + "RFC8259": "https://www.rfc-editor.org/rfc/rfc8259.html", + "RFC8610": "https://www.rfc-editor.org/rfc/rfc8610", + "RFC8949": "https://www.rfc-editor.org/rfc/rfc8949.html", + "RFC9052": "https://datatracker.ietf.org/doc/html/rfc9052", + "RFC9052-CoseSign": "https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si", + "RFC9052-HeaderParameters": "https://www.rfc-editor.org/rfc/rfc8152#section-3.1", + "RFC9165": "https://www.rfc-editor.org/rfc/rfc9165", + "RFC9562": "https://www.rfc-editor.org/rfc/rfc9562.html", + "RFC9562-V4": "https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-4", + "RFC9562-V7": "https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7", + "application/cbor": "https://www.iana.org/assignments/media-types/application/cbor", + "application/json": "https://www.iana.org/assignments/media-types/application/json", + "br": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br", + "text/css": "https://www.rfc-editor.org/rfc/rfc2318.html", + "text/plain": "https://www.rfc-editor.org/rfc/rfc2046.html" + } }, "encodingTypes": { "br": { @@ -1999,7 +2073,7 @@ "dropDownSingleSelect": { "definition": { "contentMediaType": "text/plain", - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "description": "UI - Drop Down Selection of a single entry from the defined enum.\n\nSelect one option from a selector styled as a dropdown menu.\nOnly one choice is allowed.", @@ -2140,7 +2214,7 @@ "pattern": "^[\\S\\s]*$", "type": "string" }, - "description": "UI - Multiline text entry with Markdown content.\nUse Markdown formatting for rich text. \nMarkdown formatting is as defined by \n\nThe following Markdown Extensions are also supported:\n\n* None", + "description": "UI - Multiline text entry with Markdown content.\nUse Markdown formatting for rich text. \nMarkdown formatting is as defined by CommonMark.\n\nThe following Markdown Extensions are also supported:\n\n* None", "parameters": { "description": { "description": "The description of the field presented during data entry.", @@ -2178,7 +2252,7 @@ "multiSelect": { "definition": { "items": { - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "type": "array", @@ -2232,7 +2306,7 @@ "radioButtonSelect": { "definition": { "contentMediaType": "text/plain", - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "description": "UI - Radio Button Selection.\n\nSelect one option from a list of text options.\nSelector is styled as a set of Radio Buttons.", @@ -3043,7 +3117,7 @@ }, "singleLineTextEntry": { "definition": { - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "description": "UI - Single Line text entry without any markup or rich text capability.\nA single line of text.\nNo formatting, markup, line breaks, or special characters are allowed.", @@ -3085,7 +3159,7 @@ "definition": { "items": { "minLength": 1, - "pattern": "^.*$", + "pattern": "^[^\\n]*$", "type": "string" }, "type": "array", @@ -3142,24 +3216,6 @@ "parent": "section" } }, - "linkAKA": { - "BROTLI": "RFC7932", - "CBOR": "RFC8949", - "CBOR Deterministic Encoding": "CBOR-LFD-ENCODING", - "CBOR Encoded IPLD Content Identifier": "CBOR-TAG-42", - "CDDL": "RFC8610", - "COSE": "RFC9052", - "COSE Header Parameters": "RFC9052-HeaderParameters", - "COSE Sign": "RFC9052-CoseSign", - "IPFS CID": "IPFS-CID", - "JSON": "RFC8259", - "RFC9165 - CDDL Additional Controls": "RFC9165", - "URI": "RFC3986", - "UTF-8": "RFC3629", - "UUID": "RFC9562", - "UUIDv4": "RFC9562-V4", - "UUIDv7": "RFC9562-V7" - }, "metadata": { "formats": { "Collaborators Reference List": { From 1f5dc28694fdd3eac7ae36d147e2f1d5b0de3468 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 21 Jun 2025 19:52:09 +0700 Subject: [PATCH 20/42] docs(docs): Add chain metadata to support chained document references. --- .../08_concepts/signed_doc/cddl/chain.cddl | 50 ++++ .../signed_doc/cddl/document_ref.cddl | 6 +- .../signed_doc/cddl/document_refs.cddl | 30 ++ .../signed_doc/cddl/signed_document.cddl | 41 ++- .../signed_doc/docs/brand_parameters.md | 2 + .../signed_doc/docs/campaign_parameters.md | 2 + .../signed_doc/docs/category_parameters.md | 2 + .../docs/comment_moderation_action.md | 4 +- .../signed_doc/docs/decision_parameters.md | 2 + .../08_concepts/signed_doc/docs/proposal.md | 2 + .../signed_doc/docs/proposal_comment.md | 4 +- .../docs/proposal_comment_meta_template.md | 2 + .../docs/proposal_comment_template.md | 2 + .../signed_doc/docs/proposal_meta_template.md | 2 + .../docs/proposal_moderation_action.md | 4 +- .../docs/proposal_submission_action.md | 12 +- .../signed_doc/docs/proposal_template.md | 2 + .../08_concepts/signed_doc/metadata.md | 258 +++++++++++++++++- specs/definitions/signed_docs/cddl_defs.cue | 47 +++- .../includes/fraudulent_chain.mermaid | 54 ++++ .../includes/invalid_chain.mermaid | 70 +++++ .../signed_docs/includes/valid_chain.mermaid | 41 +++ specs/definitions/signed_docs/metadata.cue | 114 +++++++- specs/signed_doc.json | 142 ++++++++-- 24 files changed, 845 insertions(+), 50 deletions(-) create mode 100644 docs/src/architecture/08_concepts/signed_doc/cddl/chain.cddl create mode 100644 docs/src/architecture/08_concepts/signed_doc/cddl/document_refs.cddl create mode 100644 specs/definitions/signed_docs/includes/fraudulent_chain.mermaid create mode 100644 specs/definitions/signed_docs/includes/invalid_chain.mermaid create mode 100644 specs/definitions/signed_docs/includes/valid_chain.mermaid diff --git a/docs/src/architecture/08_concepts/signed_doc/cddl/chain.cddl b/docs/src/architecture/08_concepts/signed_doc/cddl/chain.cddl new file mode 100644 index 00000000000..271b8364668 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/cddl/chain.cddl @@ -0,0 +1,50 @@ +; chain + + +; Reference to the previous Signed Document in a sequence. +; * `height` is of the CURRENT block. +; * `document_ref` is *ONLY* omitted in the very first document in a sequence. +chain = [height, ? document_ref] + +; The consecutive sequence number of the current document +; in the chain. +; The very first document in a sequence is numbered `0` and it +; *MUST ONLY* increment by one for each successive document in +; the sequence. +; +; The FINAL sequence number is encoded with the current height +; sequence value, negated. +; +; For example the following values for height define a chain +; that has 5 documents in the sequence 0-4, the final height +; is negated to indicate the end of the chain: +; `0, 1, 2, 3, -4` +; +; No subsequent document can be chained to a sequence that has +; a final chain height. +height = int + +; Reference to a single Signed Document +document_ref = [ + document_id, + document_ver, + document_locator +] + +; Document ID +document_id = uuid_v7 + +; UUIDv7 +uuid_v7 = #6.37(bytes .size 16) + +; Document Version +document_ver = uuid_v7 + +; Where a document can be located, must be a unique identifier. +document_locator = { + "cid" => cid +} + +; IPLD content identifier +; TODO: add size limits if possible +cid = #6.42(bytes) diff --git a/docs/src/architecture/08_concepts/signed_doc/cddl/document_ref.cddl b/docs/src/architecture/08_concepts/signed_doc/cddl/document_ref.cddl index daa74de9dce..7e7f2158390 100644 --- a/docs/src/architecture/08_concepts/signed_doc/cddl/document_ref.cddl +++ b/docs/src/architecture/08_concepts/signed_doc/cddl/document_ref.cddl @@ -1,12 +1,12 @@ ; document_ref -; Reference to another Signed Document -document_ref = [ 1* [ +; Reference to a single Signed Document +document_ref = [ document_id, document_ver, document_locator -] ] +] ; Document ID document_id = uuid_v7 diff --git a/docs/src/architecture/08_concepts/signed_doc/cddl/document_refs.cddl b/docs/src/architecture/08_concepts/signed_doc/cddl/document_refs.cddl new file mode 100644 index 00000000000..adc72e56cd3 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/cddl/document_refs.cddl @@ -0,0 +1,30 @@ +; document_refs + + +; Reference to one or more Signed Documents +document_refs = [ 1* document_ref ] + +; Reference to a single Signed Document +document_ref = [ + document_id, + document_ver, + document_locator +] + +; Document ID +document_id = uuid_v7 + +; UUIDv7 +uuid_v7 = #6.37(bytes .size 16) + +; Document Version +document_ver = uuid_v7 + +; Where a document can be located, must be a unique identifier. +document_locator = { + "cid" => cid +} + +; IPLD content identifier +; TODO: add size limits if possible +cid = #6.42(bytes) diff --git a/docs/src/architecture/08_concepts/signed_doc/cddl/signed_document.cddl b/docs/src/architecture/08_concepts/signed_doc/cddl/signed_document.cddl index 56776f67508..947b56a8db7 100644 --- a/docs/src/architecture/08_concepts/signed_doc/cddl/signed_document.cddl +++ b/docs/src/architecture/08_concepts/signed_doc/cddl/signed_document.cddl @@ -65,13 +65,14 @@ Signed_Document_Metadata_Headers = ( "type" => document_type "id" => document_id "ver" => document_ver - ?"ref" => document_ref - ?"template" => document_ref - ?"reply" => document_ref + ?"ref" => document_refs + ?"template" => document_refs + ?"reply" => document_refs ?"section" => section_ref ?"collaborators" => collaborators ?"revocations" => revocations - ?"parameters" => document_ref + ?"parameters" => document_refs + ?"chain" => chain ) ; Document Type @@ -89,12 +90,15 @@ uuid_v7 = #6.37(bytes .size 16) ; Document Version document_ver = uuid_v7 -; Reference to another Signed Document -document_ref = [ 1* [ +; Reference to one or more Signed Documents +document_refs = [ 1* document_ref ] + +; Reference to a single Signed Document +document_ref = [ document_id, document_ver, document_locator -] ] +] ; Where a document can be located, must be a unique identifier. document_locator = { @@ -120,6 +124,29 @@ catalyst_id_kid = bytes ; List of revoked versions of this document. revocations = [ * document_ver ] / true +; Reference to the previous Signed Document in a sequence. +; * `height` is of the CURRENT block. +; * `document_ref` is *ONLY* omitted in the very first document in a sequence. +chain = [height, ? document_ref] + +; The consecutive sequence number of the current document +; in the chain. +; The very first document in a sequence is numbered `0` and it +; *MUST ONLY* increment by one for each successive document in +; the sequence. +; +; The FINAL sequence number is encoded with the current height +; sequence value, negated. +; +; For example the following values for height define a chain +; that has 5 documents in the sequence 0-4, the final height +; is negated to indicate the end of the chain: +; `0, 1, 2, 3, -4` +; +; No subsequent document can be chained to a sequence that has +; a final chain height. +height = int + ; Generic Header definition COSE_Generic_Headers = ( * COSE_label => COSE_values ) 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 1d6502d5644..020d060cfae 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 @@ -85,6 +85,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. 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 a0280cb6169..b0953e03402 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 @@ -85,6 +85,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. 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 dcc4b79bb83..e963837dbf2 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 @@ -85,6 +85,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. 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 d10c42d0030..cb26e7c77e3 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 @@ -85,6 +85,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. @@ -107,7 +109,7 @@ Some documents allow multiple references, and they are documented as required. The document reference serves two purposes: 1. It ensures that the document referenced by an ID/Version is not substituted. - In other words, that the document intended to be referenced, is actually referenced. + In other words, that the document intended to be referenced, is actually referenced. 2. It Allows the document to be unambiguously located in decentralized storage systems. There can be any number of Document Locations in any reference. 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 e4afd30cecc..c2caa541f08 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 @@ -85,6 +85,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. 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 6b94c1c6b28..a2563693899 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md @@ -108,6 +108,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. 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 03e1ba8bd67..1fe7c8db557 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 @@ -92,6 +92,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. @@ -114,7 +116,7 @@ Some documents allow multiple references, and they are documented as required. The document reference serves two purposes: 1. It ensures that the document referenced by an ID/Version is not substituted. - In other words, that the document intended to be referenced, is actually referenced. + In other words, that the document intended to be referenced, is actually referenced. 2. It Allows the document to be unambiguously located in decentralized storage systems. There can be any number of Document Locations in any reference. 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 e6849b7326c..74b199e00b0 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 @@ -90,6 +90,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. 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 199b7712ce8..7a87d63693d 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 @@ -93,6 +93,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. 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 548fc99844c..f92c6e0604a 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 @@ -90,6 +90,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. 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 2c114548600..8aa046c4e39 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 @@ -85,6 +85,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. @@ -107,7 +109,7 @@ Some documents allow multiple references, and they are documented as required. The document reference serves two purposes: 1. It ensures that the document referenced by an ID/Version is not substituted. - In other words, that the document intended to be referenced, is actually referenced. + In other words, that the document intended to be referenced, is actually referenced. 2. It Allows the document to be unambiguously located in decentralized storage systems. There can be any number of Document Locations in any reference. 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 13669d7ce39..030f2854af6 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 @@ -116,6 +116,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. @@ -139,7 +141,7 @@ Some documents allow multiple references, and they are documented as required. The document reference serves two purposes: 1. It ensures that the document referenced by an ID/Version is not substituted. - In other words, that the document intended to be referenced, is actually referenced. + In other words, that the document intended to be referenced, is actually referenced. 2. It Allows the document to be unambiguously located in decentralized storage systems. There can be any number of Document Locations in any reference. @@ -196,8 +198,8 @@ 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`. + `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 @@ -212,8 +214,8 @@ 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`. + `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 { 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 babbed81734..219061849a5 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 @@ -93,6 +93,8 @@ IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a docu The unique version of the document. The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + #### [`ver`](../metadata.md#ver) Validation The document version must always be >= the document ID. diff --git a/docs/src/architecture/08_concepts/signed_doc/metadata.md b/docs/src/architecture/08_concepts/signed_doc/metadata.md index 8daa80ac974..a152b1ebec9 100644 --- a/docs/src/architecture/08_concepts/signed_doc/metadata.md +++ b/docs/src/architecture/08_concepts/signed_doc/metadata.md @@ -5,6 +5,21 @@ The following types of metadata have been defined. All Metadata fields use one of these types. +### Chain Link + +A link to a previous document in a chained sequence. + + +??? note "CDDL Specification" + + * [cddl/chain.cddl](cddl/chain.cddl) + + ```cddl + {{ include_file('./cddl/chain.cddl', indent=4) }} + ``` + + + ### Collaborators Reference List A list of collaborators who can participate in drafting and submitting a document @@ -42,10 +57,10 @@ A document reference identifier ??? note "CDDL Specification" - * [cddl/document_ref.cddl](cddl/document_ref.cddl) + * [cddl/document_refs.cddl](cddl/document_refs.cddl) ```cddl - {{ include_file('./cddl/document_ref.cddl', indent=4) }} + {{ include_file('./cddl/document_refs.cddl', indent=4) }} ``` @@ -184,6 +199,17 @@ IF [`ver`](metadata.md#ver) does not == [`id`](metadata.md#id) then a document w The unique version of the document. The first version of the document must set [`ver`](metadata.md#ver) == [`id`](metadata.md#id) +[`ver`](metadata.md#ver) represents either: + +* when a document changes over time, such as + with a new version of a particular document that supersedes an + earlier one. +* when a new document in a sequence of documents is produced. + +Because the most common use [`ver`](metadata.md#ver) is a new version of the same document +this is to be assumed unless the document specifies its representing +a sequence of documents. + #### `ver` Validation The document version must always be >= the document ID. @@ -218,7 +244,7 @@ Some documents allow multiple references, and they are documented as required. The document reference serves two purposes: 1. It ensures that the document referenced by an ID/Version is not substituted. - In other words, that the document intended to be referenced, is actually referenced. + In other words, that the document intended to be referenced, is actually referenced. 2. It Allows the document to be unambiguously located in decentralized storage systems. There can be any number of Document Locations in any reference. @@ -342,6 +368,232 @@ In addition to the validation performed for [Document Reference](metadata.md#doc * Any linked referenced document that includes a [`parameters`](metadata.md#parameters) metadata must match the [`parameters`](metadata.md#parameters) of the referencing document. +### `chain` + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Chain Link](metadata.md#chain-link) | + +An immutable link to the previous document in a chained sequence of documents. +Because ID/Ver only defines values for the current document, and is not intended +by itself to prevent insertion of documents in a sequence, the [`chain`](metadata.md#chain) +metadata allows for the latest document to directly point to its previous iteration. + +It also aids in discoverability, where the latest document may be pinned but prior +documents can be discovered automatically by following the chain. + +#### `chain` Validation + +Chained Documents do not support collaborators. +Any document which is attempted to be published in the sequence +which is *NOT* published by the author of the first document in the +sequence is fraudulent, and to be discarded. + +In addition, the chained document *MUST*: + +* Not have `collaborators`; +* Have the same [`id`](metadata.md#id) as the document being chained to; +* Have a [`ver`](metadata.md#ver) that is greater than the [`ver`](metadata.md#ver) being chained to; +* Have the same [`type`](metadata.md#type) as the chained document; +* Have [`parameters`](metadata.md#parameters) match; +* Have not be chaining to a document already chained to by another document; +* Have its absolute `height` exactly one more than the `height` of the document being chained to. + +IF any of these validations fail, then the entire sequence of documents is INVALID. +Not just the current document. + +##### Example of a Valid Chain + +``` mermaid + classDiagram + direction LR + class Last { + type: "=Intermediate.Document Type" + id: "=Intermediate.Document ID" + ver: ">Intermediate.Document ID" + parameters: "=Intermediate.Document Parameters" + chain.height: -2 + chain.document_ref: "=Intermediate" + + author(Intermediate.Catalyst ID) + } + style Last stroke:#060,stroke-width:4px + + class Intermediate { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">First.Document ID" + parameters: "=First.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(First.Catalyst ID) + } + style Intermediate stroke:#060,stroke-width:4px + + class First { + type: "Document Type" + id: "Document ID" + ver: "=Document ID" + parameters: "Document Parameters" + chain.height: 0 + chain.document_ref: None + + author(Catalyst ID) + } + style First stroke:#060,stroke-width:4px + + Last --|> Intermediate : chains to + Intermediate --|> First : chains to + + +``` + +##### Example of an Invalid Chain + +Either of the two documents being present invalidates the data +in the entire chain, +as they are signed by the author of the chain. + +``` mermaid + classDiagram + direction LR + + class Last { + type: "=Intermediate.Document Type" + id: "=Intermediate.Document ID" + ver: ">Intermediate.Document ID" + parameters: "=Intermediate.Document Parameters" + chain.height: -2 + chain.document_ref: "=Intermediate" + + author(Intermediate.Catalyst ID) + } + style Last stroke:#f60,stroke-width:4px + + class Intermediate { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">First.Document ID" + parameters: "=First.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(First.Catalyst ID) + } + style Intermediate stroke:#f60,stroke-width:4px + + class First { + type: "Document Type" + id: "Document ID" + ver: "=Document ID" + parameters: "Document Parameters" + chain.height: 0 + chain.document_ref: None + + author(Catalyst ID) + } + style First stroke:#f60,stroke-width:4px + + Last --|> Intermediate : chains to + Intermediate --|> First : chains to + + class Invalid_Chain { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">Intermedisate.Document ID" + parameters: "=First.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(First.Catalyst ID) + } + + Invalid_Chain --|> First : Invalidly chains to + style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px + + + class After_Final { + type: "=Final.Document Type" + id: "=Final.Document ID" + ver: ">Final.Document ID" + parameters: "=Final.Document Parameters" + chain.height: 3 + chain.document_ref: "=Last" + + author(Last.Catalyst ID) + } + + After_Final --|> Last : Invalidly chains to + style After_Final fill:#100,stroke:#f00,stroke-width:4px + +``` + +##### Example of a Fraudulent Chain Document + +The invalid document does not invalidate the chain, +as its not signed by the author of the chained documents. + +``` mermaid + classDiagram + direction LR + class Last { + type: "=Intermediate.Document Type" + id: "=Intermediate.Document ID" + ver: ">Intermediate.Document ID" + parameters: "=Intermediate.Document Parameters" + chain.height: -2 + chain.document_ref: "=Intermediate" + + author(Intermediate.Catalyst ID) + } + style Last stroke:#060,stroke-width:4px + + class Intermediate { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">First.Document ID" + parameters: "=First.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(First.Catalyst ID) + } + style Intermediate stroke:#060,stroke-width:4px + + class First { + type: "Document Type" + id: "Document ID" + ver: "=Document ID" + parameters: "Document Parameters" + chain.height: 0 + chain.document_ref: None + + author(Catalyst ID) + } + style First stroke:#060,stroke-width:4px + + Last --|> Intermediate : chains to + Intermediate --|> First : chains to + + class Rejected { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">Intermedisate.Document ID" + parameters: "=Intermediate.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(Other.Catalyst ID) + } + + Rejected --|> Intermediate : Invalidly chains to + style Rejected fill:#100,stroke:#f00,stroke-width:4px + +``` + ## Copyright | Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | diff --git a/specs/definitions/signed_docs/cddl_defs.cue b/specs/definitions/signed_docs/cddl_defs.cue index 8d92d9fac1e..014872fb442 100644 --- a/specs/definitions/signed_docs/cddl_defs.cue +++ b/specs/definitions/signed_docs/cddl_defs.cue @@ -77,20 +77,27 @@ cddlDefinitions: #cddlDefinitions & { requires: ["cid"] comment: "Where a document can be located, must be a unique identifier." } + document_refs: { + def: "[ 1* \(requires[0]) ]" + requires: [ + "document_ref", + ] + comment: "Reference to one or more Signed Documents" + } document_ref: { def: """ - [ 1* [ + [ \(requires[0]), \(requires[1]), \(requires[2]) - ] ] + ] """ requires: [ "document_id", "document_ver", "document_locator", ] - comment: "Reference to another Signed Document" + comment: "Reference to a single Signed Document" } json_pointer: { def: "text" @@ -140,6 +147,40 @@ cddlDefinitions: #cddlDefinitions & { def: "[ * document_ver ] / true " requires: ["document_ver"] } + chain: { + def: "[\(requires[0]), ? \(requires[1])]" + requires: [ + "height", + "document_ref", + ] + comment: """ + Reference to the previous Signed Document in a sequence. + * `\(requires[0])` is of the CURRENT block. + * `\(requires[1])` is *ONLY* omitted in the very first document in a sequence. + """ + } + height: { + def: "int" + comment: """ + The consecutive sequence number of the current document + in the chain. + The very first document in a sequence is numbered `0` and it + *MUST ONLY* increment by one for each successive document in + the sequence. + + The FINAL sequence number is encoded with the current height + sequence value, negated. + + For example the following values for height define a chain + that has 5 documents in the sequence 0-4, the final height + is negated to indicate the end of the chain: + `0, 1, 2, 3, -4` + + No subsequent document can be chained to a sequence that has + a final chain height. + """ + } + } #cddlTypes: [ diff --git a/specs/definitions/signed_docs/includes/fraudulent_chain.mermaid b/specs/definitions/signed_docs/includes/fraudulent_chain.mermaid new file mode 100644 index 00000000000..e0446e02fca --- /dev/null +++ b/specs/definitions/signed_docs/includes/fraudulent_chain.mermaid @@ -0,0 +1,54 @@ +classDiagram + direction LR + class Last { + type: "=Intermediate.Document Type" + id: "=Intermediate.Document ID" + ver: ">Intermediate.Document ID" + parameters: "=Intermediate.Document Parameters" + chain.height: -2 + chain.document_ref: "=Intermediate" + + author(Intermediate.Catalyst ID) + } + style Last stroke:#060,stroke-width:4px + + class Intermediate { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">First.Document ID" + parameters: "=First.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(First.Catalyst ID) + } + style Intermediate stroke:#060,stroke-width:4px + + class First { + type: "Document Type" + id: "Document ID" + ver: "=Document ID" + parameters: "Document Parameters" + chain.height: 0 + chain.document_ref: None + + author(Catalyst ID) + } + style First stroke:#060,stroke-width:4px + + Last --|> Intermediate : chains to + Intermediate --|> First : chains to + + class Rejected { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">Intermedisate.Document ID" + parameters: "=Intermediate.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(Other.Catalyst ID) + } + + Rejected --|> Intermediate : Invalidly chains to + style Rejected fill:#100,stroke:#f00,stroke-width:4px diff --git a/specs/definitions/signed_docs/includes/invalid_chain.mermaid b/specs/definitions/signed_docs/includes/invalid_chain.mermaid new file mode 100644 index 00000000000..0846d231f85 --- /dev/null +++ b/specs/definitions/signed_docs/includes/invalid_chain.mermaid @@ -0,0 +1,70 @@ +classDiagram + direction LR + + class Last { + type: "=Intermediate.Document Type" + id: "=Intermediate.Document ID" + ver: ">Intermediate.Document ID" + parameters: "=Intermediate.Document Parameters" + chain.height: -2 + chain.document_ref: "=Intermediate" + + author(Intermediate.Catalyst ID) + } + style Last stroke:#f60,stroke-width:4px + + class Intermediate { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">First.Document ID" + parameters: "=First.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(First.Catalyst ID) + } + style Intermediate stroke:#f60,stroke-width:4px + + class First { + type: "Document Type" + id: "Document ID" + ver: "=Document ID" + parameters: "Document Parameters" + chain.height: 0 + chain.document_ref: None + + author(Catalyst ID) + } + style First stroke:#f60,stroke-width:4px + + Last --|> Intermediate : chains to + Intermediate --|> First : chains to + + class Invalid_Chain { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">Intermedisate.Document ID" + parameters: "=First.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(First.Catalyst ID) + } + + Invalid_Chain --|> First : Invalidly chains to + style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px + + + class After_Final { + type: "=Final.Document Type" + id: "=Final.Document ID" + ver: ">Final.Document ID" + parameters: "=Final.Document Parameters" + chain.height: 3 + chain.document_ref: "=Last" + + author(Last.Catalyst ID) + } + + After_Final --|> Last : Invalidly chains to + style After_Final fill:#100,stroke:#f00,stroke-width:4px diff --git a/specs/definitions/signed_docs/includes/valid_chain.mermaid b/specs/definitions/signed_docs/includes/valid_chain.mermaid new file mode 100644 index 00000000000..4bfaff6b87d --- /dev/null +++ b/specs/definitions/signed_docs/includes/valid_chain.mermaid @@ -0,0 +1,41 @@ +classDiagram + direction LR + class Last { + type: "=Intermediate.Document Type" + id: "=Intermediate.Document ID" + ver: ">Intermediate.Document ID" + parameters: "=Intermediate.Document Parameters" + chain.height: -2 + chain.document_ref: "=Intermediate" + + author(Intermediate.Catalyst ID) + } + style Last stroke:#060,stroke-width:4px + + class Intermediate { + type: "=First.Document Type" + id: "=First.Document ID" + ver: ">First.Document ID" + parameters: "=First.Document Parameters" + chain.height: 1 + chain.document_ref: "=First" + + author(First.Catalyst ID) + } + style Intermediate stroke:#060,stroke-width:4px + + class First { + type: "Document Type" + id: "Document ID" + ver: "=Document ID" + parameters: "Document Parameters" + chain.height: 0 + chain.document_ref: None + + author(Catalyst ID) + } + style First stroke:#060,stroke-width:4px + + Last --|> Intermediate : chains to + Intermediate --|> First : chains to + diff --git a/specs/definitions/signed_docs/metadata.cue b/specs/definitions/signed_docs/metadata.cue index 96ad8fe91cd..29ddbda3875 100644 --- a/specs/definitions/signed_docs/metadata.cue +++ b/specs/definitions/signed_docs/metadata.cue @@ -1,6 +1,7 @@ // Signed Document Definitions // // Metadata Types and Constraints +@extern(embed) package signed_docs import ( @@ -8,6 +9,9 @@ import ( "github.com/input-output-hk/catalyst-libs/specs/generic:optional" ) +_chainValidMermaid: _ @embed(file=includes/valid_chain.mermaid,type=text) +_chainInvalidMermaid: _ @embed(file=includes/invalid_chain.mermaid,type=text) +_chainFraudulentMermaid: _ @embed(file=includes/fraudulent_chain.mermaid,type=text) // Metadata Formats. // format_name : cddl definition #metadataFormats: { @@ -20,7 +24,7 @@ import ( metadata: formats: #metadataFormats & { "Document Reference": { description: "A document reference identifier" - cddl: "document_ref" + cddl: "document_refs" } UUIDv7: { description: "Version 7 formatted UUID" @@ -54,6 +58,10 @@ metadata: formats: #metadataFormats & { description: "A list of all versions of this document which are 'revoked'." cddl: "revocations" } + "Chain Link": { + description: "A link to a previous document in a chained sequence." + cddl: "chain" + } } // Types of a Metadata Fields @@ -77,6 +85,7 @@ _metadataNames: [ "collaborators", "revocations", "parameters", + "chain", ] _allMetadataNames: or([ @@ -97,11 +106,43 @@ _allMetadataNames: or([ } // Markdown description of the field. - description: string | *"" + description: string // Optional notes about validating the field. validation: string | *null } +_ver_description_common: """ + The unique version of the document. + The first version of the document must set `ver` == `id` + """ + +_ver_description_complete: """ + \(_ver_description_common) + + `ver` represents either: + + * when a document changes over time, such as + with a new version of a particular document that supersedes an + earlier one. + * when a new document in a sequence of documents is produced. + + Because the most common use `ver` is a new version of the same document + this is to be assumed unless the document specifies its representing + a sequence of documents. + """ + +_ver_description_versioned: """ + \(_ver_description_common) + + `ver` represents new versions of the same document as it changes over time. + """ + +_ver_description_sequenced: """ + \(_ver_description_common) + + `ver` represents new documents in a sequence of documents. + """ + // Metadata fields that are optional #metadataStruct: { [_allMetadataNames]: #metadataField @@ -132,13 +173,9 @@ _metadata: #metadataStruct & { } // Document Version ver: { - required: "yes" - format: "Document Ver" - description: """ - The unique version of the document. - The first version of the document must set `ver` == `id` - """ - + required: "yes" + format: "Document Ver" + description: string | *_ver_description_versioned validation: """ The document version must always be >= the document ID. """ @@ -260,11 +297,69 @@ _metadata: #metadataStruct & { `parameters` of the referencing document. """ } + + chain: { + format: "Chain Link" + description: """ + An immutable link to the previous document in a chained sequence of documents. + Because ID/Ver only defines values for the current document, and is not intended + by itself to prevent insertion of documents in a sequence, the `chain` + metadata allows for the latest document to directly point to its previous iteration. + + It also aids in discoverability, where the latest document may be pinned but prior + documents can be discovered automatically by following the chain. + """ + validation: """ + Chained Documents do not support collaborators. + Any document which is attempted to be published in the sequence + which is *NOT* published by the author of the first document in the + sequence is fraudulent, and to be discarded. + + In addition, the chained document *MUST*: + + * Not have `collaborators`; + * Have the same `id` as the document being chained to; + * Have a `ver` that is greater than the `ver` being chained to; + * Have the same `type` as the chained document; + * Have `parameters` match; + * Have not be chaining to a document already chained to by another document; + * Have its absolute `height` exactly one more than the `height` of the document being chained to. + + IF any of these validations fail, then the entire sequence of documents is INVALID. + Not just the current document. + + ##### Example of a Valid Chain + + ``` mermaid + \(_chainValidMermaid) + ``` + + ##### Example of an Invalid Chain + + Either of the two documents being present invalidates the data + in the entire chain, + as they are signed by the author of the chain. + + ``` mermaid + \(_chainInvalidMermaid) + ``` + + ##### Example of a Fraudulent Chain Document + + The invalid document does not invalidate the chain, + as its not signed by the author of the chained documents. + + ``` mermaid + \(_chainFraudulentMermaid) + ``` + """ + } } // Note: we make all normally excluded fields optional at the global level, because they are globally optional metadata: headers: _metadata metadata: headers: { + ver: description: _ver_description_complete ref: required: "optional" ref: type: _allDocNamesList template: required: "optional" @@ -275,6 +370,7 @@ metadata: headers: { collaborators: required: "optional" parameters: required: "optional" parameters: type: #parameterDocNamesList + chain: required: "optional" } // Preferred display order diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 1179c8f468b..802aa23d7db 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -115,6 +115,14 @@ "def": "bytes", "requires": [] }, + "chain": { + "comment": "Reference to the previous Signed Document in a sequence.\n* `height` is of the CURRENT block.\n* `document_ref` is *ONLY* omitted in the very first document in a sequence.", + "def": "[height, ? document_ref]", + "requires": [ + "height", + "document_ref" + ] + }, "cid": { "comment": "IPLD content identifier\nTODO: add size limits if possible", "def": "#6.42(bytes)", @@ -144,14 +152,21 @@ ] }, "document_ref": { - "comment": "Reference to another Signed Document", - "def": "[ 1* [\n document_id, \n document_ver, \n document_locator\n] ]", + "comment": "Reference to a single Signed Document", + "def": "[\n document_id, \n document_ver, \n document_locator\n]", "requires": [ "document_id", "document_ver", "document_locator" ] }, + "document_refs": { + "comment": "Reference to one or more Signed Documents", + "def": "[ 1* document_ref ]", + "requires": [ + "document_ref" + ] + }, "document_type": { "comment": "Document Type", "def": "[ 1* uuid_v4 ]", @@ -168,6 +183,11 @@ "uuid_v7" ] }, + "height": { + "comment": "The consecutive sequence number of the current document \nin the chain.\nThe very first document in a sequence is numbered `0` and it\n*MUST ONLY* increment by one for each successive document in\nthe sequence.\n\nThe FINAL sequence number is encoded with the current height\nsequence value, negated. \n\nFor example the following values for height define a chain\nthat has 5 documents in the sequence 0-4, the final height \nis negated to indicate the end of the chain:\n`0, 1, 2, 3, -4`\n\nNo subsequent document can be chained to a sequence that has\na final chain height.", + "def": "int", + "requires": [] + }, "http_content_encoding": { "comment": "Supported Content Encoding Types", "def": "tstr .eq \"br\"", @@ -378,6 +398,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -433,7 +459,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -483,6 +509,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -541,7 +573,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -596,6 +628,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -654,7 +692,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -709,6 +747,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -769,7 +813,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -821,6 +865,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -883,7 +933,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -944,6 +994,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -1011,7 +1067,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1075,6 +1131,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -1149,7 +1211,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1209,6 +1271,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -1271,7 +1339,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1335,6 +1403,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -1400,7 +1474,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1462,6 +1536,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -1524,7 +1604,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1587,6 +1667,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -1645,7 +1731,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1701,6 +1787,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -1768,7 +1860,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1892,6 +1984,12 @@ } }, "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -1959,7 +2057,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -3218,6 +3316,10 @@ }, "metadata": { "formats": { + "Chain Link": { + "cddl": "chain", + "description": "A link to a previous document in a chained sequence." + }, "Collaborators Reference List": { "cddl": "collaborators", "description": "A list of collaborators who can participate in drafting and submitting a document" @@ -3227,7 +3329,7 @@ "description": "A unique document identifier" }, "Document Reference": { - "cddl": "document_ref", + "cddl": "document_refs", "description": "A document reference identifier" }, "Document Type": { @@ -3256,6 +3358,12 @@ } }, "headers": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "optional", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", @@ -3349,7 +3457,7 @@ "validation": "**MUST** be a known document type." }, "ver": { - "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`", + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents either:\n\n* when a document changes over time, such as\n\twith a new version of a particular document that supersedes an \n\tearlier one.\n* when a new document in a sequence of documents is produced.\n\t\nBecause the most common use `ver` is a new version of the same document\nthis is to be assumed unless the document specifies its representing\na sequence of documents.", "format": "Document Ver", "required": "yes", "validation": "The document version must always be >= the document ID." From 79bc324529ac12aa11806f403b695677e9f5f0c2 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 21 Jun 2025 21:08:01 +0700 Subject: [PATCH 21/42] fix(docs): lint issues --- .markdownlint-cli2.jsonc | 3 +- .../08_concepts/signed_doc/metadata.md | 14 ++- .../08_concepts/signed_doc/templates.md | 2 +- .../includes/fraudulent_chain.mermaid | 2 +- .../includes/invalid_chain.mermaid | 2 +- specs/definitions/signed_docs/metadata.cue | 106 ++++++++++-------- specs/generators/packages/spec/README.md | 1 + .../packages/spec/src/spec/base_types.py | 2 + .../packages/spec/src/spec/cddl/cose.py | 8 +- .../packages/spec/src/spec/cddl/definition.py | 13 +-- .../packages/spec/src/spec/doc_types.py | 4 +- .../spec/src/spec/forms/element/element.py | 11 +- .../spec/src/spec/forms/element/parameters.py | 36 +++--- .../packages/spec/src/spec/forms/template.py | 6 +- .../packages/spec/src/spec/metadata.py | 21 ++-- specs/generators/src/docs/doc_generator.py | 6 +- specs/generators/src/docs/spec_md.py | 2 +- .../src/docs/template_example_schema_json.py | 7 -- specs/generators/src/docs/templates_md.py | 4 + specs/signed_doc.json | 28 ++--- 20 files changed, 148 insertions(+), 130 deletions(-) diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc index 04934f5ab75..5605720392d 100644 --- a/.markdownlint-cli2.jsonc +++ b/.markdownlint-cli2.jsonc @@ -11,7 +11,8 @@ ".config/dictionaries/**", "**/target/**", "**/.dart_tool/**", - "**/.pytest_cache/**" + "**/.pytest_cache/**", + "**/.venv" ], // Set standard config options in `/.markdownlint.jsonc` "config": { diff --git a/docs/src/architecture/08_concepts/signed_doc/metadata.md b/docs/src/architecture/08_concepts/signed_doc/metadata.md index a152b1ebec9..a7516e0749d 100644 --- a/docs/src/architecture/08_concepts/signed_doc/metadata.md +++ b/docs/src/architecture/08_concepts/signed_doc/metadata.md @@ -406,8 +406,9 @@ Not just the current document. ##### Example of a Valid Chain + ``` mermaid - classDiagram + classDiagram direction LR class Last { type: "=Intermediate.Document Type" @@ -450,6 +451,7 @@ Not just the current document. ``` + ##### Example of an Invalid Chain @@ -457,8 +459,9 @@ Either of the two documents being present invalidates the data in the entire chain, as they are signed by the author of the chain. + ``` mermaid - classDiagram + classDiagram direction LR class Last { @@ -503,7 +506,7 @@ as they are signed by the author of the chain. class Invalid_Chain { type: "=First.Document Type" id: "=First.Document ID" - ver: ">Intermedisate.Document ID" + ver: ">Intermediate.Document ID" parameters: "=First.Document Parameters" chain.height: 1 chain.document_ref: "=First" @@ -530,12 +533,14 @@ as they are signed by the author of the chain. style After_Final fill:#100,stroke:#f00,stroke-width:4px ``` + ##### Example of a Fraudulent Chain Document The invalid document does not invalidate the chain, as its not signed by the author of the chained documents. + ``` mermaid classDiagram direction LR @@ -581,7 +586,7 @@ as its not signed by the author of the chained documents. class Rejected { type: "=First.Document Type" id: "=First.Document ID" - ver: ">Intermedisate.Document ID" + ver: ">Intermediate.Document ID" parameters: "=Intermediate.Document Parameters" chain.height: 1 chain.document_ref: "=First" @@ -593,6 +598,7 @@ as its not signed by the author of the chained documents. style Rejected fill:#100,stroke:#f00,stroke-width:4px ``` + ## Copyright diff --git a/docs/src/architecture/08_concepts/signed_doc/templates.md b/docs/src/architecture/08_concepts/signed_doc/templates.md index 8b137891791..56934c598f1 100644 --- a/docs/src/architecture/08_concepts/signed_doc/templates.md +++ b/docs/src/architecture/08_concepts/signed_doc/templates.md @@ -1 +1 @@ - +# Templates" diff --git a/specs/definitions/signed_docs/includes/fraudulent_chain.mermaid b/specs/definitions/signed_docs/includes/fraudulent_chain.mermaid index e0446e02fca..5e87b72c643 100644 --- a/specs/definitions/signed_docs/includes/fraudulent_chain.mermaid +++ b/specs/definitions/signed_docs/includes/fraudulent_chain.mermaid @@ -42,7 +42,7 @@ classDiagram class Rejected { type: "=First.Document Type" id: "=First.Document ID" - ver: ">Intermedisate.Document ID" + ver: ">Intermediate.Document ID" parameters: "=Intermediate.Document Parameters" chain.height: 1 chain.document_ref: "=First" diff --git a/specs/definitions/signed_docs/includes/invalid_chain.mermaid b/specs/definitions/signed_docs/includes/invalid_chain.mermaid index 0846d231f85..e9193cc674d 100644 --- a/specs/definitions/signed_docs/includes/invalid_chain.mermaid +++ b/specs/definitions/signed_docs/includes/invalid_chain.mermaid @@ -43,7 +43,7 @@ classDiagram class Invalid_Chain { type: "=First.Document Type" id: "=First.Document ID" - ver: ">Intermedisate.Document ID" + ver: ">Intermediate.Document ID" parameters: "=First.Document Parameters" chain.height: 1 chain.document_ref: "=First" diff --git a/specs/definitions/signed_docs/metadata.cue b/specs/definitions/signed_docs/metadata.cue index 29ddbda3875..ffd870ff1e0 100644 --- a/specs/definitions/signed_docs/metadata.cue +++ b/specs/definitions/signed_docs/metadata.cue @@ -108,7 +108,7 @@ _allMetadataNames: or([ // Markdown description of the field. description: string // Optional notes about validating the field. - validation: string | *null + validation: string } _ver_description_common: """ @@ -143,6 +143,64 @@ _ver_description_sequenced: """ `ver` represents new documents in a sequence of documents. """ +_chain_validation_common: """ + Chained Documents do not support collaborators. + Any document which is attempted to be published in the sequence + which is *NOT* published by the author of the first document in the + sequence is fraudulent, and to be discarded. + + In addition, the chained document *MUST*: + + * Not have `collaborators`; + * Have the same `id` as the document being chained to; + * Have a `ver` that is greater than the `ver` being chained to; + * Have the same `type` as the chained document; + * Have `parameters` match; + * Have not be chaining to a document already chained to by another document; + * Have its absolute `height` exactly one more than the `height` of the document being chained to. + + IF any of these validations fail, then the entire sequence of documents is INVALID. + Not just the current document. + """ + +_chain_validation_examples: """ + ##### Example of a Valid Chain + + + ``` mermaid + \(_chainValidMermaid) + ``` + + + ##### Example of an Invalid Chain + + Either of the two documents being present invalidates the data + in the entire chain, + as they are signed by the author of the chain. + + + ``` mermaid + \(_chainInvalidMermaid) + ``` + + + ##### Example of a Fraudulent Chain Document + + The invalid document does not invalidate the chain, + as its not signed by the author of the chained documents. + + + ``` mermaid + \(_chainFraudulentMermaid) + ``` + + """ + +_chain_validation_complete: """ + \(_chain_validation_common) + + \(_chain_validation_examples) + """ // Metadata fields that are optional #metadataStruct: { [_allMetadataNames]: #metadataField @@ -309,49 +367,8 @@ _metadata: #metadataStruct & { It also aids in discoverability, where the latest document may be pinned but prior documents can be discovered automatically by following the chain. """ - validation: """ - Chained Documents do not support collaborators. - Any document which is attempted to be published in the sequence - which is *NOT* published by the author of the first document in the - sequence is fraudulent, and to be discarded. - - In addition, the chained document *MUST*: - - * Not have `collaborators`; - * Have the same `id` as the document being chained to; - * Have a `ver` that is greater than the `ver` being chained to; - * Have the same `type` as the chained document; - * Have `parameters` match; - * Have not be chaining to a document already chained to by another document; - * Have its absolute `height` exactly one more than the `height` of the document being chained to. - - IF any of these validations fail, then the entire sequence of documents is INVALID. - Not just the current document. - - ##### Example of a Valid Chain - - ``` mermaid - \(_chainValidMermaid) - ``` - - ##### Example of an Invalid Chain - - Either of the two documents being present invalidates the data - in the entire chain, - as they are signed by the author of the chain. - - ``` mermaid - \(_chainInvalidMermaid) - ``` - - ##### Example of a Fraudulent Chain Document - - The invalid document does not invalidate the chain, - as its not signed by the author of the chained documents. - - ``` mermaid - \(_chainFraudulentMermaid) - ``` + validation: string | *""" + \(_chain_validation_common) """ } } @@ -371,6 +388,7 @@ metadata: headers: { parameters: required: "optional" parameters: type: #parameterDocNamesList chain: required: "optional" + chain: validation: _chain_validation_complete } // Preferred display order diff --git a/specs/generators/packages/spec/README.md b/specs/generators/packages/spec/README.md index e69de29bb2d..1b94098f258 100644 --- a/specs/generators/packages/spec/README.md +++ b/specs/generators/packages/spec/README.md @@ -0,0 +1 @@ +# Interpreted Specification Library diff --git a/specs/generators/packages/spec/src/spec/base_types.py b/specs/generators/packages/spec/src/spec/base_types.py index 3990fbdb690..7a076e9b9d5 100644 --- a/specs/generators/packages/spec/src/spec/base_types.py +++ b/specs/generators/packages/spec/src/spec/base_types.py @@ -12,6 +12,8 @@ class DocTypeId(RootModel[UUID4]): root: UUID4 # name: uuid_str class Config: + """Config.""" + frozen = True @computed_field diff --git a/specs/generators/packages/spec/src/spec/cddl/cose.py b/specs/generators/packages/spec/src/spec/cddl/cose.py index 294655ddfc0..566a91dbae6 100644 --- a/specs/generators/packages/spec/src/spec/cddl/cose.py +++ b/specs/generators/packages/spec/src/spec/cddl/cose.py @@ -30,15 +30,11 @@ class GenericHeader(BaseModel): model_config = ConfigDict(extra="forbid") - @computed_field - @property def name(self) -> str: """Get headers name.""" return self._name - @computed_field - @name.setter - def name(self, name: str) -> None: + def set_name(self, name: str) -> None: """Set headers name.""" self._name = name @@ -74,7 +70,7 @@ def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 # Set Cose Header Names for name, header in self.root.items(): - header.name = name + header.set_name(name) def get(self, name: str) -> CoseHeader: """Get a Cose Header by its name.""" diff --git a/specs/generators/packages/spec/src/spec/cddl/definition.py b/specs/generators/packages/spec/src/spec/cddl/definition.py index c2a5ebf4cd1..704b11ae6e0 100644 --- a/specs/generators/packages/spec/src/spec/cddl/definition.py +++ b/specs/generators/packages/spec/src/spec/cddl/definition.py @@ -3,7 +3,7 @@ import re import typing -from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, RootModel, computed_field +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, RootModel class CDDLDefinition(BaseModel): @@ -18,13 +18,12 @@ class CDDLDefinition(BaseModel): model_config = ConfigDict(extra="forbid") - @computed_field - def name(self) -> str: # type: ignore[obscured] + def name(self) -> str: """Name Of the Parameter.""" return self._name - @name.setter # type: ignore[prop-decorator] - def name(self, val: str) -> None: + def set_name(self, val: str) -> None: + """Set Name.""" self._name = val @@ -38,7 +37,7 @@ def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 super().model_post_init(context) for def_name, value in self.root.items(): - value.name = def_name + value.set_name(def_name) def get(self, name: str) -> CDDLDefinition: """Get a CDDL Definition.""" @@ -49,7 +48,7 @@ def add(self, definition: CDDLDefinition | list[CDDLDefinition]) -> None: if isinstance(definition, CDDLDefinition): definition = [definition] for this_def in definition: - self.root[this_def.name] = this_def + self.root[this_def.name()] = this_def @staticmethod def _add_cddl_comments(comment: str) -> tuple[str, bool]: diff --git a/specs/generators/packages/spec/src/spec/doc_types.py b/specs/generators/packages/spec/src/spec/doc_types.py index 9563d67f4e3..225602d3f72 100644 --- a/specs/generators/packages/spec/src/spec/doc_types.py +++ b/specs/generators/packages/spec/src/spec/doc_types.py @@ -21,7 +21,7 @@ def formatted_names(self, *, prefix: str = "", separator: str = "/", suffix: str type_names: list[str] = [self._base_types.name(sub_type) for sub_type in self.root] return f"{prefix}{separator.join(type_names)}{suffix}" - def formatted_ids( + def formatted_ids( # noqa: PLR0913 self, *, prefix: str = "[", @@ -35,5 +35,5 @@ def formatted_ids( id_strings: list[str] = ( [uuid.as_cbor for uuid in self.root] if cbor else [uuid.as_uuid_str for uuid in self.root] ) - id_strings = [f"{start_quote}{id}{end_quote}" for id in id_strings] + id_strings = [f"{start_quote}{ids}{end_quote}" for ids in id_strings] return f"{prefix}{separator.join(id_strings)}{suffix}" diff --git a/specs/generators/packages/spec/src/spec/forms/element/element.py b/specs/generators/packages/spec/src/spec/forms/element/element.py index 86ee64d5fd7..c40046faabe 100644 --- a/specs/generators/packages/spec/src/spec/forms/element/element.py +++ b/specs/generators/packages/spec/src/spec/forms/element/element.py @@ -19,22 +19,21 @@ class Element(BaseModel): model_config = ConfigDict(extra="forbid") - @computed_field - def name(self) -> str: # type: ignore[obscured] + def name(self) -> str: """Name Of the Parameter.""" return self._name - @name.setter # type: ignore[prop-decorator] - def name(self, val: str) -> None: + def set_name(self, val: str) -> None: + """Set Name.""" self._name = val - @computed_field() + @computed_field @cached_property def json_definition(self) -> dict[str, Any]: """Json Definition.""" return self.definition - @computed_field() + @computed_field @cached_property def example(self) -> dict[str, Any]: """Generate an example of the definition.""" diff --git a/specs/generators/packages/spec/src/spec/forms/element/parameters.py b/specs/generators/packages/spec/src/spec/forms/element/parameters.py index 4245c797d9d..8d42dc775e6 100644 --- a/specs/generators/packages/spec/src/spec/forms/element/parameters.py +++ b/specs/generators/packages/spec/src/spec/forms/element/parameters.py @@ -28,27 +28,26 @@ class Parameter(BaseModel): minimum: int | None = Field(default=None) maximum: int | None = Field(default=None) example: Any = Field(default=None) + _name: str = PrivateAttr(default="Unknown") _element_name: str = PrivateAttr(default="Unknown") model_config = ConfigDict(extra="forbid") - @computed_field - def element_name(self) -> str: # type: ignore[obscured] + def element_name(self) -> str: """Name Of the Parameters Element Type.""" - return self._name + return self._element_name - @element_name.setter # type: ignore[prop-decorator] - def element_name(self, val: str) -> None: - self._name = val + def set_element_name(self, val: str) -> None: + """Set Element Name.""" + self._element_name = val - @computed_field - def name(self) -> str: # type: ignore[obscured] + def name(self) -> str: """Name Of the Parameter.""" return self._name - @name.setter # type: ignore[prop-decorator] - def name(self, val: str) -> None: + def set_name(self, val: str) -> None: + """Set Name.""" self._name = val def example_kv(self, index: int = 0) -> tuple[str, Any]: @@ -67,25 +66,24 @@ class Parameters(RootModel[dict[str, Parameter]]): root: dict[str, Parameter] _element_name: str = PrivateAttr(default="Unknown") - @computed_field - def element_name(self) -> str | None: # type: ignore[obscured] + def element_name(self) -> str | None: """Name Of the Parameters Element Type.""" - return self._name + return self._element_name - @element_name.setter # type: ignore[prop-decorator] - def element_name(self, val: str) -> None: - self._name = val + def set_element_name(self, val: str) -> None: + """Set Element Name.""" + self._element_name = val for name, value in self.root.items(): - value.element_name = name + value.set_element_name(name) def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 """Extra setup after we deserialize.""" super().model_post_init(context) for name, value in self.root.items(): - value.name = name + value.set_name(name) - @computed_field() + @computed_field @cached_property def example(self) -> dict[str, Any]: """Generate an example of the definition.""" diff --git a/specs/generators/packages/spec/src/spec/forms/template.py b/specs/generators/packages/spec/src/spec/forms/template.py index 40ed2459dd3..8c0e94993cd 100644 --- a/specs/generators/packages/spec/src/spec/forms/template.py +++ b/specs/generators/packages/spec/src/spec/forms/template.py @@ -19,9 +19,9 @@ def model_post_init(self, context: typing.Any) -> None: # noqa: ANN401 super().model_post_init(context) for def_name, value in self.root.items(): - value.name = def_name + value.set_name(def_name) - @computed_field() + @computed_field @cached_property def json_definition(self) -> dict[str, Any]: """Json Definition.""" @@ -32,7 +32,7 @@ def json_definition(self) -> dict[str, Any]: return definitions - @computed_field() + @computed_field @cached_property def example(self) -> dict[str, Any]: """Generate an example of the definitions.""" diff --git a/specs/generators/packages/spec/src/spec/metadata.py b/specs/generators/packages/spec/src/spec/metadata.py index 27bfbb31f46..a9aec5b08e4 100644 --- a/specs/generators/packages/spec/src/spec/metadata.py +++ b/specs/generators/packages/spec/src/spec/metadata.py @@ -22,14 +22,15 @@ class MetadataHeader(GenericHeader): raw_linked_refs: list[str] | None = Field(alias="linked_refs", default=None) # Not deserialized, must be supplied. - doc_name: str | None = Field(default=None) + _name: str = PrivateAttr(default="Unknown") + _doc_name: str | None = PrivateAttr(default=None) model_config = ConfigDict(extra="forbid") def set_name(self, name: str, doc_name: str | None = None) -> None: """Set the name properties.""" - self.name = name - self.doc_name = doc_name + self._name = name + self._doc_name = doc_name @staticmethod def fix_list(fix: str | list[str] | None) -> list[str]: @@ -40,13 +41,13 @@ def fix_list(fix: str | list[str] | None) -> list[str]: fix = [fix] return fix - @computed_field() + @computed_field @cached_property def type(self) -> list[str]: """Type.""" return self.fix_list(self.raw_type) - @computed_field() + @computed_field @cached_property def linked_refs(self) -> list[str]: """Linked Refs.""" @@ -60,8 +61,8 @@ def get_validation(self) -> str: for ref in self.linked_refs: validation += f""" * The Document referenced by `{ref}` - * MUST contain `{self.name}` metadata; AND - * MUST match the referencing documents `{self.name}` value.""" + * MUST contain `{self._name}` metadata; AND + * MUST match the referencing documents `{self._name}` value.""" return validation.strip() @@ -74,7 +75,7 @@ def metadata_as_markdown(self, *, doc_types: DocType | None = None) -> str: field_title_level = "###" field_display = f""" -{field_title_level} `{self.name}` +{field_title_level} `{self._name}` | Parameter | Value | @@ -84,7 +85,7 @@ def metadata_as_markdown(self, *, doc_types: DocType | None = None) -> str: if not self.is_excluded(): field_display += f"| Format | `{self.format}` |\n" - if self.name == "type" and doc_types is not None: + if self._name == "type" and doc_types is not None: # Display the actual documents type values formatted_id = doc_types.formatted_ids( prefix="", start_quote="`", end_quote="`", separator=",
", suffix="", cbor=False @@ -107,7 +108,7 @@ def metadata_as_markdown(self, *, doc_types: DocType | None = None) -> str: field_display += f""" {self.description} -{field_title_level}# `{self.name}` Validation +{field_title_level}# `{self._name}` Validation {self.get_validation()} """ diff --git a/specs/generators/src/docs/doc_generator.py b/specs/generators/src/docs/doc_generator.py index 968f63f737a..aa48adf3301 100644 --- a/specs/generators/src/docs/doc_generator.py +++ b/specs/generators/src/docs/doc_generator.py @@ -274,14 +274,14 @@ def generate(self) -> bool: # the formatted markdown to pass lints. # self._filedata = f""" # # {self._filedata}""" # self._filedata = mdformat.text( # type: ignore # noqa: PGH003 # self._filedata, options={"number": True, "wrap": "keep"}, extensions=["mkdocs"] - # ) - # else: + # ) # noqa: ERA001, RUF100 + # else: # noqa: ERA001 self.strip_end_whitespace() return True diff --git a/specs/generators/src/docs/spec_md.py b/specs/generators/src/docs/spec_md.py index f30c0bef7b6..0d4f57a1c1e 100644 --- a/specs/generators/src/docs/spec_md.py +++ b/specs/generators/src/docs/spec_md.py @@ -39,7 +39,7 @@ def header_parameter_doc(self, header: CoseHeader) -> str: header_format_display += value_entry return f""" -#### `{header.name}` +#### `{header.name()}` {header.description} diff --git a/specs/generators/src/docs/template_example_schema_json.py b/specs/generators/src/docs/template_example_schema_json.py index 5181bf7fa94..d85cf46a17d 100644 --- a/specs/generators/src/docs/template_example_schema_json.py +++ b/specs/generators/src/docs/template_example_schema_json.py @@ -33,15 +33,8 @@ def generate(self) -> bool: "properties": self._spec.form_template.example, } - # "definitions": {{ - # {self._spec.template_json_schema_defs.json_definition} - # }}, - # }} - # """ template_schema = json.dumps(schema, indent=4) jsonschema.Draft202012Validator.check_schema(schema) - # validator = jsonschema.Draft7Validator(schema, format_checker=jsonschema.draft7_format_checker) # noqa: ERA001 - # validator.validate(schema) # noqa: ERA001 self._filedata = template_schema diff --git a/specs/generators/src/docs/templates_md.py b/specs/generators/src/docs/templates_md.py index 905647cdfca..5685a35c2f3 100644 --- a/specs/generators/src/docs/templates_md.py +++ b/specs/generators/src/docs/templates_md.py @@ -22,4 +22,8 @@ def generate(self) -> bool: if not example_schema.save_or_validate(): return False + self._filedata = """ +# Templates" +""" + return super().generate() diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 802aa23d7db..05fafccfd36 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -402,7 +402,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -513,7 +513,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -632,7 +632,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -751,7 +751,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -869,7 +869,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -998,7 +998,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -1135,7 +1135,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -1275,7 +1275,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -1407,7 +1407,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -1540,7 +1540,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -1671,7 +1671,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -1791,7 +1791,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -1988,7 +1988,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "excluded", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -3362,7 +3362,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "optional", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n``` mermaid\n classDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n``` mermaid\n classDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermedisate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n\n``` mermaid\n\tclassDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n\n``` mermaid\n\tclassDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n\n``` mermaid\n\tclassDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```\n" }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", From 6bfabdc87c9ff34e4a540aef10c0222389b94a81 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 21 Jun 2025 21:08:27 +0700 Subject: [PATCH 22/42] fix(docs): lint issues --- .config/dictionaries/project.dic | 1 + specs/generators/pyproject.toml | 4 ++-- specs/generators/uv.lock | 16 ++++++++-------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index 7977585af58..e25e6dc93b7 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -178,6 +178,7 @@ mitigations mkcron mkdelay mkdirat +mkdocs Mmap moderations moka diff --git a/specs/generators/pyproject.toml b/specs/generators/pyproject.toml index 0ad23be3423..2d3ee184924 100644 --- a/specs/generators/pyproject.toml +++ b/specs/generators/pyproject.toml @@ -6,8 +6,8 @@ dependencies = [ "jsonschema[format]>=4.24.0", "mdformat>=0.7.22", "mdformat-mkdocs>=4.3.0", - "pydantic>=2.11.6", - "pydot>=4.0.0", + "pydantic>=2.11.7", + "pydot>=4.0.1", "rich>=14.0.0", "rich-argparse>=1.7.1", "spec", diff --git a/specs/generators/uv.lock b/specs/generators/uv.lock index b8c82da9e47..f8da6b8557a 100644 --- a/specs/generators/uv.lock +++ b/specs/generators/uv.lock @@ -68,8 +68,8 @@ requires-dist = [ { name = "jsonschema", extras = ["format"], specifier = ">=4.24.0" }, { name = "mdformat", specifier = ">=0.7.22" }, { name = "mdformat-mkdocs", specifier = ">=4.3.0" }, - { name = "pydantic", specifier = ">=2.11.6" }, - { name = "pydot", specifier = ">=4.0.0" }, + { name = "pydantic", specifier = ">=2.11.7" }, + { name = "pydot", specifier = ">=4.0.1" }, { name = "rich", specifier = ">=14.0.0" }, { name = "rich-argparse", specifier = ">=1.7.1" }, { name = "spec", editable = "packages/spec" }, @@ -243,7 +243,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.6" +version = "2.11.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -251,9 +251,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ef/8f/9af0f46acc943b8c4592d06523f26a150acf6e6e37e8bd5f0ace925e996d/pydantic-2.11.6.tar.gz", hash = "sha256:12b45cfb4af17e555d3c6283d0b55271865fb0b43cc16dd0d52749dc7abf70e7", size = 787868, upload-time = "2025-06-13T09:00:29.595Z" } +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/05/11/7912a9a194ee4ea96520740d1534bc31a03a4a59d62e1d7cac9461d3f379/pydantic-2.11.6-py3-none-any.whl", hash = "sha256:a24478d2be1b91b6d3bc9597439f69ed5e87f68ebd285d86f7c7932a084b72e7", size = 444718, upload-time = "2025-06-13T09:00:27.134Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, ] [[package]] @@ -286,14 +286,14 @@ wheels = [ [[package]] name = "pydot" -version = "4.0.0" +version = "4.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyparsing" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/c3/6034ed1ebf2e3ba95a0e35fa7c43104e40444c0ed2b5325702c63e824dbf/pydot-4.0.0.tar.gz", hash = "sha256:12f16493337cade2f7631b87c8ccd299ba2e251f3ee5d0732a058df2887afe97", size = 161793, upload-time = "2025-05-04T11:13:03.214Z" } +sdist = { url = "https://files.pythonhosted.org/packages/50/35/b17cb89ff865484c6a20ef46bf9d95a5f07328292578de0b295f4a6beec2/pydot-4.0.1.tar.gz", hash = "sha256:c2148f681c4a33e08bf0e26a9e5f8e4099a82e0e2a068098f32ce86577364ad5", size = 162594, upload-time = "2025-06-17T20:09:56.454Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/16/984c0cf5073a23154b1f95c9d131b14c9fea83bfadae4ba8fc169daded11/pydot-4.0.0-py3-none-any.whl", hash = "sha256:cf86e13a6cfe2a96758a9702537f77e0ac1368db8ef277b4d3b34473ea425c97", size = 37535, upload-time = "2025-05-04T11:13:01.458Z" }, + { url = "https://files.pythonhosted.org/packages/7e/32/a7125fb28c4261a627f999d5fb4afff25b523800faed2c30979949d6facd/pydot-4.0.1-py3-none-any.whl", hash = "sha256:869c0efadd2708c0be1f916eb669f3d664ca684bc57ffb7ecc08e70d5e93fee6", size = 37087, upload-time = "2025-06-17T20:09:55.25Z" }, ] [[package]] From b9e9faeed0c167a6fc3f9c4b82b4abb34311910a Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 21 Jun 2025 21:24:49 +0700 Subject: [PATCH 23/42] fix(docs): CI build issues --- rust/signed_doc/src/validator/mod.rs | 2 +- specs/Earthfile | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/rust/signed_doc/src/validator/mod.rs b/rust/signed_doc/src/validator/mod.rs index 0c755bdcb5a..4bed4304a89 100644 --- a/rust/signed_doc/src/validator/mod.rs +++ b/rust/signed_doc/src/validator/mod.rs @@ -104,7 +104,7 @@ fn document_rules_init() -> HashMap { .with_draft(jsonschema::Draft::Draft7) .build( &serde_json::from_str(include_str!( - "./../../../../specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json" + "./../../../../specs/definitions/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json" )) .expect("Must be a valid json file"), ) diff --git a/specs/Earthfile b/specs/Earthfile index bccf4b46d2c..0621e885816 100644 --- a/specs/Earthfile +++ b/specs/Earthfile @@ -8,7 +8,7 @@ IMPORT ../docs AS docs # Get cue binary cue-bin: - FROM cuelang/cue:0.12.0 + FROM cuelang/cue:0.13.1 SAVE ARTIFACT /usr/bin/cue @@ -30,18 +30,20 @@ src: # Check that the generated signed docs data matches the src. check: FROM +src - RUN cue fmt --check --files . - RUN cue vet ./signed_docs/docs:signed_docs signed_doc.json + RUN cue fmt --check -s --files ./definitions + RUN cd definitions; cue vet ./signed_docs/docs:signed_docs ../signed_doc.json # Check the the generated signed docs documentation matches the generated signed docs data check-docs-generation: FROM python-ci+python-base - COPY ./gen_docs gen_docs + COPY ./generators generators COPY +src/signed_doc.json . COPY --dir docs+generated-signed-docs-pages/signed_doc signed_doc # Check our validation code actually works properly - RUN cd gen_docs; \ - ./main.py -o "../signed_doc" ../signed_doc.json + RUN cd generators; \ + uv run validator ../signed_doc.json + RUN cd generators; \ + uv run docs -o "../signed_doc" ../signed_doc.json # Regenerate - using the builder From 27a258e0153dcab3b758de52f8bc6f8a516a449b Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 22 Jun 2025 21:17:15 +0700 Subject: [PATCH 24/42] docs(docs): wip --- .config/dictionaries/project.dic | 1 + .../08_concepts/signed_doc/diagrams/all.dot | 104 +++--- .../signed_doc/diagrams/brand_parameters.dot | 48 +-- .../diagrams/campaign_parameters.dot | 48 +-- .../diagrams/category_parameters.dot | 48 +-- .../signed_doc/diagrams/proposal.dot | 12 +- .../signed_doc/diagrams/proposal_comment.dot | 12 +- ...dot => proposal_comment_form_template.dot} | 26 +- ...roposal_comment_presentation_template.dot} | 159 ++++----- ...emplate.dot => proposal_form_template.dot} | 26 +- ...dot => proposal_presentation_template.dot} | 158 ++++----- .../08_concepts/signed_doc/docs/proposal.md | 2 +- .../signed_doc/docs/proposal_comment.md | 2 +- ...e.md => proposal_comment_form_template.md} | 59 ++-- ...proposal_comment_presentation_template.md} | 55 ++-- ..._template.md => proposal_form_template.md} | 55 ++-- ...e.md => proposal_presentation_template.md} | 55 ++-- .../08_concepts/signed_doc/metadata.md | 16 +- .../08_concepts/signed_doc/types.md | 11 +- specs/Earthfile | 2 +- specs/Justfile | 3 +- specs/definitions/signed_docs/docs/all.cue | 51 ++- .../docs/generic_form_template.cue | 90 ++++++ .../docs/generic_presentation_template.cue | 68 ++++ .../definitions/signed_docs/docs/proposal.cue | 2 +- .../signed_docs/docs/proposal_comment.cue | 2 +- .../docs/proposal_comment_form_template.cue | 14 + .../docs/proposal_comment_meta_template.cue | 61 ---- ...proposal_comment_presentation_template.cue | 13 + .../docs/proposal_comment_template.cue | 64 ---- .../docs/proposal_form_template.cue | 15 + .../docs/proposal_meta_template.cue | 62 ---- .../docs/proposal_presentation_template.cue | 13 + .../signed_docs/docs/proposal_template.cue | 68 ---- specs/definitions/signed_docs/metadata.cue | 144 +-------- .../signed_docs/metadata_chain.cue | 89 ++++++ .../signed_docs/metadata_template.cue | 35 ++ .../definitions/signed_docs/metadata_ver.cue | 53 +++ specs/definitions/signed_docs/signed_doc.cue | 9 +- specs/signed_doc.json | 302 +++++++++--------- 40 files changed, 989 insertions(+), 1068 deletions(-) rename docs/src/architecture/08_concepts/signed_doc/diagrams/{proposal_comment_meta_template.dot => proposal_comment_form_template.dot} (86%) rename docs/src/architecture/08_concepts/signed_doc/diagrams/{proposal_comment_template.dot => proposal_comment_presentation_template.dot} (67%) rename docs/src/architecture/08_concepts/signed_doc/diagrams/{proposal_meta_template.dot => proposal_form_template.dot} (88%) rename docs/src/architecture/08_concepts/signed_doc/diagrams/{proposal_template.dot => proposal_presentation_template.dot} (68%) rename docs/src/architecture/08_concepts/signed_doc/docs/{proposal_comment_template.md => proposal_comment_form_template.md} (74%) rename docs/src/architecture/08_concepts/signed_doc/docs/{proposal_meta_template.md => proposal_comment_presentation_template.md} (73%) rename docs/src/architecture/08_concepts/signed_doc/docs/{proposal_template.md => proposal_form_template.md} (80%) rename docs/src/architecture/08_concepts/signed_doc/docs/{proposal_comment_meta_template.md => proposal_presentation_template.md} (74%) create mode 100644 specs/definitions/signed_docs/docs/generic_form_template.cue create mode 100644 specs/definitions/signed_docs/docs/generic_presentation_template.cue create mode 100644 specs/definitions/signed_docs/docs/proposal_comment_form_template.cue delete mode 100644 specs/definitions/signed_docs/docs/proposal_comment_meta_template.cue create mode 100644 specs/definitions/signed_docs/docs/proposal_comment_presentation_template.cue delete mode 100644 specs/definitions/signed_docs/docs/proposal_comment_template.cue create mode 100644 specs/definitions/signed_docs/docs/proposal_form_template.cue delete mode 100644 specs/definitions/signed_docs/docs/proposal_meta_template.cue create mode 100644 specs/definitions/signed_docs/docs/proposal_presentation_template.cue delete mode 100644 specs/definitions/signed_docs/docs/proposal_template.cue create mode 100644 specs/definitions/signed_docs/metadata_chain.cue create mode 100644 specs/definitions/signed_docs/metadata_template.cue create mode 100644 specs/definitions/signed_docs/metadata_ver.cue diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index e25e6dc93b7..7fe0292a9cf 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -81,6 +81,7 @@ elgamal encryptor Errno Eternl +evalv excalidraw explicitely extn 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 af9f30cf9e3..d9e0d6cdbe9 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot @@ -267,7 +267,7 @@ digraph "All" { - +
templateProposal Comment TemplateProposal Comment Form Template
@@ -448,13 +448,13 @@ digraph "All" { ]; - "Proposal Template" [ - id="Proposal Template"; + "Proposal Form Template" [ + id="Proposal Form Template"; label=< - @@ -498,17 +498,7 @@ digraph "All" { - - - - @@ -618,13 +608,13 @@ digraph "All" { ]; - "Proposal Comment Template" [ - id="Proposal Comment Template"; + "Proposal Comment Form Template" [ + id="Proposal Comment Form Template"; label=<
- Proposal Template + + Proposal Form Template
- - - - - -
templateProposal Meta Template
-
+ @@ -577,7 +567,7 @@ digraph "All" {
parameters
- +
templateProposal TemplateProposal Form Template
- @@ -668,17 +658,7 @@ digraph "All" { - - - - @@ -758,13 +738,13 @@ digraph "All" { ]; - "Proposal Meta Template" [ - id="Proposal Meta Template"; + "Proposal Moderation Action" [ + id="Proposal Moderation Action"; label=<
- Proposal Comment Template + + Proposal Comment Form Template
- - - - - -
templateProposal Comment Meta Template
-
+ @@ -693,13 +673,13 @@ digraph "All" { ]; - "Proposal Comment Meta Template" [ - id="Proposal Comment Meta Template"; + "Proposal Comment Presentation Template" [ + id="Proposal Comment Presentation Template"; label=<
parameters
- @@ -717,7 +697,7 @@ digraph "All" {
- Proposal Comment Meta Template + + Proposal Comment Presentation Template
- +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
b679ded3-0e7c-41ba-89f8-da62a17898ea
7808d2ba-d511-40af-84e8-c0d1625fdfdc
cb99b9bd-681a-49d8-9836-89107c02e8ef
b679ded3-0e7c-41ba-89f8-da62a17898ea
7808d2ba-d511-40af-84e8-c0d1625fdfdc
- @@ -772,7 +752,7 @@ digraph "All" {
- Proposal Meta Template + + Proposal Moderation Action
- +
content typeapplication/schema+jsonapplication/json
@@ -782,7 +762,7 @@ digraph "All" { - +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
7808d2ba-d511-40af-84e8-c0d1625fdfdc
5e60e623-ad02-4a1b-a1ac-406db978ee48
7808d2ba-d511-40af-84e8-c0d1625fdfdc
a5d232b8-5e03-4117-9afd-be32b878fcdd
@@ -808,11 +788,11 @@ digraph "All" { - + - - + +
parametersBrand Parameters
Campaign Parameters
Category Parameters
refProposal
@@ -823,13 +803,13 @@ digraph "All" { ]; - "Proposal Moderation Action" [ - id="Proposal Moderation Action"; + "Proposal Presentation Template" [ + id="Proposal Presentation Template"; label=< - @@ -837,7 +817,7 @@ digraph "All" {
- Proposal Moderation Action + + Proposal Presentation Template
- +
content typeapplication/jsonapplication/schema+json
@@ -847,7 +827,7 @@ digraph "All" { - +
type5e60e623-ad02-4a1b-a1ac-406db978ee48
7808d2ba-d511-40af-84e8-c0d1625fdfdc
a5d232b8-5e03-4117-9afd-be32b878fcdd
cb99b9bd-681a-49d8-9836-89107c02e8ef
7808d2ba-d511-40af-84e8-c0d1625fdfdc
@@ -873,11 +853,11 @@ digraph "All" { - + - - + +
refProposalparametersBrand Parameters
Campaign Parameters
Category Parameters
@@ -967,19 +947,17 @@ digraph "All" { "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"] - "Proposal":"template":e -> "Proposal Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Proposal":"template":e -> "Proposal Form 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="*"] - "Proposal Comment":"template":e -> "Proposal Comment Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Proposal Comment":"template":e -> "Proposal Comment Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Proposal Comment":"reply":e -> "Proposal Comment":"title":n [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Proposal Comment":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Comment Meta Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Comment Template":"template":e -> "Proposal Comment Meta Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Proposal Comment Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Meta Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Comment Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Comment Presentation Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Moderation Action":"ref":e -> "Proposal":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Proposal Presentation Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Submission Action":"ref":e -> "Proposal":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Proposal Submission Action":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Template":"template":e -> "Proposal Meta Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Proposal Template":"parameters":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/brand_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters.dot index ec4702ddac4..e9d334cd427 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 @@ -134,13 +134,13 @@ Relationships" ]; - "Proposal Comment Meta Template" [ - id="Proposal Comment Meta Template"; + "Proposal Comment Form Template" [ + id="Proposal Comment Form Template"; label=< - @@ -149,13 +149,13 @@ Relationships" ]; - "Proposal Comment Template" [ - id="Proposal Comment Template"; + "Proposal Comment Presentation Template" [ + id="Proposal Comment Presentation Template"; label=<
- Proposal Comment Meta Template + + Proposal Comment Form Template
- @@ -164,13 +164,13 @@ Relationships" ]; - "Proposal Meta Template" [ - id="Proposal Meta Template"; + "Proposal Form Template" [ + id="Proposal Form Template"; label=<
- Proposal Comment Template + + Proposal Comment Presentation Template
- @@ -179,13 +179,13 @@ Relationships" ]; - "Proposal Submission Action" [ - id="Proposal Submission Action"; + "Proposal Presentation Template" [ + id="Proposal Presentation Template"; label=<
- Proposal Meta Template + + Proposal Form Template
- @@ -194,13 +194,13 @@ Relationships" ]; - "Proposal Template" [ - id="Proposal Template"; + "Proposal Submission Action" [ + id="Proposal Submission Action"; label=<
- Proposal Submission Action + + Proposal Presentation Template
- @@ -213,9 +213,9 @@ Relationships" "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"] - "Proposal Comment Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Meta Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Comment Form Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Comment Presentation Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Form Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Presentation Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Submission Action":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal 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 f21afdeadf9..9286456e868 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 @@ -159,13 +159,13 @@ Relationships" ]; - "Proposal Comment Meta Template" [ - id="Proposal Comment Meta Template"; + "Proposal Comment Form Template" [ + id="Proposal Comment Form Template"; label=<
- Proposal Template + + Proposal Submission Action
- @@ -174,13 +174,13 @@ Relationships" ]; - "Proposal Comment Template" [ - id="Proposal Comment Template"; + "Proposal Comment Presentation Template" [ + id="Proposal Comment Presentation Template"; label=<
- Proposal Comment Meta Template + + Proposal Comment Form Template
- @@ -189,13 +189,13 @@ Relationships" ]; - "Proposal Meta Template" [ - id="Proposal Meta Template"; + "Proposal Form Template" [ + id="Proposal Form Template"; label=<
- Proposal Comment Template + + Proposal Comment Presentation Template
- @@ -204,13 +204,13 @@ Relationships" ]; - "Proposal Submission Action" [ - id="Proposal Submission Action"; + "Proposal Presentation Template" [ + id="Proposal Presentation Template"; label=<
- Proposal Meta Template + + Proposal Form Template
- @@ -219,13 +219,13 @@ Relationships" ]; - "Proposal Template" [ - id="Proposal Template"; + "Proposal Submission Action" [ + id="Proposal Submission Action"; label=<
- Proposal Submission Action + + Proposal Presentation Template
- @@ -239,9 +239,9 @@ Relationships" "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"] - "Proposal Comment Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Meta Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Comment Form Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Comment Presentation Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Form Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Presentation Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Submission Action":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal 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 b6a2aa470a2..7e846b3224d 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 @@ -144,13 +144,13 @@ Relationships" ]; - "Proposal Comment Meta Template" [ - id="Proposal Comment Meta Template"; + "Proposal Comment Form Template" [ + id="Proposal Comment Form Template"; label=<
- Proposal Template + + Proposal Submission Action
- @@ -159,13 +159,13 @@ Relationships" ]; - "Proposal Comment Template" [ - id="Proposal Comment Template"; + "Proposal Comment Presentation Template" [ + id="Proposal Comment Presentation Template"; label=<
- Proposal Comment Meta Template + + Proposal Comment Form Template
- @@ -174,13 +174,13 @@ Relationships" ]; - "Proposal Meta Template" [ - id="Proposal Meta Template"; + "Proposal Form Template" [ + id="Proposal Form Template"; label=<
- Proposal Comment Template + + Proposal Comment Presentation Template
- @@ -189,13 +189,13 @@ Relationships" ]; - "Proposal Submission Action" [ - id="Proposal Submission Action"; + "Proposal Presentation Template" [ + id="Proposal Presentation Template"; label=<
- Proposal Meta Template + + Proposal Form Template
- @@ -204,13 +204,13 @@ Relationships" ]; - "Proposal Template" [ - id="Proposal Template"; + "Proposal Submission Action" [ + id="Proposal Submission Action"; label=<
- Proposal Submission Action + + Proposal Presentation Template
- @@ -223,9 +223,9 @@ Relationships" "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"] - "Proposal Comment Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Meta Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Comment Form Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Comment Presentation Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Form Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Presentation Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Submission Action":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal 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/proposal.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal.dot index d7140c8a110..3c708d521ed 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal.dot @@ -13,13 +13,13 @@ Relationships" - "Proposal Template" [ - id="Proposal Template"; + "Proposal Form Template" [ + id="Proposal Form Template"; label=<
- Proposal Template + + Proposal Submission Action
- @@ -82,7 +82,7 @@ Relationships"
- Proposal Template + + Proposal Form Template
- +
templateProposal TemplateProposal Form Template
@@ -219,7 +219,7 @@ Relationships" } - "Proposal":"template":e -> "Proposal Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Proposal":"template":e -> "Proposal Form 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":"title":e -> "Proposal":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Proposal Moderation Action":"title":e -> "Proposal":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment.dot index 983953798b1..376557c355b 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment.dot @@ -28,13 +28,13 @@ Relationships" ]; - "Proposal Comment Template" [ - id="Proposal Comment Template"; + "Proposal Comment Form Template" [ + id="Proposal Comment Form Template"; label=< - @@ -107,7 +107,7 @@ Relationships"
- Proposal Comment Template + + Proposal Comment Form Template
- +
templateProposal Comment TemplateProposal Comment Form Template
@@ -225,7 +225,7 @@ Relationships" } "Proposal Comment":"ref":e -> "Proposal":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Proposal Comment":"template":e -> "Proposal Comment Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Proposal Comment":"template":e -> "Proposal Comment Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Proposal Comment":"reply":e -> "Proposal Comment":"title":n [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Proposal Comment":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Comment Moderation Action":"title":e -> "Proposal Comment":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_meta_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_form_template.dot similarity index 86% rename from docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_meta_template.dot rename to docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_form_template.dot index 068613702ad..6644a8dd9ac 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_meta_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_form_template.dot @@ -1,11 +1,11 @@ -digraph "Proposal Comment Meta Template" { +digraph "Proposal Comment Form Template" { rankdir="LR" graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; labelloc="t" - label="Proposal Comment Meta Template + label="Proposal Comment Form Template Document Relationships" fontcolor="#1d71b8" fontsize=50 @@ -64,13 +64,13 @@ Document Relationships" } - "Proposal Comment Meta Template" [ - id="Proposal Comment Meta Template"; + "Proposal Comment Form Template" [ + id="Proposal Comment Form Template"; label=< - @@ -88,7 +88,7 @@ Document Relationships"
- Proposal Comment Meta Template + + Proposal Comment Form Template
- +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
b679ded3-0e7c-41ba-89f8-da62a17898ea
7808d2ba-d511-40af-84e8-c0d1625fdfdc
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
b679ded3-0e7c-41ba-89f8-da62a17898ea
7808d2ba-d511-40af-84e8-c0d1625fdfdc
@@ -129,13 +129,13 @@ Document Relationships" ]; - "Proposal Comment Template" [ - id="Proposal Comment Template"; + "Proposal Comment" [ + id="Proposal Comment"; label=< - @@ -144,6 +144,6 @@ Document Relationships" ]; - "Proposal Comment Meta Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Comment Template":"title":e -> "Proposal Comment Meta Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Proposal Comment Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal Comment":"title":e -> "Proposal Comment Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_presentation_template.dot similarity index 67% rename from docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_template.dot rename to docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_presentation_template.dot index 0b8ef6a746a..8d5ad2531c1 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_comment_presentation_template.dot @@ -1,40 +1,77 @@ -digraph "Proposal Comment Template" { +digraph "Proposal Comment Presentation Template" { rankdir="LR" graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; labelloc="t" - label="Proposal Comment Template -Document Relationships" + label="Proposal Comment Presentation +Template Document +Relationships" fontcolor="#1d71b8" fontsize=50 compound=true - "Proposal Comment Meta Template" [ - id="Proposal Comment Meta Template"; - label=< -
- Proposal Comment Template + + Proposal Comment
- - - + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 -
- Proposal Comment Meta Template -
- > - ]; + "Brand Parameters" [ + id="Brand Parameters"; + label=< + + + + + +
+ Brand Parameters +
+ > + ]; - "Proposal Comment Template" [ - id="Proposal Comment Template"; + "Campaign Parameters" [ + id="Campaign Parameters"; + label=< + + + + + +
+ Campaign Parameters +
+ > + ]; + + + "Category Parameters" [ + id="Category Parameters"; + label=< + + + + + +
+ Category Parameters +
+ > + ]; + + } + + "Proposal Comment Presentation Template" [ + id="Proposal Comment Presentation Template"; label=< - @@ -52,7 +89,7 @@ Document Relationships"
- Proposal Comment Template + + Proposal Comment Presentation Template
- +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
b679ded3-0e7c-41ba-89f8-da62a17898ea
7808d2ba-d511-40af-84e8-c0d1625fdfdc
cb99b9bd-681a-49d8-9836-89107c02e8ef
b679ded3-0e7c-41ba-89f8-da62a17898ea
7808d2ba-d511-40af-84e8-c0d1625fdfdc
@@ -78,17 +115,7 @@ Document Relationships" - - - - - - -
templateProposal Comment Meta Template
- - - - + @@ -103,73 +130,5 @@ Document Relationships" ]; - "Proposal Comment" [ - id="Proposal Comment"; - label=< -
parameters
- - - - -
- Proposal Comment -
- > - ]; - - - 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 -
- > - ]; - - } - - "Proposal Comment Template":"template":e -> "Proposal Comment Meta Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Proposal Comment Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Comment":"title":e -> "Proposal Comment Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Proposal Comment Presentation Template":"parameters":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/proposal_meta_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_form_template.dot similarity index 88% rename from docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_meta_template.dot rename to docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_form_template.dot index 9f51887bc37..4a4fe091ca2 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_meta_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_form_template.dot @@ -1,11 +1,11 @@ -digraph "Proposal Meta Template" { +digraph "Proposal Form Template" { rankdir="LR" graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; labelloc="t" - label="Proposal Meta Template + label="Proposal Form Template Document Relationships" fontcolor="#1d71b8" fontsize=50 @@ -64,13 +64,13 @@ Document Relationships" } - "Proposal Meta Template" [ - id="Proposal Meta Template"; + "Proposal Form Template" [ + id="Proposal Form Template"; label=< - @@ -88,7 +88,7 @@ Document Relationships"
- Proposal Meta Template + + Proposal Form Template
- +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
7808d2ba-d511-40af-84e8-c0d1625fdfdc
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
7808d2ba-d511-40af-84e8-c0d1625fdfdc
@@ -129,13 +129,13 @@ Document Relationships" ]; - "Proposal Template" [ - id="Proposal Template"; + "Proposal" [ + id="Proposal"; label=< - @@ -144,6 +144,6 @@ Document Relationships" ]; - "Proposal Meta Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal Template":"title":e -> "Proposal Meta Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Proposal Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Proposal":"title":e -> "Proposal Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_presentation_template.dot similarity index 68% rename from docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_template.dot rename to docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_presentation_template.dot index 7f43a69247e..e4d23f74a84 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/proposal_presentation_template.dot @@ -1,40 +1,76 @@ -digraph "Proposal Template" { +digraph "Proposal Presentation Template" { rankdir="LR" graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; labelloc="t" - label="Proposal Template Document -Relationships" + label="Proposal Presentation Template +Document Relationships" fontcolor="#1d71b8" fontsize=50 compound=true - "Proposal Meta Template" [ - id="Proposal Meta Template"; - label=< -
- Proposal Template + + Proposal
- - - + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 -
- Proposal Meta Template -
- > - ]; + "Brand Parameters" [ + id="Brand Parameters"; + label=< + + + + + +
+ Brand Parameters +
+ > + ]; - "Proposal Template" [ - id="Proposal Template"; + "Campaign Parameters" [ + id="Campaign Parameters"; + label=< + + + + + +
+ Campaign Parameters +
+ > + ]; + + + "Category Parameters" [ + id="Category Parameters"; + label=< + + + + + +
+ Category Parameters +
+ > + ]; + + } + + "Proposal Presentation Template" [ + id="Proposal Presentation Template"; label=< - @@ -52,7 +88,7 @@ Relationships"
- Proposal Template + + Proposal Presentation Template
- +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
7808d2ba-d511-40af-84e8-c0d1625fdfdc
cb99b9bd-681a-49d8-9836-89107c02e8ef
7808d2ba-d511-40af-84e8-c0d1625fdfdc
@@ -78,17 +114,7 @@ Relationships" - - - - - - -
templateProposal Meta Template
- - - - + @@ -103,73 +129,5 @@ Relationships" ]; - "Proposal" [ - id="Proposal"; - label=< -
parameters
- - - - -
- Proposal -
- > - ]; - - - 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 -
- > - ]; - - } - - "Proposal Template":"template":e -> "Proposal Meta Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Proposal Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Proposal":"title":e -> "Proposal Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Proposal Presentation Template":"parameters":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/docs/proposal.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md index a2563693899..d75bf311847 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md @@ -121,7 +121,7 @@ The document version must always be >= the document ID. | --- | --- | | Required | yes | | Format | [Document Reference](../metadata.md#document-reference) | -| Valid References | [Proposal Template](proposal_template.md) | +| Valid References | [Proposal Form Template](proposal_form_template.md) | Reference to the template used to create and/or validate this document. 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 1fe7c8db557..72be672baec 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 @@ -146,7 +146,7 @@ The following must be true for a valid reference: | --- | --- | | Required | yes | | Format | [Document Reference](../metadata.md#document-reference) | -| Valid References | [Proposal Comment Template](proposal_comment_template.md) | +| Valid References | [Proposal Comment Form Template](proposal_comment_form_template.md) | Reference to the template used to create and/or validate this document. 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_form_template.md similarity index 74% rename from docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md index 7a87d63693d..4385eed9a30 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_form_template.md @@ -1,21 +1,34 @@ -# Proposal Comment Template +# Proposal Comment Form Template ## Description -## Proposal Comment Template Document +## Proposal Comment Form Template Document -A Proposal Comment Template defines the allowed payload contents of a -linked proposal comment. +A Proposal Comment Form Template defines both: -Proposal comments themselves are intentionally general, however they may be -linked to a brand/campaign or category via the template used by the proposal. +* The data that is entered in the Form. +* Formatting hints for the collection of the data in a form. -The payload of a proposal comment is controlled by its template. +A Proposal Comment Form Template is a [JSON Schema][JSON Schema-2020-12] Document. + +Proposal Comment entry *SHOULD* use the hints when collecting +data defined by the Proposal Comment Form Template to provide a +consistent user interface. +It *CAN* also use those hints when re-displaying the full forms data. + +Alternatively a Proposal Comment Presentation Template can be used to +format the Proposal Comment data for presentation. + +The Proposal Comment Document is intentionally general, +however it may be linked to a brand/campaign or category +via the template used by the Proposal Comment. + +The payload of a Proposal Comment is controlled by its template. -```graphviz dot proposal_comment_template.dot.svg -{{ include_file('./../diagrams/proposal_comment_template.dot', indent=4) }} +```graphviz dot proposal_comment_form_template.dot.svg +{{ include_file('./../diagrams/proposal_comment_form_template.dot', indent=4) }} ``` @@ -99,22 +112,6 @@ The first version of the document must set [`ver`](../metadata.md#ver) == [`id`] The document version must always be >= the document ID. -### [`template`](../metadata.md#template) - - -| Parameter | Value | -| --- | --- | -| Required | optional | -| Format | [Document Reference](../metadata.md#document-reference) | -| Valid References | [Proposal Comment Meta Template](proposal_comment_meta_template.md) | - -Reference to the template used to create and/or validate this document. - -#### [`template`](../metadata.md#template) Validation - -In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields, -The document payload is not valid if it does not validate completely against the referenced template. - ### [`parameters`](../metadata.md#parameters) @@ -125,6 +122,7 @@ The document payload is not valid if it does not validate completely against the | Valid References | [Brand Parameters](brand_parameters.md) | | | [Campaign Parameters](campaign_parameters.md) | | | [Category Parameters](category_parameters.md) | +| Linked Reference Metadata | [`template`](#template) | A reference to the Parameters Document this document lies under. @@ -134,10 +132,15 @@ In addition to the validation performed for [Document Reference](../metadata.md# * Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the [`parameters`](../metadata.md#parameters) of the referencing document. +* The Document referenced by [`template`](../metadata.md#template) + * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND + * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. ## Payload -[JSON Schema][JSON Schema-2020-12] document which defines the content of the Proposal Comments. +[JSON Schema][JSON Schema-2020-12] document which defines the valid contents and +formatting hints for the collection of data for a +Proposal Comment Document. ## Signers @@ -170,6 +173,10 @@ New versions of this document may be published by: * Use generalized parameters. +#### 0.04 (2025-05-05) + +* Generalize the Form Template definitions. + [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode 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_comment_presentation_template.md similarity index 73% rename from docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md index f92c6e0604a..4ac3d56a9da 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md @@ -1,18 +1,31 @@ -# Proposal Meta Template +# Proposal Comment Presentation Template ## Description -## Proposal Meta Template Document +## Proposal Comment Presentation Template Document -A Proposal Meta Template is used to enforce functional requirements -are met in any Proposal Template. +A Proposal Comment Presentation Template defines how the data +captured by the Proposal Comment Form Template is to be displayed. -The payload of a proposal template is controlled by its meta template. +Multiple Proposal Comment Presentation Templates can exist for the +same Proposal Comment Form Template. +Each can be used to display the form data under different +circumstances. + +Proposal Comment Presentation Templates can reference any data contained +in the Proposal Comment Document, as well as any documents linked by: + +* [`ref`](../metadata.md#ref) +* [`reply`](../metadata.md#reply) +* [`parameters`](../metadata.md#parameters) + +The presentation of the payload of a Proposal Comment is controlled by +its Proposal Comment Presentation Template/s. -```graphviz dot proposal_meta_template.dot.svg -{{ include_file('./../diagrams/proposal_meta_template.dot', indent=4) }} +```graphviz dot proposal_comment_presentation_template.dot.svg +{{ include_file('./../diagrams/proposal_comment_presentation_template.dot', indent=4) }} ``` @@ -54,7 +67,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`7808d2ba-d511-40af-84e8-c0d1625fdfdc` | +| Type | `cb99b9bd-681a-49d8-9836-89107c02e8ef`,
`b679ded3-0e7c-41ba-89f8-da62a17898ea`,
`7808d2ba-d511-40af-84e8-c0d1625fdfdc` | The document TYPE. @@ -118,20 +131,19 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Payload -[JSON Schema][JSON Schema-2020-12] document which ensures the minimum required functional requirements -of the Proposal Template are met. +TBD. +But roughly, will be: -This ensures that payloads can be reliably interpreted by business logic processes, -while allowing for flexibility to capture extended information. - -Must be a valid according to . +1. A way to identify where the presentation template is intended to be used. +2. Optional [CSS] to control the presentation. +3. A [Handlebars] templated [HTML][HTML5] or [Markdown][CommonMark] file data which defines the presentation. ## Signers The following Admin roles may sign documents of this type: -* Root Admin * Brand Admin +* Campaign Admin New versions of this document may be published by: @@ -149,15 +161,14 @@ New versions of this document may be published by: ### Changelog -#### 0.01 (2025-04-04) - -* First Published Version - -#### 0.03 (2025-05-05) +#### 0.04 (2025-05-05) -* Use generalized parameters. +* First Version. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 +[Handlebars]: https://handlebarsjs.com/ [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[CommonMark]: https://spec.commonmark.org/0.31.2/ [RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 +[HTML5]: https://html.spec.whatwg.org/multipage/syntax.html#syntax +[CSS]: https://www.w3.org/Style/CSS/ diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md similarity index 80% rename from docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md index 219061849a5..a48c2517294 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md @@ -1,21 +1,34 @@ -# Proposal Template +# Proposal Form Template ## Description -## Proposal Template Document +## Proposal Form Template Document -A Proposal Template defines the allowed payload contents of a -linked proposal. +A Proposal Form Template defines both: -Proposals themselves are intentionally general, however they may be -linked to a brand/campaign or category via the template used by the proposal. +* The data that is entered in the Form. +* Formatting hints for the collection of the data in a form. -The payload of a proposal is controlled by its template. +A Proposal Form Template is a [JSON Schema][JSON Schema-2020-12] Document. + +Proposal entry *SHOULD* use the hints when collecting +data defined by the Proposal Form Template to provide a +consistent user interface. +It *CAN* also use those hints when re-displaying the full forms data. + +Alternatively a Proposal Presentation Template can be used to +format the Proposal data for presentation. + +The Proposal Document is intentionally general, +however it may be linked to a brand/campaign or category +via the template used by the Proposal. + +The payload of a Proposal is controlled by its template. -```graphviz dot proposal_template.dot.svg -{{ include_file('./../diagrams/proposal_template.dot', indent=4) }} +```graphviz dot proposal_form_template.dot.svg +{{ include_file('./../diagrams/proposal_form_template.dot', indent=4) }} ``` @@ -99,22 +112,6 @@ The first version of the document must set [`ver`](../metadata.md#ver) == [`id`] The document version must always be >= the document ID. -### [`template`](../metadata.md#template) - - -| Parameter | Value | -| --- | --- | -| Required | optional | -| Format | [Document Reference](../metadata.md#document-reference) | -| Valid References | [Proposal Meta Template](proposal_meta_template.md) | - -Reference to the template used to create and/or validate this document. - -#### [`template`](../metadata.md#template) Validation - -In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields, -The document payload is not valid if it does not validate completely against the referenced template. - ### [`parameters`](../metadata.md#parameters) @@ -141,7 +138,9 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Payload -[JSON Schema][JSON Schema-2020-12] document which defines the valid contents of a proposal document. +[JSON Schema][JSON Schema-2020-12] document which defines the valid contents and +formatting hints for the collection of data for a +Proposal Document. ## Signers @@ -174,6 +173,10 @@ New versions of this document may be published by: * Use generalized parameters. +#### 0.04 (2025-05-05) + +* Generalize the Form Template definitions. + [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode 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_presentation_template.md similarity index 74% rename from docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_meta_template.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md index 74b199e00b0..98e2b7122cb 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_presentation_template.md @@ -1,18 +1,31 @@ -# Proposal Comment Meta Template +# Proposal Presentation Template ## Description -## Proposal Comment Meta Template Document +## Proposal Presentation Template Document -A Proposal Comment Meta Template is used to enforce functional requirements -are met in any Proposal Comment Template. +A Proposal Presentation Template defines how the data +captured by the Proposal Form Template is to be displayed. -The payload of a proposal comment template is controlled by its meta template. +Multiple Proposal Presentation Templates can exist for the +same Proposal Form Template. +Each can be used to display the form data under different +circumstances. + +Proposal Presentation Templates can reference any data contained +in the Proposal Document, as well as any documents linked by: + +* [`ref`](../metadata.md#ref) +* [`reply`](../metadata.md#reply) +* [`parameters`](../metadata.md#parameters) + +The presentation of the payload of a Proposal is controlled by +its Proposal Presentation Template/s. -```graphviz dot proposal_comment_meta_template.dot.svg -{{ include_file('./../diagrams/proposal_comment_meta_template.dot', indent=4) }} +```graphviz dot proposal_presentation_template.dot.svg +{{ include_file('./../diagrams/proposal_presentation_template.dot', indent=4) }} ``` @@ -54,7 +67,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`b679ded3-0e7c-41ba-89f8-da62a17898ea`,
`7808d2ba-d511-40af-84e8-c0d1625fdfdc` | +| Type | `cb99b9bd-681a-49d8-9836-89107c02e8ef`,
`7808d2ba-d511-40af-84e8-c0d1625fdfdc` | The document TYPE. @@ -118,20 +131,19 @@ In addition to the validation performed for [Document Reference](../metadata.md# ## Payload -[JSON Schema][JSON Schema-2020-12] document which ensures the minimum required functional requirements -of the Proposal Comment Template are met. +TBD. +But roughly, will be: -This ensures that payloads can be reliably interpreted by business logic processes, -while allowing for flexibility to capture extended information. - -Must be a valid according to . +1. A way to identify where the presentation template is intended to be used. +2. Optional [CSS] to control the presentation. +3. A [Handlebars] templated [HTML][HTML5] or [Markdown][CommonMark] file data which defines the presentation. ## Signers The following Admin roles may sign documents of this type: -* Root Admin * Brand Admin +* Campaign Admin New versions of this document may be published by: @@ -149,15 +161,14 @@ New versions of this document may be published by: ### Changelog -#### 0.01 (2025-04-04) - -* First Published Version - -#### 0.03 (2025-05-05) +#### 0.04 (2025-05-05) -* Use generalized parameters. +* First Version. [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 +[Handlebars]: https://handlebarsjs.com/ [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[CommonMark]: https://spec.commonmark.org/0.31.2/ [RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 +[HTML5]: https://html.spec.whatwg.org/multipage/syntax.html#syntax +[CSS]: https://www.w3.org/Style/CSS/ diff --git a/docs/src/architecture/08_concepts/signed_doc/metadata.md b/docs/src/architecture/08_concepts/signed_doc/metadata.md index a7516e0749d..13d21cb9477 100644 --- a/docs/src/architecture/08_concepts/signed_doc/metadata.md +++ b/docs/src/architecture/08_concepts/signed_doc/metadata.md @@ -221,11 +221,11 @@ The document version must always be >= the document ID. | --- | --- | | Required | optional | | Format | [Document Reference](metadata.md#document-reference) | -| Valid References | [Proposal Meta Template](./docs/proposal_meta_template.md) | -| | [Proposal Template](./docs/proposal_template.md) | +| Valid References | [Proposal Form Template](./docs/proposal_form_template.md) | +| | [Proposal Presentation Template](./docs/proposal_presentation_template.md) | | | [Proposal](./docs/proposal.md) | -| | [Proposal Comment Meta Template](./docs/proposal_comment_meta_template.md) | -| | [Proposal Comment Template](./docs/proposal_comment_template.md) | +| | [Proposal Comment Form Template](./docs/proposal_comment_form_template.md) | +| | [Proposal Comment Presentation Template](./docs/proposal_comment_presentation_template.md) | | | [Proposal Comment](./docs/proposal_comment.md) | | | [Proposal Submission Action](./docs/proposal_submission_action.md) | | | [Proposal Moderation Action](./docs/proposal_moderation_action.md) | @@ -244,7 +244,7 @@ Some documents allow multiple references, and they are documented as required. The document reference serves two purposes: 1. It ensures that the document referenced by an ID/Version is not substituted. - In other words, that the document intended to be referenced, is actually referenced. + In other words, that the document intended to be referenced, is actually referenced. 2. It Allows the document to be unambiguously located in decentralized storage systems. There can be any number of Document Locations in any reference. @@ -274,10 +274,8 @@ The following must be true for a valid reference: | --- | --- | | Required | optional | | Format | [Document Reference](metadata.md#document-reference) | -| Valid References | [Proposal Meta Template](./docs/proposal_meta_template.md) | -| | [Proposal Template](./docs/proposal_template.md) | -| | [Proposal Comment Meta Template](./docs/proposal_comment_meta_template.md) | -| | [Proposal Comment Template](./docs/proposal_comment_template.md) | +| Valid References | [Proposal Form Template](./docs/proposal_form_template.md) | +| | [Proposal Comment Form Template](./docs/proposal_comment_form_template.md) | Reference to the template used to create and/or validate this document. diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index 35c823f1a52..b7a432dba49 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -12,10 +12,11 @@ All Document Types are defined by composing these base document types: | Category | `818938c3-3139-4daa-afe6-974c78488e95` | `37(h'818938c331394daaafe6974c78488e95')` | | Comment | `b679ded3-0e7c-41ba-89f8-da62a17898ea` | `37(h'b679ded30e7c41ba89f8da62a17898ea')` | | Decision | `788ff4c6-d65a-451f-bb33-575fe056b411` | `37(h'788ff4c6d65a451fbb33575fe056b411')` | +| FormTemplate | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | `37(h'0ce8ab3892584fbca62e7faa6e58318f')` | | ModerationAction | `a5d232b8-5e03-4117-9afd-be32b878fcdd` | `37(h'a5d232b85e0341179afdbe32b878fcdd')` | +| PresentationTemplate | `cb99b9bd-681a-49d8-9836-89107c02e8ef` | `37(h'cb99b9bd681a49d8983689107c02e8ef')` | | Proposal | `7808d2ba-d511-40af-84e8-c0d1625fdfdc` | `37(h'7808d2bad51140af84e8c0d1625fdfdc')` | | SubmissionAction | `78927329-cfd9-4ea1-9c71-0e019b126a65` | `37(h'78927329cfd94ea19c710e019b126a65')` | -| Template | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | `37(h'0ce8ab3892584fbca62e7faa6e58318f')` | ## Document Types @@ -31,12 +32,12 @@ All Defined Document Types | [Decision Parameters](./docs/decision_parameters.md) | Decision | [37(h'788ff4c6d65a451fbb33575fe056b411')] | | [Proposal](./docs/proposal.md) | Proposal | [37(h'7808d2bad51140af84e8c0d1625fdfdc')] | | [Proposal Comment](./docs/proposal_comment.md) | Comment/Proposal | [37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | -| [Proposal Comment Meta Template](./docs/proposal_comment_meta_template.md) | Template/Template/Comment/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | -| [Proposal Comment Template](./docs/proposal_comment_template.md) | Template/Comment/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | -| [Proposal Meta Template](./docs/proposal_meta_template.md) | Template/Template/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | +| [Proposal Comment Form Template](./docs/proposal_comment_form_template.md) | FormTemplate/Comment/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | +| [Proposal Comment Presentation Template](./docs/proposal_comment_presentation_template.md) | PresentationTemplate/Comment/Proposal | [37(h'cb99b9bd681a49d8983689107c02e8ef'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | +| [Proposal Form Template](./docs/proposal_form_template.md) | FormTemplate/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | | [Proposal Moderation Action](./docs/proposal_moderation_action.md) | Action/Proposal/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | +| [Proposal Presentation Template](./docs/proposal_presentation_template.md) | PresentationTemplate/Proposal | [37(h'cb99b9bd681a49d8983689107c02e8ef'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | | [Proposal Submission Action](./docs/proposal_submission_action.md) | Action/Proposal/SubmissionAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'78927329cfd94ea19c710e019b126a65')] | -| [Proposal Template](./docs/proposal_template.md) | Template/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | ## Document Relationship Hierarchy diff --git a/specs/Earthfile b/specs/Earthfile index 0621e885816..ddcad7701db 100644 --- a/specs/Earthfile +++ b/specs/Earthfile @@ -31,7 +31,7 @@ src: check: FROM +src RUN cue fmt --check -s --files ./definitions - RUN cd definitions; cue vet ./signed_docs/docs:signed_docs ../signed_doc.json + RUN cd definitions; CUE_EXPERIMENT=evalv3=0 cue vet ./signed_docs/docs:signed_docs ../signed_doc.json # Check the the generated signed docs documentation matches the generated signed docs data check-docs-generation: diff --git a/specs/Justfile b/specs/Justfile index d524c2c20cd..f759d2f3131 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -35,7 +35,8 @@ regenerate: check regenerate-signed-doc-json validate && validate-docs # Validate the generated signed_docs.json is correct against the cue schema. validate: # Generate the intermediate compiled schema data. - cd definitions; cue vet ./signed_docs/docs:signed_docs ../signed_doc.json + cd definitions; CUE_EXPERIMENT=evalv3=0 cue vet ./signed_docs/docs:signed_docs ../signed_doc.json + # cd definitions; cue vet ./signed_docs/docs:signed_docs ../signed_doc.json # Check the Model is valid. cd generators; uv run validator ../signed_doc.json diff --git a/specs/definitions/signed_docs/docs/all.cue b/specs/definitions/signed_docs/docs/all.cue index c5ffb2294d3..7c03a764cc8 100644 --- a/specs/definitions/signed_docs/docs/all.cue +++ b/specs/definitions/signed_docs/docs/all.cue @@ -7,43 +7,42 @@ import ( // Named Type UUIDs for easier definitions/references _allDocTypes: { - Template: "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" - Proposal: "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - Comment: "b679ded3-0e7c-41ba-89f8-da62a17898ea" - Action: "5e60e623-ad02-4a1b-a1ac-406db978ee48" - SubmissionAction: "78927329-cfd9-4ea1-9c71-0e019b126a65" - ModerationAction: "a5d232b8-5e03-4117-9afd-be32b878fcdd" - Brand: "ebcabeeb-5bc5-4f95-91e8-cab8ca724172" - Campaign: "5ef32d5d-f240-462c-a7a4-ba4af221fa23" - Category: "818938c3-3139-4daa-afe6-974c78488e95" - Decision: "788ff4c6-d65a-451f-bb33-575fe056b411" + FormTemplate: "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + PresentationTemplate: "cb99b9bd-681a-49d8-9836-89107c02e8ef" + Proposal: "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + Comment: "b679ded3-0e7c-41ba-89f8-da62a17898ea" + Action: "5e60e623-ad02-4a1b-a1ac-406db978ee48" + SubmissionAction: "78927329-cfd9-4ea1-9c71-0e019b126a65" + ModerationAction: "a5d232b8-5e03-4117-9afd-be32b878fcdd" + Brand: "ebcabeeb-5bc5-4f95-91e8-cab8ca724172" + Campaign: "5ef32d5d-f240-462c-a7a4-ba4af221fa23" + Category: "818938c3-3139-4daa-afe6-974c78488e95" + Decision: "788ff4c6-d65a-451f-bb33-575fe056b411" } // Source of truth for ALL Document Types and their matching UUID's. // Format is : : _allDocs: { - "Proposal Meta Template": [ - _allDocTypes["Template"], // Template - _allDocTypes["Template"], // For Templates - _allDocTypes["Proposal"], // On Proposals + "Proposal Form Template": [ + _allDocTypes["FormTemplate"], // Form Template + _allDocTypes["Proposal"], // For Proposals ] - "Proposal Template": [ - _allDocTypes["Template"], // Template - _allDocTypes["Proposal"], // For Proposals + "Proposal Presentation Template": [ + _allDocTypes["PresentationTemplate"], // Presentation Template + _allDocTypes["Proposal"], // For Proposals ] Proposal: [ _allDocTypes["Proposal"], ] - "Proposal Comment Meta Template": [ - _allDocTypes["Template"], // Template - _allDocTypes["Template"], // For Templates - _allDocTypes["Comment"], // On Comment - _allDocTypes["Proposal"], // On Proposals + "Proposal Comment Form Template": [ + _allDocTypes["FormTemplate"], // Form Template + _allDocTypes["Comment"], // For Comments + _allDocTypes["Proposal"], // On Proposals ] - "Proposal Comment Template": [ - _allDocTypes["Template"], // Template - _allDocTypes["Comment"], // For Comments - _allDocTypes["Proposal"], // On Proposals + "Proposal Comment Presentation Template": [ + _allDocTypes["PresentationTemplate"], // PresentationTemplate + _allDocTypes["Comment"], // For Comments + _allDocTypes["Proposal"], // On Proposals ] "Proposal Comment": [ _allDocTypes["Comment"], // Comment diff --git a/specs/definitions/signed_docs/docs/generic_form_template.cue b/specs/definitions/signed_docs/docs/generic_form_template.cue new file mode 100644 index 00000000000..f357918bc2b --- /dev/null +++ b/specs/definitions/signed_docs/docs/generic_form_template.cue @@ -0,0 +1,90 @@ +package signed_docs + +// Template Standardized Descriptions + +_form_template_description: """ + ## {{ .doc }} Form Template Document + + A {{ .doc }} Form Template defines both: + + * The data that is entered in the Form. + * Formatting hints for the collection of the data in a form. + + A {{ .doc }} Form Template is a JSON Schema Document. + + {{ .doc }} entry *SHOULD* use the hints when collecting + data defined by the {{ .doc }} Form Template to provide a + consistent user interface. + It *CAN* also use those hints when re-displaying the full forms data. + + Alternatively a {{ .doc }} Presentation Template can be used to + format the {{ .doc }} data for presentation. + + The {{ .doc }} Document is intentionally general, + however it may be linked to a brand/campaign or category + via the template used by the {{ .doc }}. + + The payload of a {{ .doc }} is controlled by its template. + """ + +_form_template_payload_description: """ + JSON Schema document which defines the valid contents and + formatting hints for the collection of data for a + {{ .doc }} Document. + """ + +#generic_form_template: #signedDocument & { + description: _ + + headers: "content type": value: "application/schema+json" + + metadata: { + template: required: "excluded" + + parameters: { + required: "yes" + type: doc_clusters."System Parameters".docs + linked_refs: [ + "template", + ] + } + } + + payload: description: _ + + signers: roles: { + // No User Role may publish this document. + user: [] + + // Brand Admin and Lower may publish this document. + admin: [ + "Brand Admin", + "Campaign Admin", + ] + } + +} + +_generic_form_template_versions: [#changelogEntry, ...#changelogEntry] & [ + { + version: "0.01" + modified: "2025-04-04" + changes: """ + * First Published Version + """ + }, + { + version: "0.03" + modified: "2025-05-05" + changes: """ + * Use generalized parameters. + """ + }, + { + version: "0.04" + modified: "2025-05-05" + changes: """ + * Generalize the Form Template definitions. + """ + }, +] diff --git a/specs/definitions/signed_docs/docs/generic_presentation_template.cue b/specs/definitions/signed_docs/docs/generic_presentation_template.cue new file mode 100644 index 00000000000..3556eb900b5 --- /dev/null +++ b/specs/definitions/signed_docs/docs/generic_presentation_template.cue @@ -0,0 +1,68 @@ +package signed_docs + +// Template Standardized Descriptions + +_presentation_template_description: """ + ## {{ .doc }} Presentation Template Document + + A {{ .doc }} Presentation Template defines how the data + captured by the {{ .doc }} Form Template is to be displayed. + + Multiple {{ .doc }} Presentation Templates can exist for the + same {{.doc }} Form Template. + Each can be used to display the form data under different + circumstances. + + {{ .doc }} Presentation Templates can reference any data contained + in the {{ .doc }} Document, as well as any documents linked by: + + * `ref` + * `reply` + * `parameters` + + The presentation of the payload of a {{ .doc }} is controlled by + its {{ .doc }} Presentation Template/s. + """ + +_presentation_template_payload_description: """ + TBD. + But roughly, will be: + + 1. A way to identify where the presentation template is intended to be used. + 2. Optional CSS to control the presentation. + 3. A Handlebars templated HTML or Markdown file data which defines the presentation. + """ + +_generic_presentation_template: #signedDocument & { + description: _ + + headers: "content type": value: "application/schema+json" + + metadata: parameters: { + required: "yes" + type: doc_clusters."System Parameters".docs + } + + payload: description: _ + + signers: roles: { + // No User Role may publish this document. + user: [] + + // Brand Admin and Lower may publish this document. + admin: [ + "Brand Admin", + "Campaign Admin", + ] + } +} + +_generic_presentation_template_versions: [#changelogEntry, ...#changelogEntry] & [ + { + version: "0.04" + modified: "2025-05-05" + changes: """ + * First Version. + """ + }, +] diff --git a/specs/definitions/signed_docs/docs/proposal.cue b/specs/definitions/signed_docs/docs/proposal.cue index f78d3093999..bd7651cb273 100644 --- a/specs/definitions/signed_docs/docs/proposal.cue +++ b/specs/definitions/signed_docs/docs/proposal.cue @@ -59,7 +59,7 @@ docs: #DocumentDefinitions & { metadata: { template: { required: "yes" - type: "Proposal Template" + type: "Proposal Form Template" } collaborators: required: "optional" diff --git a/specs/definitions/signed_docs/docs/proposal_comment.cue b/specs/definitions/signed_docs/docs/proposal_comment.cue index b0fe9cb1e6c..3df7f069b2e 100644 --- a/specs/definitions/signed_docs/docs/proposal_comment.cue +++ b/specs/definitions/signed_docs/docs/proposal_comment.cue @@ -56,7 +56,7 @@ docs: #DocumentDefinitions & { template: { required: "yes" - type: "Proposal Comment Template" + type: "Proposal Comment Form Template" } revocations: required: "optional" diff --git a/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue b/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue new file mode 100644 index 00000000000..2898956cbc9 --- /dev/null +++ b/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue @@ -0,0 +1,14 @@ +// Proposal Comment Form Template Document Definition +package signed_docs + +import "text/template" + +_proposal_comment_form_data: doc: "Proposal Comment" + +docs: #DocumentDefinitions & { + "Proposal Comment Form Template": #generic_form_template & { + description: template.Execute(_form_template_description, _proposal_comment_form_data) + payload: description: template.Execute(_form_template_payload_description, _proposal_comment_form_data) + versions: _generic_form_template_versions + } +} diff --git a/specs/definitions/signed_docs/docs/proposal_comment_meta_template.cue b/specs/definitions/signed_docs/docs/proposal_comment_meta_template.cue deleted file mode 100644 index 05947a4c9fa..00000000000 --- a/specs/definitions/signed_docs/docs/proposal_comment_meta_template.cue +++ /dev/null @@ -1,61 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Proposal Comment Meta Template": { - description: """ - ## Proposal Comment Meta Template Document - - A Proposal Comment Meta Template is used to enforce functional requirements - are met in any Proposal Comment Template. - - The payload of a proposal comment template is controlled by its meta template. - """ - - headers: "content type": value: "application/schema+json" - - metadata: parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - } - - payload: { - description: """ - JSON Schema document which ensures the minimum required functional requirements - of the Proposal Comment Template are met. - - This ensures that payloads can be reliably interpreted by business logic processes, - while allowing for flexibility to capture extended information. - """ - - schema: "https://json-schema.org/draft-07/schema" - } - signers: roles: { - // No User Role may publish this document. - user: [] - - // Root Admin and brand Admin may publish this document. - admin: [ - "Root Admin", - "Brand Admin", - ] - } - - versions: [ - { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - { - version: "0.03" - modified: "2025-05-05" - changes: """ - * Use generalized parameters. - """ - }, - ]} -} diff --git a/specs/definitions/signed_docs/docs/proposal_comment_presentation_template.cue b/specs/definitions/signed_docs/docs/proposal_comment_presentation_template.cue new file mode 100644 index 00000000000..8103ada69f7 --- /dev/null +++ b/specs/definitions/signed_docs/docs/proposal_comment_presentation_template.cue @@ -0,0 +1,13 @@ +// Proposal Form Template Document Definition +package signed_docs + +import "text/template" + +_proposal_comment_presentation_data: doc: "Proposal Comment" + +docs: #DocumentDefinitions & { + "Proposal Comment Presentation Template": _generic_presentation_template + "Proposal Comment Presentation Template": description: template.Execute(_presentation_template_description, _proposal_comment_presentation_data) + "Proposal Comment Presentation Template": payload: description: template.Execute(_presentation_template_payload_description, _proposal_comment_presentation_data) + "Proposal Comment Presentation Template": versions: _generic_presentation_template_versions +} diff --git a/specs/definitions/signed_docs/docs/proposal_comment_template.cue b/specs/definitions/signed_docs/docs/proposal_comment_template.cue deleted file mode 100644 index ba12fab5ad9..00000000000 --- a/specs/definitions/signed_docs/docs/proposal_comment_template.cue +++ /dev/null @@ -1,64 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Proposal Comment Template": { - description: """ - ## Proposal Comment Template Document - - A Proposal Comment Template defines the allowed payload contents of a - linked proposal comment. - - Proposal comments themselves are intentionally general, however they may be - linked to a brand/campaign or category via the template used by the proposal. - - The payload of a proposal comment is controlled by its template. - """ - - headers: "content type": value: "application/schema+json" - - metadata: { - template: { - required: "optional" - type: "Proposal Comment Meta Template" - } - - parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - } - } - - payload: description: """ - JSON Schema document which defines the content of the Proposal Comments. - """ - - signers: roles: { - // No User Role may publish this document. - user: [] - - // Brand Admin and Lower may publish this document. - admin: [ - "Brand Admin", - "Campaign Admin", - ] - } - - versions: [ - { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - { - version: "0.03" - modified: "2025-05-05" - changes: """ - * Use generalized parameters. - """ - }, - ]} -} diff --git a/specs/definitions/signed_docs/docs/proposal_form_template.cue b/specs/definitions/signed_docs/docs/proposal_form_template.cue new file mode 100644 index 00000000000..2786514c821 --- /dev/null +++ b/specs/definitions/signed_docs/docs/proposal_form_template.cue @@ -0,0 +1,15 @@ +// Proposal Form Template Document Definition +package signed_docs + +import "text/template" + +_proposal_form_data: doc: "Proposal" + +docs: #DocumentDefinitions & { + "Proposal Form Template": #generic_form_template & { + description: template.Execute(_form_template_description, _proposal_form_data) + payload: description: template.Execute(_form_template_payload_description, _proposal_form_data) + versions: _generic_form_template_versions + //metadata: template: type: "Proposal Presentation Template" + } +} diff --git a/specs/definitions/signed_docs/docs/proposal_meta_template.cue b/specs/definitions/signed_docs/docs/proposal_meta_template.cue deleted file mode 100644 index 6b0ea8a7e69..00000000000 --- a/specs/definitions/signed_docs/docs/proposal_meta_template.cue +++ /dev/null @@ -1,62 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Proposal Meta Template": { - description: """ - ## Proposal Meta Template Document - - A Proposal Meta Template is used to enforce functional requirements - are met in any Proposal Template. - - The payload of a proposal template is controlled by its meta template. - """ - - headers: "content type": value: "application/schema+json" - - metadata: parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - } - - payload: { - description: """ - JSON Schema document which ensures the minimum required functional requirements - of the Proposal Template are met. - - This ensures that payloads can be reliably interpreted by business logic processes, - while allowing for flexibility to capture extended information. - """ - - schema: "https://json-schema.org/draft-07/schema" - } - signers: roles: { - // No User Role may publish this document. - user: [] - - // Root Admin and brand Admin may publish this document. - admin: [ - "Root Admin", - "Brand Admin", - ] - } - - versions: [ - { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - { - version: "0.03" - modified: "2025-05-05" - changes: """ - * Use generalized parameters. - """ - }, - ] - } -} diff --git a/specs/definitions/signed_docs/docs/proposal_presentation_template.cue b/specs/definitions/signed_docs/docs/proposal_presentation_template.cue new file mode 100644 index 00000000000..2cbd5610acc --- /dev/null +++ b/specs/definitions/signed_docs/docs/proposal_presentation_template.cue @@ -0,0 +1,13 @@ +// Proposal Form Template Document Definition +package signed_docs + +import "text/template" + +_proposal_presentation_data: doc: "Proposal" + +docs: #DocumentDefinitions & { + "Proposal Presentation Template": _generic_presentation_template + "Proposal Presentation Template": description: template.Execute(_presentation_template_description, _proposal_form_data) + "Proposal Presentation Template": payload: description: template.Execute(_presentation_template_payload_description, _proposal_form_data) + "Proposal Presentation Template": versions: _generic_presentation_template_versions +} diff --git a/specs/definitions/signed_docs/docs/proposal_template.cue b/specs/definitions/signed_docs/docs/proposal_template.cue deleted file mode 100644 index af711f15bbf..00000000000 --- a/specs/definitions/signed_docs/docs/proposal_template.cue +++ /dev/null @@ -1,68 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Proposal Template": { - description: """ - ## Proposal Template Document - - A Proposal Template defines the allowed payload contents of a - linked proposal. - - Proposals themselves are intentionally general, however they may be - linked to a brand/campaign or category via the template used by the proposal. - - The payload of a proposal is controlled by its template. - """ - - headers: "content type": value: "application/schema+json" - - metadata: { - template: { - required: "optional" - type: "Proposal Meta Template" - } - - parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - linked_refs: [ - "template", - ] - } - } - - payload: description: """ - JSON Schema document which defines the valid contents of a proposal document. - """ - - signers: roles: { - // No User Role may publish this document. - user: [] - - // Brand Admin and Lower may publish this document. - admin: [ - "Brand Admin", - "Campaign Admin", - ] - } - - versions: [ - { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - { - version: "0.03" - modified: "2025-05-05" - changes: """ - * Use generalized parameters. - """ - }, - ] - } -} diff --git a/specs/definitions/signed_docs/metadata.cue b/specs/definitions/signed_docs/metadata.cue index ffd870ff1e0..cd631647e59 100644 --- a/specs/definitions/signed_docs/metadata.cue +++ b/specs/definitions/signed_docs/metadata.cue @@ -9,9 +9,6 @@ import ( "github.com/input-output-hk/catalyst-libs/specs/generic:optional" ) -_chainValidMermaid: _ @embed(file=includes/valid_chain.mermaid,type=text) -_chainInvalidMermaid: _ @embed(file=includes/invalid_chain.mermaid,type=text) -_chainFraudulentMermaid: _ @embed(file=includes/fraudulent_chain.mermaid,type=text) // Metadata Formats. // format_name : cddl definition #metadataFormats: { @@ -21,7 +18,8 @@ _chainFraudulentMermaid: _ @embed(file=includes/fraudulent_chain.mermaid,type=te } } -metadata: formats: #metadataFormats & { +metadata: formats: #metadataFormats +metadata: formats: { "Document Reference": { description: "A document reference identifier" cddl: "document_refs" @@ -46,6 +44,7 @@ metadata: formats: #metadataFormats & { description: "A unique chronological document version" cddl: "document_ver" } + "Section Reference": { description: "A document section reference identifier" cddl: "section_ref" @@ -73,6 +72,7 @@ metadata: formats: #metadataFormats & { #metadataTypesConstraint: or(#metadataTypes) // Canonical List of all valid metadata names +// Must be listed in preferred order _metadataNames: list.UniqueItems _metadataNames: [ "type", @@ -111,101 +111,13 @@ _allMetadataNames: or([ validation: string } -_ver_description_common: """ - The unique version of the document. - The first version of the document must set `ver` == `id` - """ - -_ver_description_complete: """ - \(_ver_description_common) - - `ver` represents either: - - * when a document changes over time, such as - with a new version of a particular document that supersedes an - earlier one. - * when a new document in a sequence of documents is produced. - - Because the most common use `ver` is a new version of the same document - this is to be assumed unless the document specifies its representing - a sequence of documents. - """ - -_ver_description_versioned: """ - \(_ver_description_common) - - `ver` represents new versions of the same document as it changes over time. - """ - -_ver_description_sequenced: """ - \(_ver_description_common) - - `ver` represents new documents in a sequence of documents. - """ - -_chain_validation_common: """ - Chained Documents do not support collaborators. - Any document which is attempted to be published in the sequence - which is *NOT* published by the author of the first document in the - sequence is fraudulent, and to be discarded. - - In addition, the chained document *MUST*: - - * Not have `collaborators`; - * Have the same `id` as the document being chained to; - * Have a `ver` that is greater than the `ver` being chained to; - * Have the same `type` as the chained document; - * Have `parameters` match; - * Have not be chaining to a document already chained to by another document; - * Have its absolute `height` exactly one more than the `height` of the document being chained to. - - IF any of these validations fail, then the entire sequence of documents is INVALID. - Not just the current document. - """ - -_chain_validation_examples: """ - ##### Example of a Valid Chain - - - ``` mermaid - \(_chainValidMermaid) - ``` - - - ##### Example of an Invalid Chain - - Either of the two documents being present invalidates the data - in the entire chain, - as they are signed by the author of the chain. - - - ``` mermaid - \(_chainInvalidMermaid) - ``` - - - ##### Example of a Fraudulent Chain Document - - The invalid document does not invalidate the chain, - as its not signed by the author of the chained documents. - - - ``` mermaid - \(_chainFraudulentMermaid) - ``` - - """ - -_chain_validation_complete: """ - \(_chain_validation_common) - - \(_chain_validation_examples) - """ // Metadata fields that are optional #metadataStruct: { [_allMetadataNames]: #metadataField } -_metadata: #metadataStruct & { + +#metadata: #metadataStruct +#metadata: { // Document Type type: { required: "yes" @@ -229,15 +141,6 @@ _metadata: #metadataStruct & { `id` and `ver` being equal *MUST* exist. """ } - // Document Version - ver: { - required: "yes" - format: "Document Ver" - description: string | *_ver_description_versioned - validation: """ - The document version must always be >= the document ID. - """ - } ref: { description: """ @@ -356,27 +259,11 @@ _metadata: #metadataStruct & { """ } - chain: { - format: "Chain Link" - description: """ - An immutable link to the previous document in a chained sequence of documents. - Because ID/Ver only defines values for the current document, and is not intended - by itself to prevent insertion of documents in a sequence, the `chain` - metadata allows for the latest document to directly point to its previous iteration. - - It also aids in discoverability, where the latest document may be pinned but prior - documents can be discovered automatically by following the chain. - """ - validation: string | *""" - \(_chain_validation_common) - """ - } } // Note: we make all normally excluded fields optional at the global level, because they are globally optional -metadata: headers: _metadata +metadata: headers: #metadata metadata: headers: { - ver: description: _ver_description_complete ref: required: "optional" ref: type: _allDocNamesList template: required: "optional" @@ -387,22 +274,9 @@ metadata: headers: { collaborators: required: "optional" parameters: required: "optional" parameters: type: #parameterDocNamesList - chain: required: "optional" - chain: validation: _chain_validation_complete } // Preferred display order // If metadata field not listed, then list them after the explicit ones, in alphabetical order. metadata: order: list.UniqueItems -metadata: order: [..._allMetadataNames] & [ - "type", - "id", - "ver", - "ref", - "template", - "reply", - "section", - "collaborators", - "revocations", - "parameters", -] +metadata: order: [..._allMetadataNames] & _metadataNames diff --git a/specs/definitions/signed_docs/metadata_chain.cue b/specs/definitions/signed_docs/metadata_chain.cue new file mode 100644 index 00000000000..4c2000e9002 --- /dev/null +++ b/specs/definitions/signed_docs/metadata_chain.cue @@ -0,0 +1,89 @@ +// Signed Document Definitions +// +// Metadata Types and Constraints +@extern(embed) +package signed_docs + +_chainValidMermaid: _ @embed(file=includes/valid_chain.mermaid,type=text) +_chainInvalidMermaid: _ @embed(file=includes/invalid_chain.mermaid,type=text) +_chainFraudulentMermaid: _ @embed(file=includes/fraudulent_chain.mermaid,type=text) + +_chain_validation_common: """ + Chained Documents do not support collaborators. + Any document which is attempted to be published in the sequence + which is *NOT* published by the author of the first document in the + sequence is fraudulent, and to be discarded. + + In addition, the chained document *MUST*: + + * Not have `collaborators`; + * Have the same `id` as the document being chained to; + * Have a `ver` that is greater than the `ver` being chained to; + * Have the same `type` as the chained document; + * Have `parameters` match; + * Have not be chaining to a document already chained to by another document; + * Have its absolute `height` exactly one more than the `height` of the document being chained to. + + IF any of these validations fail, then the entire sequence of documents is INVALID. + Not just the current document. + """ + +_chain_validation_examples: """ + ##### Example of a Valid Chain + + + ``` mermaid + \(_chainValidMermaid) + ``` + + + ##### Example of an Invalid Chain + + Either of the two documents being present invalidates the data + in the entire chain, + as they are signed by the author of the chain. + + + ``` mermaid + \(_chainInvalidMermaid) + ``` + + + ##### Example of a Fraudulent Chain Document + + The invalid document does not invalidate the chain, + as its not signed by the author of the chained documents. + + + ``` mermaid + \(_chainFraudulentMermaid) + ``` + + """ + +_chain_validation_complete: """ + \(_chain_validation_common) + + \(_chain_validation_examples) + """ + +#metadata: chain: { + format: "Chain Link" + description: """ + An immutable link to the previous document in a chained sequence of documents. + Because ID/Ver only defines values for the current document, and is not intended + by itself to prevent insertion of documents in a sequence, the `chain` + metadata allows for the latest document to directly point to its previous iteration. + + It also aids in discoverability, where the latest document may be pinned but prior + documents can be discovered automatically by following the chain. + """ + validation: string | *""" + \(_chain_validation_common) + """ +} + +metadata: headers: chain: { + required: "optional" + validation: _chain_validation_complete +} diff --git a/specs/definitions/signed_docs/metadata_template.cue b/specs/definitions/signed_docs/metadata_template.cue new file mode 100644 index 00000000000..3f77683cc3b --- /dev/null +++ b/specs/definitions/signed_docs/metadata_template.cue @@ -0,0 +1,35 @@ +// Signed Document Definitions +// +// Metadata Types and Constraints +package signed_docs + +import ( + "strings" +) + +// List of all Template Docs (not actions) +#templateDocNamesList: [...string] & [ + for k, _ in _allDocs + if strings.Contains(k, "Template") && + !strings.Contains(k, "Presentation") && + !strings.Contains(k, "Action") {k}, +] + +_template_description: """ + Reference to the template used to create and/or validate this document. + """ +_template_validation: """ + In addition to the validation performed for `Document Reference` type fields, + The document payload is not valid if it does not validate completely against the referenced template. + """ + +#metadata: template: { + description: _template_description + validation: _template_validation +} + +// Note: we make all normally excluded fields optional at the global level, because they are globally optional +metadata: headers: { + template: required: "optional" + template: type: #templateDocNamesList +} diff --git a/specs/definitions/signed_docs/metadata_ver.cue b/specs/definitions/signed_docs/metadata_ver.cue new file mode 100644 index 00000000000..ec6e1c89803 --- /dev/null +++ b/specs/definitions/signed_docs/metadata_ver.cue @@ -0,0 +1,53 @@ +// Signed Document Definitions +// +// Metadata Types and Constraints +// `ver` +@extern(embed) +package signed_docs + +_ver_description_common: """ + The unique version of the document. + The first version of the document must set `ver` == `id` + """ + +_ver_description_complete: """ + \(_ver_description_common) + + `ver` represents either: + + * when a document changes over time, such as + with a new version of a particular document that supersedes an + earlier one. + * when a new document in a sequence of documents is produced. + + Because the most common use `ver` is a new version of the same document + this is to be assumed unless the document specifies its representing + a sequence of documents. + """ + +_ver_description_versioned: """ + \(_ver_description_common) + + `ver` represents new versions of the same document as it changes over time. + """ + +_ver_description_sequenced: """ + \(_ver_description_common) + + `ver` represents new documents in a sequence of documents. + """ + +// Document Version +#metadata: { + ver: { + required: "yes" + format: "Document Ver" + description: string | *_ver_description_versioned + validation: """ + The document version must always be >= the document ID. + """ + } +} + +// Note: we make all normally excluded fields optional at the global level, because they are globally optional +metadata: headers: ver: description: _ver_description_complete diff --git a/specs/definitions/signed_docs/signed_doc.cue b/specs/definitions/signed_docs/signed_doc.cue index a6b12e3ae46..30e1a214428 100644 --- a/specs/definitions/signed_docs/signed_doc.cue +++ b/specs/definitions/signed_docs/signed_doc.cue @@ -39,7 +39,7 @@ import ( headers: _coseHeaders // The Metadata fields in this document (non cose standard) - metadata: _metadata + metadata: #metadata // Requirements for the document payload. payload?: _payload @@ -105,13 +105,6 @@ _allDocNamesList: [...string] & [ !strings.Contains(k, "Action") {k}, ] -// List of all Template Docs (not actions) -#templateDocNamesList: [...string] & [ - for k, _ in _allDocs - if strings.Contains(k, "Template") && - !strings.Contains(k, "Action") {k}, -] - // List of all the document names we have defined. _allDocNames: or(_allDocNamesList) diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 05fafccfd36..8816e1d9b85 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -10,10 +10,11 @@ "Category": "818938c3-3139-4daa-afe6-974c78488e95", "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea", "Decision": "788ff4c6-d65a-451f-bb33-575fe056b411", + "FormTemplate": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "ModerationAction": "a5d232b8-5e03-4117-9afd-be32b878fcdd", + "PresentationTemplate": "cb99b9bd-681a-49d8-9836-89107c02e8ef", "Proposal": "7808d2ba-d511-40af-84e8-c0d1625fdfdc", - "SubmissionAction": "78927329-cfd9-4ea1-9c71-0e019b126a65", - "Template": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + "SubmissionAction": "78927329-cfd9-4ea1-9c71-0e019b126a65" }, "cddlDefinitions": { "COSE_Document_Header_Map": { @@ -1057,7 +1058,7 @@ "linked_refs": null, "multiple": false, "required": "yes", - "type": "Proposal Template", + "type": "Proposal Form Template", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { @@ -1201,7 +1202,7 @@ "linked_refs": null, "multiple": false, "required": "yes", - "type": "Proposal Comment Template", + "type": "Proposal Comment Form Template", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { @@ -1249,9 +1250,9 @@ } ] }, - "Proposal Comment Meta Template": { + "Proposal Comment Form Template": { "authors": {}, - "description": "## Proposal Comment Meta Template Document\n\nA Proposal Comment Meta Template is used to enforce functional requirements\nare met in any Proposal Comment Template.\n\nThe payload of a proposal comment template is controlled by its meta template.", + "description": "## Proposal Comment Form Template Document\n\t\nA Proposal Comment Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Proposal Comment Form Template is a JSON Schema Document.\n\nProposal Comment entry *SHOULD* use the hints when collecting \ndata defined by the Proposal Comment Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Proposal Comment Presentation Template can be used to\nformat the Proposal Comment data for presentation.\n\nThe Proposal Comment Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Proposal Comment.\n\nThe payload of a Proposal Comment is controlled by its template.", "headers": { "content type": { "coseLabel": 3, @@ -1292,7 +1293,9 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": null, + "linked_refs": [ + "template" + ], "multiple": false, "required": "yes", "type": [ @@ -1347,14 +1350,13 @@ }, "notes": [], "payload": { - "description": "JSON Schema document which ensures the minimum required functional requirements\nof the Proposal Comment Template are met.\n\nThis ensures that payloads can be reliably interpreted by business logic processes, \nwhile allowing for flexibility to capture extended information.", - "schema": "https://json-schema.org/draft-07/schema" + "description": "JSON Schema document which defines the valid contents and \nformatting hints for the collection of data for a \nProposal Comment Document." }, "signers": { "roles": { "admin": [ - "Root Admin", - "Brand Admin" + "Brand Admin", + "Campaign Admin" ], "user": [] }, @@ -1363,7 +1365,6 @@ } }, "type": [ - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "b679ded3-0e7c-41ba-89f8-da62a17898ea", "7808d2ba-d511-40af-84e8-c0d1625fdfdc" @@ -1378,12 +1379,17 @@ "changes": "* Use generalized parameters.", "modified": "2025-05-05", "version": "0.03" + }, + { + "changes": "* Generalize the Form Template definitions.", + "modified": "2025-05-05", + "version": "0.04" } ] }, - "Proposal Comment Template": { + "Proposal Comment Presentation Template": { "authors": {}, - "description": "## Proposal Comment Template Document\n\nA Proposal Comment Template defines the allowed payload contents of a\nlinked proposal comment.\n\nProposal comments themselves are intentionally general, however they may be\nlinked to a brand/campaign or category via the template used by the proposal.\n\nThe payload of a proposal comment is controlled by its template.", + "description": "## Proposal Comment Presentation Template Document\n\t\nA Proposal Comment Presentation Template defines how the data\ncaptured by the Proposal Comment Form Template is to be displayed.\n\nMultiple Proposal Comment Presentation Templates can exist for the \nsame Proposal Comment Form Template.\nEach can be used to display the form data under different \ncircumstances.\n\nProposal Comment Presentation Templates can reference any data contained\nin the Proposal Comment Document, as well as any documents linked by:\n\n* `ref`\n* `reply`\n* `parameters`\n\nThe presentation of the payload of a Proposal Comment is controlled by \nits Proposal Comment Presentation Template/s.", "headers": { "content type": { "coseLabel": 3, @@ -1461,10 +1467,7 @@ "template": { "description": "Reference to the template used to create and/or validate this document.", "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": "Proposal Comment Meta Template", + "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { @@ -1482,7 +1485,7 @@ }, "notes": [], "payload": { - "description": "JSON Schema document which defines the content of the Proposal Comments." + "description": "TBD.\nBut roughly, will be:\n\n1. A way to identify where the presentation template is intended to be used.\n2. Optional CSS to control the presentation.\n3. A Handlebars templated HTML or Markdown file data which defines the presentation." }, "signers": { "roles": { @@ -1497,26 +1500,21 @@ } }, "type": [ - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "cb99b9bd-681a-49d8-9836-89107c02e8ef", "b679ded3-0e7c-41ba-89f8-da62a17898ea", "7808d2ba-d511-40af-84e8-c0d1625fdfdc" ], "versions": [ { - "changes": "* First Published Version", - "modified": "2025-04-04", - "version": "0.01" - }, - { - "changes": "* Use generalized parameters.", + "changes": "* First Version.", "modified": "2025-05-05", - "version": "0.03" + "version": "0.04" } ] }, - "Proposal Meta Template": { + "Proposal Form Template": { "authors": {}, - "description": "## Proposal Meta Template Document\n\nA Proposal Meta Template is used to enforce functional requirements\nare met in any Proposal Template.\n\nThe payload of a proposal template is controlled by its meta template.", + "description": "## Proposal Form Template Document\n\t\nA Proposal Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Proposal Form Template is a JSON Schema Document.\n\nProposal entry *SHOULD* use the hints when collecting \ndata defined by the Proposal Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Proposal Presentation Template can be used to\nformat the Proposal data for presentation.\n\nThe Proposal Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Proposal.\n\nThe payload of a Proposal is controlled by its template.", "headers": { "content type": { "coseLabel": 3, @@ -1557,7 +1555,9 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": null, + "linked_refs": [ + "template" + ], "multiple": false, "required": "yes", "type": [ @@ -1612,14 +1612,13 @@ }, "notes": [], "payload": { - "description": "JSON Schema document which ensures the minimum required functional requirements\nof the Proposal Template are met.\n\nThis ensures that payloads can be reliably interpreted by business logic processes, \nwhile allowing for flexibility to capture extended information.", - "schema": "https://json-schema.org/draft-07/schema" + "description": "JSON Schema document which defines the valid contents and \nformatting hints for the collection of data for a \nProposal Document." }, "signers": { "roles": { "admin": [ - "Root Admin", - "Brand Admin" + "Brand Admin", + "Campaign Admin" ], "user": [] }, @@ -1628,7 +1627,6 @@ } }, "type": [ - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "7808d2ba-d511-40af-84e8-c0d1625fdfdc" ], @@ -1642,6 +1640,11 @@ "changes": "* Use generalized parameters.", "modified": "2025-05-05", "version": "0.03" + }, + { + "changes": "* Generalize the Form Template definitions.", + "modified": "2025-05-05", + "version": "0.04" } ] }, @@ -1761,20 +1764,16 @@ } ] }, - "Proposal Submission Action": { + "Proposal Presentation Template": { "authors": {}, - "business_logic": { - "back_end": "A Submitted proposal with collaborators *MUST* have \na `final` submission by *ALL* listed `collaborators`.\nIf any `collaborator` has not submitted a `final` submission by the deadline, then the proposal \nis not considered `final` and will not be considered in the category it was being submitted to.", - "front_end": "A proposal with `collaborators` will not be shown as having a confirmed collaborator,\nunless there exists a `draft` or `final` proposal submission from that collaborator.\n\nAny document that lists a collaborator should be highlighted to that collaborator so\nthey can take appropriate action, such as:\n\n* Confirm they are a collaborator by submitting this document as `draft`\n* Agree to being a collaborator on the final submission by submitting this document as `final`\n* Hide themselves from the collaborators list but do not remove themselves by submitting `hide`\n* Remove themselves permanently as a collaborator by publishing a new version with them removed.\n\nTo eliminate the necessity for collaborators to accept collaboration on every version, \nthey will be considered as agreeing to be a collaborator on any version of the document\nthat lists them, if their latest submission is `draft` or `final`.\n\nIf their latest submission on a document is `hide` they should be considered to not\nhave agreed to be a collaborator.\n\n*NOTE* `final` status ONLY applies to the exactly referenced document and version." - }, - "description": "## Proposal Submission Action\n\nA Proposal Submission Action is a document which can attempt to either submit a \nparticular version of a proposal into a campaign, or withdraw it.\n\nThe last action on the document ts the action which takes effect at the deadline.\n\nFor multiple collaborators, multiple submission actions can be posted independently, \nbut none of them will take effect until ALL collaborators have posted equivalent actions.\n\nFor example, three collaborators Alice/Bob/Claire can each post one submission action\nfor the same document. \nUnless they all submit the same version of the proposal\nthe proposal will not be seen as submitted.\n\nThe payload is a fixed format.", + "description": "## Proposal Presentation Template Document\n\t\nA Proposal Presentation Template defines how the data\ncaptured by the Proposal Form Template is to be displayed.\n\nMultiple Proposal Presentation Templates can exist for the \nsame Proposal Form Template.\nEach can be used to display the form data under different \ncircumstances.\n\nProposal Presentation Templates can reference any data contained\nin the Proposal Document, as well as any documents linked by:\n\n* `ref`\n* `reply`\n* `parameters`\n\nThe presentation of the payload of a Proposal is controlled by \nits Proposal Presentation Template/s.", "headers": { "content type": { "coseLabel": 3, "description": "Media Type/s allowed in the Payload", "format": "Media Type", "required": "yes", - "value": "application/json" + "value": "application/schema+json" }, "content-encoding": { "coseLabel": "content-encoding", @@ -1808,9 +1807,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": [ - "ref" - ], + "linked_refs": null, "multiple": false, "required": "yes", "type": [ @@ -1823,10 +1820,7 @@ "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", "format": "Document Reference", - "linked_refs": null, - "multiple": true, - "required": "yes", - "type": "Proposal", + "required": "excluded", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { @@ -1868,110 +1862,46 @@ }, "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#", - "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/" - } - ], - "properties": { - "action": { - "$ref": "#/definitions/action" - } - }, - "required": [ - "action" - ], - "title": "Proposal Submission Action Payload Schema", - "type": "object", - "x-changelog": { - "2025-03-01": [ - "First Version Created." - ] - } - } + "description": "TBD.\nBut roughly, will be:\n\n1. A way to identify where the presentation template is intended to be used.\n2. Optional CSS to control the presentation.\n3. A Handlebars templated HTML or Markdown file data which defines the presentation." }, "signers": { - "referenced": true, "roles": { - "user": [ - "Proposer" - ] + "admin": [ + "Brand Admin", + "Campaign Admin" + ], + "user": [] }, "update": { - "author": true, - "collaborators": true + "author": true } }, "type": [ - "5e60e623-ad02-4a1b-a1ac-406db978ee48", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc", - "78927329-cfd9-4ea1-9c71-0e019b126a65" + "cb99b9bd-681a-49d8-9836-89107c02e8ef", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" ], - "validation": "No validation is required beyond as defined by:\n\n* [metadata](#metadata) \n* [payload](#payload)\n* [signers](#signers)", "versions": [ { - "changes": "* First Published Version", - "modified": "2025-04-04", - "version": "0.01" - }, - { - "changes": "* Use generalized parameters.", + "changes": "* First Version.", "modified": "2025-05-05", - "version": "0.03" + "version": "0.04" } ] }, - "Proposal Template": { + "Proposal Submission Action": { "authors": {}, - "description": "## Proposal Template Document\n\nA Proposal Template defines the allowed payload contents of a\nlinked proposal.\n\nProposals themselves are intentionally general, however they may be\nlinked to a brand/campaign or category via the template used by the proposal.\n\nThe payload of a proposal is controlled by its template.", + "business_logic": { + "back_end": "A Submitted proposal with collaborators *MUST* have \na `final` submission by *ALL* listed `collaborators`.\nIf any `collaborator` has not submitted a `final` submission by the deadline, then the proposal \nis not considered `final` and will not be considered in the category it was being submitted to.", + "front_end": "A proposal with `collaborators` will not be shown as having a confirmed collaborator,\nunless there exists a `draft` or `final` proposal submission from that collaborator.\n\nAny document that lists a collaborator should be highlighted to that collaborator so\nthey can take appropriate action, such as:\n\n* Confirm they are a collaborator by submitting this document as `draft`\n* Agree to being a collaborator on the final submission by submitting this document as `final`\n* Hide themselves from the collaborators list but do not remove themselves by submitting `hide`\n* Remove themselves permanently as a collaborator by publishing a new version with them removed.\n\nTo eliminate the necessity for collaborators to accept collaboration on every version, \nthey will be considered as agreeing to be a collaborator on any version of the document\nthat lists them, if their latest submission is `draft` or `final`.\n\nIf their latest submission on a document is `hide` they should be considered to not\nhave agreed to be a collaborator.\n\n*NOTE* `final` status ONLY applies to the exactly referenced document and version." + }, + "description": "## Proposal Submission Action\n\nA Proposal Submission Action is a document which can attempt to either submit a \nparticular version of a proposal into a campaign, or withdraw it.\n\nThe last action on the document ts the action which takes effect at the deadline.\n\nFor multiple collaborators, multiple submission actions can be posted independently, \nbut none of them will take effect until ALL collaborators have posted equivalent actions.\n\nFor example, three collaborators Alice/Bob/Claire can each post one submission action\nfor the same document. \nUnless they all submit the same version of the proposal\nthe proposal will not be seen as submitted.\n\nThe payload is a fixed format.", "headers": { "content type": { "coseLabel": 3, "description": "Media Type/s allowed in the Payload", "format": "Media Type", "required": "yes", - "value": "application/schema+json" + "value": "application/json" }, "content-encoding": { "coseLabel": "content-encoding", @@ -2006,7 +1936,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "linked_refs": [ - "template" + "ref" ], "multiple": false, "required": "yes", @@ -2020,7 +1950,10 @@ "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", "format": "Document Reference", - "required": "excluded", + "linked_refs": null, + "multiple": true, + "required": "yes", + "type": "Proposal", "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, "reply": { @@ -2044,10 +1977,7 @@ "template": { "description": "Reference to the template used to create and/or validate this document.", "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "optional", - "type": "Proposal Meta Template", + "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { @@ -2065,24 +1995,87 @@ }, "notes": [], "payload": { - "description": "JSON Schema document which defines the valid contents of a proposal document." + "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#", + "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/" + } + ], + "properties": { + "action": { + "$ref": "#/definitions/action" + } + }, + "required": [ + "action" + ], + "title": "Proposal Submission Action Payload Schema", + "type": "object", + "x-changelog": { + "2025-03-01": [ + "First Version Created." + ] + } + } }, "signers": { + "referenced": true, "roles": { - "admin": [ - "Brand Admin", - "Campaign Admin" - ], - "user": [] + "user": [ + "Proposer" + ] }, "update": { - "author": true + "author": true, + "collaborators": true } }, "type": [ - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "78927329-cfd9-4ea1-9c71-0e019b126a65" ], + "validation": "No validation is required beyond as defined by:\n\n* [metadata](#metadata) \n* [payload](#payload)\n* [signers](#signers)", "versions": [ { "changes": "* First Published Version", @@ -3397,11 +3390,11 @@ "multiple": false, "required": "optional", "type": [ - "Proposal Meta Template", - "Proposal Template", + "Proposal Form Template", + "Proposal Presentation Template", "Proposal", - "Proposal Comment Meta Template", - "Proposal Comment Template", + "Proposal Comment Form Template", + "Proposal Comment Presentation Template", "Proposal Comment", "Proposal Submission Action", "Proposal Moderation Action", @@ -3443,10 +3436,8 @@ "multiple": false, "required": "optional", "type": [ - "Proposal Meta Template", - "Proposal Template", - "Proposal Comment Meta Template", - "Proposal Comment Template" + "Proposal Form Template", + "Proposal Comment Form Template" ], "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, @@ -3473,7 +3464,8 @@ "section", "collaborators", "revocations", - "parameters" + "parameters", + "chain" ] } } From a9dd9119e206286b98e7fba15becf74981527ffe Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 23 Jun 2025 13:16:47 +0700 Subject: [PATCH 25/42] docs(docs): Add fully generalized, templated parameters documents to the specification. --- .config/dictionaries/project.dic | 1 + .gitignore | 2 + .../08_concepts/signed_doc/diagrams/all.dot | 770 +++++++++++++----- .../signed_doc/diagrams/brand_parameters.dot | 243 ++++-- ...dot => brand_parameters_form_template.dot} | 21 +- .../diagrams/campaign_parameters.dot | 287 ++++--- .../campaign_parameters_form_template.dot | 135 +++ .../diagrams/category_parameters.dot | 263 ++++-- .../category_parameters_form_template.dot | 135 +++ .../diagrams/contest_parameters.dot | 179 ++++ .../contest_parameters_form_template.dot | 150 ++++ .../signed_doc/docs/brand_parameters.md | 113 ++- ...s.md => brand_parameters_form_template.md} | 51 +- .../signed_doc/docs/campaign_parameters.md | 114 ++- .../docs/campaign_parameters_form_template.md | 180 ++++ .../signed_doc/docs/category_parameters.md | 114 ++- .../docs/category_parameters_form_template.md | 180 ++++ .../docs/comment_moderation_action.md | 2 +- .../signed_doc/docs/contest_parameters.md | 237 ++++++ .../docs/contest_parameters_form_template.md | 180 ++++ .../docs/proposal_comment_form_template.md | 3 - .../proposal_comment_presentation_template.md | 2 - .../signed_doc/docs/proposal_form_template.md | 3 - .../docs/proposal_moderation_action.md | 2 +- .../docs/proposal_presentation_template.md | 2 - .../docs/proposal_submission_action.md | 12 +- .../08_concepts/signed_doc/metadata.md | 22 +- .../08_concepts/signed_doc/types.md | 15 +- specs/definitions/signed_docs/docs/all.cue | 34 +- .../signed_docs/docs/brand_parameters.cue | 23 - .../signed_docs/docs/campaign_parameters.cue | 33 - .../signed_docs/docs/category_parameters.cue | 35 - .../signed_docs/docs/decision_parameters.cue | 33 - .../docs/generic_form_template.cue | 8 +- .../signed_docs/docs/generic_parameters.cue | 88 ++ .../docs/generic_presentation_template.cue | 2 - .../signed_docs/docs/parameters_brand.cue | 21 + .../docs/parameters_brand_form_template.cue | 11 + .../signed_docs/docs/parameters_campaign.cue | 24 + .../parameters_campaign_form_template.cue | 12 + .../signed_docs/docs/parameters_category.cue | 24 + .../parameters_category_form_template.cue | 12 + .../signed_docs/docs/parameters_contest.cue | 24 + .../docs/parameters_contest_form_template.cue | 12 + .../docs/proposal_submission_action.cue | 2 +- .../signed_docs/metadata_chain.cue | 6 +- specs/generators/src/docs/doc_generator.py | 12 +- specs/signed_doc.json | 714 ++++++++++++++-- 48 files changed, 3811 insertions(+), 737 deletions(-) rename docs/src/architecture/08_concepts/signed_doc/diagrams/{decision_parameters.dot => brand_parameters_form_template.dot} (83%) create mode 100644 docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot create mode 100644 docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot create mode 100644 docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot create mode 100644 docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot rename docs/src/architecture/08_concepts/signed_doc/docs/{decision_parameters.md => brand_parameters_form_template.md} (69%) create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md delete mode 100644 specs/definitions/signed_docs/docs/brand_parameters.cue delete mode 100644 specs/definitions/signed_docs/docs/campaign_parameters.cue delete mode 100644 specs/definitions/signed_docs/docs/category_parameters.cue delete mode 100644 specs/definitions/signed_docs/docs/decision_parameters.cue create mode 100644 specs/definitions/signed_docs/docs/generic_parameters.cue create mode 100644 specs/definitions/signed_docs/docs/parameters_brand.cue create mode 100644 specs/definitions/signed_docs/docs/parameters_brand_form_template.cue create mode 100644 specs/definitions/signed_docs/docs/parameters_campaign.cue create mode 100644 specs/definitions/signed_docs/docs/parameters_campaign_form_template.cue create mode 100644 specs/definitions/signed_docs/docs/parameters_category.cue create mode 100644 specs/definitions/signed_docs/docs/parameters_category_form_template.cue create mode 100644 specs/definitions/signed_docs/docs/parameters_contest.cue create mode 100644 specs/definitions/signed_docs/docs/parameters_contest_form_template.cue diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index 7fe0292a9cf..3c86b726ff9 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -22,6 +22,7 @@ blockdiag blockfetch blosc bmac +Bogale bootstrapper BROTLI Cabe diff --git a/.gitignore b/.gitignore index 16f34110365..e61ead2abd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +new + ## Secrets **/.secret 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 d9e0d6cdbe9..6a3eb523512 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot @@ -12,196 +12,200 @@ digraph "All" { - subgraph cluster_system_parameters { - label = "System Parameters"; - color=blue - penwidth=20 - - "Brand Parameters" [ - id="Brand Parameters"; - label=< - - - - - - - - - - - - - - - - + "Brand Parameters Form Template" [ + id="Brand Parameters Form Template"; + label=< +
- Brand Parameters -
- - - - - -
content typeapplication/json
-
- - - - - -
typeebcabeeb-5bc5-4f95-91e8-cab8ca724172
-
- - - - - -
idDocument Id
-
- - - - - -
verDocument Ver
-
+ + + + + + + + + + + + + + + + + + -
+ Brand Parameters Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
typeebcabeeb-5bc5-4f95-91e8-cab8ca724172
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersBrand Parameters
Campaign Parameters
Category Parameters
+
- > - ]; + + > + ]; - "Campaign Parameters" [ - id="Campaign Parameters"; - label=< - - - - - - - - - - - - - - - - - - - + "Campaign Parameters Form Template" [ + id="Campaign Parameters Form Template"; + label=< +
- Campaign Parameters -
- - - - - -
content typeapplication/json
-
- - - - - -
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
-
- - - - - -
idDocument Id
-
- - - - - -
verDocument Ver
-
- - - - - -
parametersBrand Parameters
-
+ + + + + + + + + + + + + + + + + + -
+ Campaign Parameters Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersBrand Parameters
Campaign Parameters
Category Parameters
+
- > - ]; + + > + ]; - "Category Parameters" [ - id="Category Parameters"; - label=< - - - - - - - - - - - - - - - - - - - + "Category Parameters Form Template" [ + id="Category Parameters Form Template"; + label=< +
- Category Parameters -
- - - - - -
content typeapplication/json
-
- - - - - -
type818938c3-3139-4daa-afe6-974c78488e95
-
- - - - - -
idDocument Id
-
- - - - - -
verDocument Ver
-
- - - - - -
parametersCampaign Parameters
-
+ + + + + + + + + + + + + + + + + + -
+ Category Parameters Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type818938c3-3139-4daa-afe6-974c78488e95
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersBrand Parameters
Campaign Parameters
Category Parameters
+
- > - ]; + + > + ]; - } "Proposal Comment" [ id="Proposal Comment"; @@ -383,13 +387,78 @@ digraph "All" { ]; - "Decision Parameters" [ - id="Decision Parameters"; + "Contest Parameters Form Template" [ + id="Contest Parameters Form Template"; label=< - + + + + + + + + + + + + + + + + + +
- Decision Parameters + + Contest Parameters Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type788ff4c6-d65a-451f-bb33-575fe056b411
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersBrand Parameters
Campaign Parameters
Category Parameters
+
+ > + ]; + + + "Contest Parameters" [ + id="Contest Parameters"; + label=< + + + @@ -407,7 +476,7 @@ digraph "All" {
+ Contest Parameters
- +
type788ff4c6-d65a-451f-bb33-575fe056b411788ff4c6-d65a-451f-bb33-575fe056b411
60185874-7e13-407c-a06c-238ffe637ae6
@@ -426,14 +495,44 @@ digraph "All" { - - + + + +
verDocument VerverDocument Ver
+ + + + + + + + + +
templateContest Parameters Form Template
+ + + + + + + + + +
collaboratorsCollaborators Reference List
+ + + + + + + +
revocationsVersion Revocations
- + @@ -943,10 +1042,299 @@ digraph "All" { ]; + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 + + "Brand Parameters" [ + id="Brand Parameters"; + label=< +
parameters
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Brand Parameters +
+ + + + + +
content typeapplication/json
+
+ + + + + +
typeebcabeeb-5bc5-4f95-91e8-cab8ca724172
60185874-7e13-407c-a06c-238ffe637ae6
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
templateBrand Parameters Form Template
+
+ + + + + +
collaboratorsCollaborators Reference List
+
+ + + + + +
revocationsVersion Revocations
+
+ > + ]; + + + "Campaign Parameters" [ + id="Campaign Parameters"; + label=< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Campaign Parameters +
+ + + + + +
content typeapplication/json
+
+ + + + + +
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
60185874-7e13-407c-a06c-238ffe637ae6
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
templateCampaign Parameters Form Template
+
+ + + + + +
collaboratorsCollaborators Reference List
+
+ + + + + +
revocationsVersion Revocations
+
+ + + + + +
parametersBrand Parameters
+
+ > + ]; + + + "Category Parameters" [ + id="Category Parameters"; + label=< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Category Parameters +
+ + + + + +
content typeapplication/json
+
+ + + + + +
type818938c3-3139-4daa-afe6-974c78488e95
60185874-7e13-407c-a06c-238ffe637ae6
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
templateCategory Parameters Form Template
+
+ + + + + +
collaboratorsCollaborators Reference List
+
+ + + + + +
revocationsVersion Revocations
+
+ + + + + +
parametersCampaign Parameters
+
+ > + ]; + + } + + "Brand Parameters":"template":e -> "Brand Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Brand Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Campaign Parameters":"template":e -> "Campaign Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Campaign Parameters":"parameters":e -> "Brand Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Campaign Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Category Parameters":"template":e -> "Category Parameters Form Template":"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="*"] + "Category Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "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"] + "Contest Parameters":"template":e -> "Contest Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Contest Parameters":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Contest Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal":"template":e -> "Proposal Form 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 e9d334cd427..d537924e337 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 @@ -13,89 +13,73 @@ Relationships" - subgraph cluster_system_parameters { - label = "System Parameters"; - color=blue - penwidth=20 + "Brand Parameters Form Template" [ + id="Brand Parameters Form Template"; + label=< + + + + - "Brand Parameters" [ - id="Brand Parameters"; - label=< -
+ Brand Parameters Form Template +
- - - - - - - - - - - - - - - +
- Brand Parameters -
- - - - - -
content typeapplication/json
-
- - - - - -
typeebcabeeb-5bc5-4f95-91e8-cab8ca724172
-
- - - - - -
idDocument Id
-
- - - - - -
verDocument Ver
-
+ > + ]; - - > - ]; + "Campaign Parameters Form Template" [ + id="Campaign Parameters Form Template"; + label=< + + + + - "Campaign Parameters" [ - id="Campaign Parameters"; - label=< -
+ Campaign Parameters Form Template +
- - - +
- Campaign Parameters -
+ > + ]; - - > - ]; - } + "Category Parameters Form Template" [ + id="Category Parameters Form Template"; + label=< + + + + - "Decision Parameters" [ - id="Decision Parameters"; +
+ Category Parameters Form Template +
+ > + ]; + + + "Contest Parameters" [ + id="Contest Parameters"; label=< - + + +
- Decision Parameters + + Contest Parameters +
+ > + ]; + + + "Contest Parameters Form Template" [ + id="Contest Parameters Form Template"; + label=< + + + @@ -209,8 +193,119 @@ Relationships" ]; + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 + + "Brand Parameters" [ + id="Brand Parameters"; + label=< +
+ Contest Parameters Form Template
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Brand Parameters +
+ + + + + +
content typeapplication/json
+
+ + + + + +
typeebcabeeb-5bc5-4f95-91e8-cab8ca724172
60185874-7e13-407c-a06c-238ffe637ae6
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
templateBrand Parameters Form Template
+
+ + + + + +
collaboratorsCollaborators Reference List
+
+ + + + + +
revocationsVersion Revocations
+
+ > + ]; + + + "Campaign Parameters" [ + id="Campaign Parameters"; + label=< + + + + + +
+ Campaign Parameters +
+ > + ]; + + } + + "Brand Parameters":"template":e -> "Brand Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Brand Parameters Form Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "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"] + "Campaign Parameters Form Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Category Parameters Form Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Contest Parameters":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Contest Parameters Form Template":"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 Form 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/decision_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters_form_template.dot similarity index 83% rename from docs/src/architecture/08_concepts/signed_doc/diagrams/decision_parameters.dot rename to docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters_form_template.dot index ff41dcf0f65..9d421279b56 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/decision_parameters.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters_form_template.dot @@ -1,12 +1,12 @@ -digraph "Decision Parameters" { +digraph "Brand Parameters Form Template" { rankdir="LR" graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; labelloc="t" - label="Decision Parameters Document -Relationships" + label="Brand Parameters Form Template +Document Relationships" fontcolor="#1d71b8" fontsize=50 compound=true @@ -64,13 +64,13 @@ Relationships" } - "Decision Parameters" [ - id="Decision Parameters"; + "Brand Parameters Form Template" [ + id="Brand Parameters Form Template"; label=< - @@ -78,7 +78,7 @@ Relationships"
- Decision Parameters + + Brand Parameters Form Template
- +
content typeapplication/jsonapplication/schema+json
@@ -88,7 +88,7 @@ Relationships" - +
type788ff4c6-d65a-451f-bb33-575fe056b411ebcabeeb-5bc5-4f95-91e8-cab8ca724172
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
@@ -129,5 +129,6 @@ Relationships" ]; - "Decision Parameters":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Brand Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Brand Parameters":"title":e -> "Brand Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } 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 9286456e868..b8a11fc2f86 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 @@ -13,114 +13,73 @@ Relationships" - subgraph cluster_system_parameters { - label = "System Parameters"; - color=blue - penwidth=20 + "Campaign Parameters Form Template" [ + id="Campaign Parameters Form Template"; + label=< + + + + - "Brand Parameters" [ - id="Brand Parameters"; - label=< -
+ Campaign Parameters Form Template +
- - - +
- Brand Parameters -
+ > + ]; - - > - ]; + "Brand Parameters Form Template" [ + id="Brand Parameters Form Template"; + label=< + + + + - "Campaign Parameters" [ - id="Campaign Parameters"; - label=< -
+ Brand Parameters Form Template +
- - - - - - - - - - - - - - - - - - +
- Campaign Parameters -
- - - - - -
content typeapplication/json
-
- - - - - -
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
-
- - - - - -
idDocument Id
-
- - - - - -
verDocument Ver
-
- - - - - -
parametersBrand Parameters
-
+ > + ]; - - > - ]; + "Category Parameters Form Template" [ + id="Category Parameters Form Template"; + label=< + + + + - "Category Parameters" [ - id="Category Parameters"; - label=< -
+ Category Parameters Form Template +
- - - +
- Category Parameters -
+ > + ]; - - > - ]; - } + "Contest Parameters" [ + id="Contest Parameters"; + label=< + + + + + +
+ Contest Parameters +
+ > + ]; - "Decision Parameters" [ - id="Decision Parameters"; + + "Contest Parameters Form Template" [ + id="Contest Parameters Form Template"; label=< - @@ -234,9 +193,145 @@ Relationships" ]; + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 + + "Brand Parameters" [ + id="Brand Parameters"; + label=< +
- Decision Parameters + + Contest Parameters Form Template
+ + + + +
+ Brand Parameters +
+ > + ]; + + + "Campaign Parameters" [ + id="Campaign Parameters"; + label=< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Campaign Parameters +
+ + + + + +
content typeapplication/json
+
+ + + + + +
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
60185874-7e13-407c-a06c-238ffe637ae6
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
templateCampaign Parameters Form Template
+
+ + + + + +
collaboratorsCollaborators Reference List
+
+ + + + + +
revocationsVersion Revocations
+
+ + + + + +
parametersBrand Parameters
+
+ > + ]; + + + "Category Parameters" [ + id="Category Parameters"; + label=< + + + + + +
+ Category Parameters +
+ > + ]; + + } + + "Campaign Parameters":"template":e -> "Campaign Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Campaign Parameters":"parameters":e -> "Brand Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Brand Parameters Form Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Campaign Parameters Form Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "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"] + "Category Parameters Form Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Contest Parameters":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Contest Parameters Form Template":"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 Form 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/campaign_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot new file mode 100644 index 00000000000..aff620a00e3 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot @@ -0,0 +1,135 @@ +digraph "Campaign Parameters Form Template" { + rankdir="LR" + graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; + node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; + edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; + + labelloc="t" + label="Campaign Parameters Form +Template Document +Relationships" + fontcolor="#1d71b8" + fontsize=50 + compound=true + + + + 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 +
+ > + ]; + + } + + "Campaign Parameters Form Template" [ + id="Campaign Parameters Form Template"; + label=< + + + + + + + + + + + + + + + + + + + + +
+ Campaign Parameters Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersBrand Parameters
Campaign Parameters
Category Parameters
+
+ > + ]; + + + "Campaign Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Campaign Parameters":"title":e -> "Campaign Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] +} 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 7e846b3224d..0e4a3ba08e3 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 @@ -13,99 +13,73 @@ Relationships" - subgraph cluster_system_parameters { - label = "System Parameters"; - color=blue - penwidth=20 + "Category Parameters Form Template" [ + id="Category Parameters Form Template"; + label=< + + + + - "Campaign Parameters" [ - id="Campaign Parameters"; - label=< -
+ Category Parameters Form Template +
- - - +
- Campaign Parameters -
+ > + ]; - - > - ]; + "Brand Parameters Form Template" [ + id="Brand Parameters Form Template"; + label=< + + + + - "Category Parameters" [ - id="Category Parameters"; - label=< -
+ Brand Parameters Form Template +
- - - - - - - - - - - - - - - - - - +
- Category Parameters -
- - - - - -
content typeapplication/json
-
- - - - - -
type818938c3-3139-4daa-afe6-974c78488e95
-
- - - - - -
idDocument Id
-
- - - - - -
verDocument Ver
-
- - - - - -
parametersCampaign Parameters
-
+ > + ]; - - > - ]; - } + "Campaign Parameters Form Template" [ + id="Campaign Parameters Form Template"; + label=< + + + + - "Decision Parameters" [ - id="Decision Parameters"; +
+ Campaign Parameters Form Template +
+ > + ]; + + + "Contest Parameters" [ + id="Contest Parameters"; label=< - + + +
- Decision Parameters + + Contest Parameters +
+ > + ]; + + + "Contest Parameters Form Template" [ + id="Contest Parameters Form Template"; + label=< + + + @@ -219,8 +193,129 @@ Relationships" ]; + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 + + "Campaign Parameters" [ + id="Campaign Parameters"; + label=< +
+ Contest Parameters Form Template
+ + + + +
+ Campaign Parameters +
+ > + ]; + + + "Category Parameters" [ + id="Category Parameters"; + label=< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Category Parameters +
+ + + + + +
content typeapplication/json
+
+ + + + + +
type818938c3-3139-4daa-afe6-974c78488e95
60185874-7e13-407c-a06c-238ffe637ae6
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
templateCategory Parameters Form Template
+
+ + + + + +
collaboratorsCollaborators Reference List
+
+ + + + + +
revocationsVersion Revocations
+
+ + + + + +
parametersCampaign Parameters
+
+ > + ]; + + } + + "Category Parameters":"template":e -> "Category Parameters Form Template":"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="*"] - "Decision Parameters":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Brand Parameters Form Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Campaign Parameters Form Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Category Parameters Form Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Contest Parameters":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Contest Parameters Form Template":"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 Form 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/category_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot new file mode 100644 index 00000000000..fca38408d6a --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot @@ -0,0 +1,135 @@ +digraph "Category Parameters Form Template" { + rankdir="LR" + graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; + node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; + edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; + + labelloc="t" + label="Category Parameters Form +Template Document +Relationships" + fontcolor="#1d71b8" + fontsize=50 + compound=true + + + + 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 +
+ > + ]; + + } + + "Category Parameters Form Template" [ + id="Category Parameters Form Template"; + label=< + + + + + + + + + + + + + + + + + + + + +
+ Category Parameters Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type818938c3-3139-4daa-afe6-974c78488e95
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersBrand Parameters
Campaign Parameters
Category Parameters
+
+ > + ]; + + + "Category Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Category Parameters":"title":e -> "Category Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] +} diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot new file mode 100644 index 00000000000..092e7245e71 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot @@ -0,0 +1,179 @@ +digraph "Contest Parameters" { + rankdir="LR" + graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; + node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; + edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; + + labelloc="t" + label="Contest Parameters Document +Relationships" + fontcolor="#1d71b8" + fontsize=50 + compound=true + + + + "Contest Parameters Form Template" [ + id="Contest Parameters Form Template"; + label=< + + + + + +
+ Contest Parameters Form Template +
+ > + ]; + + + "Contest Parameters" [ + id="Contest Parameters"; + label=< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Contest Parameters +
+ + + + + +
content typeapplication/json
+
+ + + + + +
type788ff4c6-d65a-451f-bb33-575fe056b411
60185874-7e13-407c-a06c-238ffe637ae6
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
templateContest Parameters Form Template
+
+ + + + + +
collaboratorsCollaborators Reference List
+
+ + + + + +
revocationsVersion Revocations
+
+ + + + + +
parametersBrand Parameters
Campaign Parameters
Category Parameters
+
+ > + ]; + + + 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 +
+ > + ]; + + } + + "Contest Parameters":"template":e -> "Contest Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Contest Parameters":"parameters":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/contest_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot new file mode 100644 index 00000000000..8c2f1edf674 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot @@ -0,0 +1,150 @@ +digraph "Contest Parameters Form Template" { + rankdir="LR" + graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; + node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; + edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; + + labelloc="t" + label="Contest Parameters Form +Template Document +Relationships" + fontcolor="#1d71b8" + fontsize=50 + compound=true + + + + 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 +
+ > + ]; + + } + + "Contest Parameters Form Template" [ + id="Contest Parameters Form Template"; + label=< + + + + + + + + + + + + + + + + + + + + +
+ Contest Parameters Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type788ff4c6-d65a-451f-bb33-575fe056b411
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersBrand Parameters
Campaign Parameters
Category Parameters
+
+ > + ]; + + + "Contest Parameters" [ + id="Contest Parameters"; + label=< + + + + + +
+ Contest Parameters +
+ > + ]; + + + "Contest Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Contest Parameters":"title":e -> "Contest Parameters Form Template":"title":w [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 020d060cfae..d12cc399e90 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,24 @@ ## Description -Parameters which define this brand within the system. +Brand Parameters define the parameter data required for the +system at the Brand level. + +Parameter Data includes things such as: + +* Functional parameters +* Timeline data +* Branded Content and Copy + +The content of the parameters is defined solely by the +Brand Parameters Form Template. + +This allows parameters to vary based on individual system +requirements over time. + +Functional Parameters are mapped using the (TBD Functional Parameters Map). + +The payload of a Brand is controlled by its template. @@ -14,10 +31,7 @@ Parameters which define this brand within the system. ### Validation -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. +No extra validation defined. ### Business Logic @@ -49,7 +63,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `ebcabeeb-5bc5-4f95-91e8-cab8ca724172` | +| Type | `ebcabeeb-5bc5-4f95-91e8-cab8ca724172`,
`60185874-7e13-407c-a06c-238ffe637ae6` | The document TYPE. @@ -91,22 +105,90 @@ The first version of the document must set [`ver`](../metadata.md#ver) == [`id`] The document version must always be >= the document ID. +### [`template`](../metadata.md#template) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Brand Parameters Form Template](brand_parameters_form_template.md) | + +Reference to the template used to create and/or validate this document. + +#### [`template`](../metadata.md#template) Validation + +In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields, +The document payload is not valid if it does not validate completely against the referenced template. + +### [`collaborators`](../metadata.md#collaborators) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Collaborators Reference List](../metadata.md#collaborators-reference-list) | + +A list of collaborators who may also publish updates to versions of this document. +This should include all parties who have not signed this document directly. + +Every subsequent version can amend the collaborators list. +However, the initial Author can never be removed from being able to +publish a new version of the document. + +#### [`collaborators`](../metadata.md#collaborators) Validation + +This list does not imply these collaborators have consented to collaborate, only that the author/s +are permitting these potential collaborators to participate in the drafting and submission process. +However, any document submission referencing a proposal MUST be signed by all collaborators in +addition to the author. + +### [`revocations`](../metadata.md#revocations) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Version Revocations](../metadata.md#version-revocations) | + +A document may include a list of any prior versions which are considered to be revoked. +Only the revocation list in the latest version of the document applies. +Revoked documents are flagged as no longer valid, and should not be displayed. +As a special case, if the revocations are set to `true` then all versions of the document +are revoked, including the latest document. + +In this case, when the latest document is revoked, the payload may be empty. +Any older document that has [`revocations`](../metadata.md#revocations) set to `true` is always to be filtered +and its payload is to be assumed to be invalid. + +This allows for an entire document and any/all published versions to be revoked. +A new version of the document that is published after this, may reinstate prior +document versions, by not listing them as revoked. +However, any document where revocations was set `true` can never be reinstated. + +#### [`revocations`](../metadata.md#revocations) Validation + +If the field is `true` the payload may be absent or invalid. +Such documents may never be submitted. + ## 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. +Brand Parameters Document controlling the Brand +within a Brand. + +Must be valid according to the schema contained within the +[Document Reference](../metadata.md#document-reference) from the [`template`](../metadata.md#template) metadata. ## Signers -The following User roles may sign documents of this type: +The following Admin roles may sign documents of this type: -* Registered +* Brand Admin New versions of this document may be published by: * author +* collaborators ## Copyright @@ -114,8 +196,9 @@ 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-30 | +| Modified | 2025-06-20 | | Authors | Alex Pozhylenkov | +| | Nathan Bogale | | | Steven Johnson | ### Changelog @@ -124,6 +207,10 @@ New versions of this document may be published by: * First Published Version +#### 0.02 (2025-06-20) + +* Generalized as another kind of form data document + [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode [RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/decision_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md similarity index 69% rename from docs/src/architecture/08_concepts/signed_doc/docs/decision_parameters.md rename to docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md index c2caa541f08..a45bdf723eb 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/decision_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md @@ -1,13 +1,32 @@ -# Decision Parameters +# Brand Parameters Form Template ## Description -Parameters which define an individual voting event. +A Brand Parameters Form Template defines both: + +* The data that is entered in the Form. +* Formatting hints for the collection of the data in a form. + +A Brand Parameters Form Template is a [JSON Schema][JSON Schema-2020-12] Document. + +Brand Parameters entry *SHOULD* use the hints when collecting +data defined by the Brand Parameters Form Template to provide a +consistent user interface. +It *CAN* also use those hints when re-displaying the full forms data. + +Alternatively a Brand Parameters Presentation Template can be used to +format the Brand Parameters data for presentation. + +The Brand Parameters Document is intentionally general, +however it may be linked to a brand/campaign or category +via the template used by the Brand Parameters. + +The payload of a Brand Parameters is controlled by its template. -```graphviz dot decision_parameters.dot.svg -{{ include_file('./../diagrams/decision_parameters.dot', indent=4) }} +```graphviz dot brand_parameters_form_template.dot.svg +{{ include_file('./../diagrams/brand_parameters_form_template.dot', indent=4) }} ``` @@ -37,7 +56,7 @@ This section will be included and updated in future iterations. ## [COSE Header Parameters][RFC9052-HeaderParameters] -* [content type](../spec.md#content-type) = `application/json` +* [content type](../spec.md#content-type) = `application/schema+json` * [content-encoding](../spec.md#content-encoding) = `[br]` ## Metadata @@ -49,7 +68,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `788ff4c6-d65a-451f-bb33-575fe056b411` | +| Type | `ebcabeeb-5bc5-4f95-91e8-cab8ca724172`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | The document TYPE. @@ -101,6 +120,7 @@ The document version must always be >= the document ID. | Valid References | [Brand Parameters](brand_parameters.md) | | | [Campaign Parameters](campaign_parameters.md) | | | [Category Parameters](category_parameters.md) | +| Linked Reference Metadata | [`template`](#template) | A reference to the Parameters Document this document lies under. @@ -110,19 +130,21 @@ In addition to the validation performed for [Document Reference](../metadata.md# * Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the [`parameters`](../metadata.md#parameters) of the referencing document. +* The Document referenced by [`template`](../metadata.md#template) + * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND + * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. ## 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. +[JSON Schema][JSON Schema-2020-12] document which defines the valid contents and +formatting hints for the collection of data for a +Brand Parameters Document. ## Signers -The following User roles may sign documents of this type: +The following Admin roles may sign documents of this type: -* Registered +* Brand Admin New versions of this document may be published by: @@ -148,6 +170,11 @@ New versions of this document may be published by: * Use generalized parameters. +#### 0.04 (2025-05-05) + +* Generalize the Form Template definitions. + [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode [RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters.md index b0953e03402..877aae9468f 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,24 @@ ## Description -Parameters which define a Campaign within a Brand in the system. +Campaign Parameters define the parameter data required for the +system at the Campaign level. + +Parameter Data includes things such as: + +* Functional parameters +* Timeline data +* Branded Content and Copy + +The content of the parameters is defined solely by the +Campaign Parameters Form Template. + +This allows parameters to vary based on individual system +requirements over time. + +Functional Parameters are mapped using the (TBD Functional Parameters Map). + +The payload of a Campaign is controlled by its template. @@ -14,10 +31,8 @@ Parameters which define a Campaign within a Brand in the system. ### Validation -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. +The Campaign Parameters Document *MUST* be linked through [`parameters`](../metadata.md#parameters) to +its Brand Parameters Document. ### Business Logic @@ -49,7 +64,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `5ef32d5d-f240-462c-a7a4-ba4af221fa23` | +| Type | `5ef32d5d-f240-462c-a7a4-ba4af221fa23`,
`60185874-7e13-407c-a06c-238ffe637ae6` | The document TYPE. @@ -91,6 +106,72 @@ The first version of the document must set [`ver`](../metadata.md#ver) == [`id`] The document version must always be >= the document ID. +### [`template`](../metadata.md#template) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Campaign Parameters Form Template](campaign_parameters_form_template.md) | + +Reference to the template used to create and/or validate this document. + +#### [`template`](../metadata.md#template) Validation + +In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields, +The document payload is not valid if it does not validate completely against the referenced template. + +### [`collaborators`](../metadata.md#collaborators) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Collaborators Reference List](../metadata.md#collaborators-reference-list) | + +A list of collaborators who may also publish updates to versions of this document. +This should include all parties who have not signed this document directly. + +Every subsequent version can amend the collaborators list. +However, the initial Author can never be removed from being able to +publish a new version of the document. + +#### [`collaborators`](../metadata.md#collaborators) Validation + +This list does not imply these collaborators have consented to collaborate, only that the author/s +are permitting these potential collaborators to participate in the drafting and submission process. +However, any document submission referencing a proposal MUST be signed by all collaborators in +addition to the author. + +### [`revocations`](../metadata.md#revocations) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Version Revocations](../metadata.md#version-revocations) | + +A document may include a list of any prior versions which are considered to be revoked. +Only the revocation list in the latest version of the document applies. +Revoked documents are flagged as no longer valid, and should not be displayed. +As a special case, if the revocations are set to `true` then all versions of the document +are revoked, including the latest document. + +In this case, when the latest document is revoked, the payload may be empty. +Any older document that has [`revocations`](../metadata.md#revocations) set to `true` is always to be filtered +and its payload is to be assumed to be invalid. + +This allows for an entire document and any/all published versions to be revoked. +A new version of the document that is published after this, may reinstate prior +document versions, by not listing them as revoked. +However, any document where revocations was set `true` can never be reinstated. + +#### [`revocations`](../metadata.md#revocations) Validation + +If the field is `true` the payload may be absent or invalid. +Such documents may never be submitted. + ### [`parameters`](../metadata.md#parameters) @@ -111,20 +192,22 @@ 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. +Campaign Parameters Document controlling the Campaign +within a Brand. + +Must be valid according to the schema contained within the +[Document Reference](../metadata.md#document-reference) from the [`template`](../metadata.md#template) metadata. ## Signers -The following User roles may sign documents of this type: +The following Admin roles may sign documents of this type: -* Registered +* Brand Admin New versions of this document may be published by: * author +* collaborators ## Copyright @@ -132,8 +215,9 @@ 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-30 | +| Modified | 2025-06-20 | | Authors | Alex Pozhylenkov | +| | Nathan Bogale | | | Steven Johnson | ### Changelog @@ -142,9 +226,9 @@ New versions of this document may be published by: * First Published Version -#### 0.03 (2025-05-05) +#### 0.02 (2025-06-20) -* Use generalized parameters. +* Generalized as another kind of form data document [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_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md new file mode 100644 index 00000000000..60bd9ecaff8 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md @@ -0,0 +1,180 @@ +# Campaign Parameters Form Template + +## Description + +A Campaign Parameters Form Template defines both: + +* The data that is entered in the Form. +* Formatting hints for the collection of the data in a form. + +A Campaign Parameters Form Template is a [JSON Schema][JSON Schema-2020-12] Document. + +Campaign Parameters entry *SHOULD* use the hints when collecting +data defined by the Campaign Parameters Form Template to provide a +consistent user interface. +It *CAN* also use those hints when re-displaying the full forms data. + +Alternatively a Campaign Parameters Presentation Template can be used to +format the Campaign Parameters data for presentation. + +The Campaign Parameters Document is intentionally general, +however it may be linked to a brand/campaign or category +via the template used by the Campaign Parameters. + +The payload of a Campaign Parameters is controlled by its template. + + + +```graphviz dot campaign_parameters_form_template.dot.svg +{{ include_file('./../diagrams/campaign_parameters_form_template.dot', indent=4) }} +``` + + + +### Validation + +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. + +### Business Logic + +#### Front End + +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. + +#### Back End + +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. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +* [content type](../spec.md#content-type) = `application/schema+json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `5ef32d5d-f240-462c-a7a4-ba4af221fa23`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a document with +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +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) | +| | [Campaign Parameters](campaign_parameters.md) | +| | [Category Parameters](category_parameters.md) | +| Linked Reference Metadata | [`template`](#template) | + +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. +* The Document referenced by [`template`](../metadata.md#template) + * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND + * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. + +## Payload + +[JSON Schema][JSON Schema-2020-12] document which defines the valid contents and +formatting hints for the collection of data for a +Campaign Parameters Document. + +## Signers + +The following Admin roles may sign documents of this type: + +* Brand Admin + +New versions of this document may be published by: + +* author + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-05-30 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-04-04) + +* First Published Version + +#### 0.03 (2025-05-05) + +* Use generalized parameters. + +#### 0.04 (2025-05-05) + +* Generalize the Form Template definitions. + +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters.md index e963837dbf2..df7ca591169 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,24 @@ ## Description -Parameters which define a Category withing a Campaign under a Brand in the system. +Category Parameters define the parameter data required for the +system at the Category level. + +Parameter Data includes things such as: + +* Functional parameters +* Timeline data +* Branded Content and Copy + +The content of the parameters is defined solely by the +Category Parameters Form Template. + +This allows parameters to vary based on individual system +requirements over time. + +Functional Parameters are mapped using the (TBD Functional Parameters Map). + +The payload of a Category is controlled by its template. @@ -14,10 +31,8 @@ Parameters which define a Category withing a Campaign under a Brand in the syste ### Validation -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. +The Category Parameters Document *MUST* be linked through [`parameters`](../metadata.md#parameters) to +its Campaign Parameters Document. ### Business Logic @@ -49,7 +64,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `818938c3-3139-4daa-afe6-974c78488e95` | +| Type | `818938c3-3139-4daa-afe6-974c78488e95`,
`60185874-7e13-407c-a06c-238ffe637ae6` | The document TYPE. @@ -91,6 +106,72 @@ The first version of the document must set [`ver`](../metadata.md#ver) == [`id`] The document version must always be >= the document ID. +### [`template`](../metadata.md#template) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Category Parameters Form Template](category_parameters_form_template.md) | + +Reference to the template used to create and/or validate this document. + +#### [`template`](../metadata.md#template) Validation + +In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields, +The document payload is not valid if it does not validate completely against the referenced template. + +### [`collaborators`](../metadata.md#collaborators) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Collaborators Reference List](../metadata.md#collaborators-reference-list) | + +A list of collaborators who may also publish updates to versions of this document. +This should include all parties who have not signed this document directly. + +Every subsequent version can amend the collaborators list. +However, the initial Author can never be removed from being able to +publish a new version of the document. + +#### [`collaborators`](../metadata.md#collaborators) Validation + +This list does not imply these collaborators have consented to collaborate, only that the author/s +are permitting these potential collaborators to participate in the drafting and submission process. +However, any document submission referencing a proposal MUST be signed by all collaborators in +addition to the author. + +### [`revocations`](../metadata.md#revocations) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Version Revocations](../metadata.md#version-revocations) | + +A document may include a list of any prior versions which are considered to be revoked. +Only the revocation list in the latest version of the document applies. +Revoked documents are flagged as no longer valid, and should not be displayed. +As a special case, if the revocations are set to `true` then all versions of the document +are revoked, including the latest document. + +In this case, when the latest document is revoked, the payload may be empty. +Any older document that has [`revocations`](../metadata.md#revocations) set to `true` is always to be filtered +and its payload is to be assumed to be invalid. + +This allows for an entire document and any/all published versions to be revoked. +A new version of the document that is published after this, may reinstate prior +document versions, by not listing them as revoked. +However, any document where revocations was set `true` can never be reinstated. + +#### [`revocations`](../metadata.md#revocations) Validation + +If the field is `true` the payload may be absent or invalid. +Such documents may never be submitted. + ### [`parameters`](../metadata.md#parameters) @@ -111,20 +192,22 @@ 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. +Category Parameters Document controlling the Category +within a Campaign. + +Must be valid according to the schema contained within the +[Document Reference](../metadata.md#document-reference) from the [`template`](../metadata.md#template) metadata. ## Signers -The following User roles may sign documents of this type: +The following Admin roles may sign documents of this type: -* Registered +* Brand Admin New versions of this document may be published by: * author +* collaborators ## Copyright @@ -132,8 +215,9 @@ 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-30 | +| Modified | 2025-06-20 | | Authors | Alex Pozhylenkov | +| | Nathan Bogale | | | Steven Johnson | ### Changelog @@ -142,9 +226,9 @@ New versions of this document may be published by: * First Published Version -#### 0.03 (2025-05-05) +#### 0.02 (2025-06-20) -* Use generalized parameters. +* Generalized as another kind of form data document [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_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md new file mode 100644 index 00000000000..da22ca30edb --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md @@ -0,0 +1,180 @@ +# Category Parameters Form Template + +## Description + +A Category Parameters Form Template defines both: + +* The data that is entered in the Form. +* Formatting hints for the collection of the data in a form. + +A Category Parameters Form Template is a [JSON Schema][JSON Schema-2020-12] Document. + +Category Parameters entry *SHOULD* use the hints when collecting +data defined by the Category Parameters Form Template to provide a +consistent user interface. +It *CAN* also use those hints when re-displaying the full forms data. + +Alternatively a Category Parameters Presentation Template can be used to +format the Category Parameters data for presentation. + +The Category Parameters Document is intentionally general, +however it may be linked to a brand/campaign or category +via the template used by the Category Parameters. + +The payload of a Category Parameters is controlled by its template. + + + +```graphviz dot category_parameters_form_template.dot.svg +{{ include_file('./../diagrams/category_parameters_form_template.dot', indent=4) }} +``` + + + +### Validation + +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. + +### Business Logic + +#### Front End + +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. + +#### Back End + +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. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +* [content type](../spec.md#content-type) = `application/schema+json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `818938c3-3139-4daa-afe6-974c78488e95`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a document with +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +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) | +| | [Campaign Parameters](campaign_parameters.md) | +| | [Category Parameters](category_parameters.md) | +| Linked Reference Metadata | [`template`](#template) | + +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. +* The Document referenced by [`template`](../metadata.md#template) + * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND + * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. + +## Payload + +[JSON Schema][JSON Schema-2020-12] document which defines the valid contents and +formatting hints for the collection of data for a +Category Parameters Document. + +## Signers + +The following Admin roles may sign documents of this type: + +* Brand Admin + +New versions of this document may be published by: + +* author + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-05-30 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-04-04) + +* First Published Version + +#### 0.03 (2025-05-05) + +* Use generalized parameters. + +#### 0.04 (2025-05-05) + +* Generalize the Form Template definitions. + +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/comment_moderation_action.md b/docs/src/architecture/08_concepts/signed_doc/docs/comment_moderation_action.md index cb26e7c77e3..ed9a0493f9a 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 @@ -109,7 +109,7 @@ Some documents allow multiple references, and they are documented as required. The document reference serves two purposes: 1. It ensures that the document referenced by an ID/Version is not substituted. - In other words, that the document intended to be referenced, is actually referenced. + In other words, that the document intended to be referenced, is actually referenced. 2. It Allows the document to be unambiguously located in decentralized storage systems. There can be any number of Document Locations in any reference. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md new file mode 100644 index 00000000000..478d189bc9d --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md @@ -0,0 +1,237 @@ +# Contest Parameters + +## Description + +Contest Parameters define the parameter data required for the +system at the Contest level. + +Parameter Data includes things such as: + +* Functional parameters +* Timeline data +* Branded Content and Copy + +The content of the parameters is defined solely by the +Contest Parameters Form Template. + +This allows parameters to vary based on individual system +requirements over time. + +Functional Parameters are mapped using the (TBD Functional Parameters Map). + +The payload of a Contest is controlled by its template. + + + +```graphviz dot contest_parameters.dot.svg +{{ include_file('./../diagrams/contest_parameters.dot', indent=4) }} +``` + + + +### Validation + +The Contest Parameters Document *MUST* be linked through [`parameters`](../metadata.md#parameters) to +its Brand/Campaign/Category Parameters Document. + +### Business Logic + +#### Front End + +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. + +#### Back End + +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. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `788ff4c6-d65a-451f-bb33-575fe056b411`,
`60185874-7e13-407c-a06c-238ffe637ae6` | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a document with +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +The document version must always be >= the document ID. + +### [`template`](../metadata.md#template) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Contest Parameters Form Template](contest_parameters_form_template.md) | + +Reference to the template used to create and/or validate this document. + +#### [`template`](../metadata.md#template) Validation + +In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields, +The document payload is not valid if it does not validate completely against the referenced template. + +### [`collaborators`](../metadata.md#collaborators) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Collaborators Reference List](../metadata.md#collaborators-reference-list) | + +A list of collaborators who may also publish updates to versions of this document. +This should include all parties who have not signed this document directly. + +Every subsequent version can amend the collaborators list. +However, the initial Author can never be removed from being able to +publish a new version of the document. + +#### [`collaborators`](../metadata.md#collaborators) Validation + +This list does not imply these collaborators have consented to collaborate, only that the author/s +are permitting these potential collaborators to participate in the drafting and submission process. +However, any document submission referencing a proposal MUST be signed by all collaborators in +addition to the author. + +### [`revocations`](../metadata.md#revocations) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Version Revocations](../metadata.md#version-revocations) | + +A document may include a list of any prior versions which are considered to be revoked. +Only the revocation list in the latest version of the document applies. +Revoked documents are flagged as no longer valid, and should not be displayed. +As a special case, if the revocations are set to `true` then all versions of the document +are revoked, including the latest document. + +In this case, when the latest document is revoked, the payload may be empty. +Any older document that has [`revocations`](../metadata.md#revocations) set to `true` is always to be filtered +and its payload is to be assumed to be invalid. + +This allows for an entire document and any/all published versions to be revoked. +A new version of the document that is published after this, may reinstate prior +document versions, by not listing them as revoked. +However, any document where revocations was set `true` can never be reinstated. + +#### [`revocations`](../metadata.md#revocations) Validation + +If the field is `true` the payload may be absent or invalid. +Such documents may never be submitted. + +### [`parameters`](../metadata.md#parameters) + + +| Parameter | Value | +| --- | --- | +| 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) | + +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 + +Contest Parameters Document controlling the Contest +within a Brand/Campaign/Category. + +Must be valid according to the schema contained within the +[Document Reference](../metadata.md#document-reference) from the [`template`](../metadata.md#template) metadata. + +## Signers + +The following Admin roles may sign documents of this type: + +* Brand Admin + +New versions of this document may be published by: + +* author +* collaborators + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-06-20 | +| Authors | Alex Pozhylenkov | +| | Nathan Bogale | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-04-04) + +* First Published Version + +#### 0.02 (2025-06-20) + +* Generalized as another kind of form data document + +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md new file mode 100644 index 00000000000..13183bb0e5f --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md @@ -0,0 +1,180 @@ +# Contest Parameters Form Template + +## Description + +A Contest Parameters Form Template defines both: + +* The data that is entered in the Form. +* Formatting hints for the collection of the data in a form. + +A Contest Parameters Form Template is a [JSON Schema][JSON Schema-2020-12] Document. + +Contest Parameters entry *SHOULD* use the hints when collecting +data defined by the Contest Parameters Form Template to provide a +consistent user interface. +It *CAN* also use those hints when re-displaying the full forms data. + +Alternatively a Contest Parameters Presentation Template can be used to +format the Contest Parameters data for presentation. + +The Contest Parameters Document is intentionally general, +however it may be linked to a brand/campaign or category +via the template used by the Contest Parameters. + +The payload of a Contest Parameters is controlled by its template. + + + +```graphviz dot contest_parameters_form_template.dot.svg +{{ include_file('./../diagrams/contest_parameters_form_template.dot', indent=4) }} +``` + + + +### Validation + +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. + +### Business Logic + +#### Front End + +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. + +#### Back End + +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. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +* [content type](../spec.md#content-type) = `application/schema+json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `788ff4c6-d65a-451f-bb33-575fe056b411`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a document with +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +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) | +| | [Campaign Parameters](campaign_parameters.md) | +| | [Category Parameters](category_parameters.md) | +| Linked Reference Metadata | [`template`](#template) | + +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. +* The Document referenced by [`template`](../metadata.md#template) + * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND + * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. + +## Payload + +[JSON Schema][JSON Schema-2020-12] document which defines the valid contents and +formatting hints for the collection of data for a +Contest Parameters Document. + +## Signers + +The following Admin roles may sign documents of this type: + +* Brand Admin + +New versions of this document may be published by: + +* author + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-05-30 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-04-04) + +* First Published Version + +#### 0.03 (2025-05-05) + +* Use generalized parameters. + +#### 0.04 (2025-05-05) + +* Generalize the Form Template definitions. + +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md index 4385eed9a30..70d80cddd7a 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md @@ -2,8 +2,6 @@ ## Description -## Proposal Comment Form Template Document - A Proposal Comment Form Template defines both: * The data that is entered in the Form. @@ -147,7 +145,6 @@ Proposal Comment Document. The following Admin roles may sign documents of this type: * Brand Admin -* Campaign Admin New versions of this document may be published by: diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md index 4ac3d56a9da..d4f671d3300 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md @@ -2,8 +2,6 @@ ## Description -## Proposal Comment Presentation Template Document - A Proposal Comment Presentation Template defines how the data captured by the Proposal Comment Form Template is to be displayed. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md index a48c2517294..9cf27f72eee 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md @@ -2,8 +2,6 @@ ## Description -## Proposal Form Template Document - A Proposal Form Template defines both: * The data that is entered in the Form. @@ -147,7 +145,6 @@ Proposal Document. The following Admin roles may sign documents of this type: * Brand Admin -* Campaign Admin New versions of this document may be published by: 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 8aa046c4e39..47ced57cfca 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 @@ -109,7 +109,7 @@ Some documents allow multiple references, and they are documented as required. The document reference serves two purposes: 1. It ensures that the document referenced by an ID/Version is not substituted. - In other words, that the document intended to be referenced, is actually referenced. + In other words, that the document intended to be referenced, is actually referenced. 2. It Allows the document to be unambiguously located in decentralized storage systems. There can be any number of Document Locations in any reference. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md index 98e2b7122cb..7e6456af170 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md @@ -2,8 +2,6 @@ ## Description -## Proposal Presentation Template Document - A Proposal Presentation Template defines how the data captured by the Proposal Form Template is to be displayed. 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 030f2854af6..3eabaaf5376 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 @@ -2,7 +2,7 @@ ## Description -## Proposal Submission Action +Proposal Submission Action A Proposal Submission Action is a document which can attempt to either submit a particular version of a proposal into a campaign, or withdraw it. @@ -141,7 +141,7 @@ Some documents allow multiple references, and they are documented as required. The document reference serves two purposes: 1. It ensures that the document referenced by an ID/Version is not substituted. - In other words, that the document intended to be referenced, is actually referenced. + In other words, that the document intended to be referenced, is actually referenced. 2. It Allows the document to be unambiguously located in decentralized storage systems. There can be any number of Document Locations in any reference. @@ -198,8 +198,8 @@ 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`. + `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 @@ -214,8 +214,8 @@ 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`. + `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 { diff --git a/docs/src/architecture/08_concepts/signed_doc/metadata.md b/docs/src/architecture/08_concepts/signed_doc/metadata.md index 13d21cb9477..3f0e676f077 100644 --- a/docs/src/architecture/08_concepts/signed_doc/metadata.md +++ b/docs/src/architecture/08_concepts/signed_doc/metadata.md @@ -202,8 +202,8 @@ The first version of the document must set [`ver`](metadata.md#ver) == [`id`](me [`ver`](metadata.md#ver) represents either: * when a document changes over time, such as - with a new version of a particular document that supersedes an - earlier one. + with a new version of a particular document that supersedes an + earlier one. * when a new document in a sequence of documents is produced. Because the most common use [`ver`](metadata.md#ver) is a new version of the same document @@ -231,9 +231,13 @@ The document version must always be >= the document ID. | | [Proposal Moderation Action](./docs/proposal_moderation_action.md) | | | [Comment Moderation Action](./docs/comment_moderation_action.md) | | | [Brand Parameters](./docs/brand_parameters.md) | +| | [Brand Parameters Form Template](./docs/brand_parameters_form_template.md) | | | [Campaign Parameters](./docs/campaign_parameters.md) | +| | [Campaign Parameters Form Template](./docs/campaign_parameters_form_template.md) | | | [Category Parameters](./docs/category_parameters.md) | -| | [Decision Parameters](./docs/decision_parameters.md) | +| | [Category Parameters Form Template](./docs/category_parameters_form_template.md) | +| | [Contest Parameters](./docs/contest_parameters.md) | +| | [Contest Parameters Form Template](./docs/contest_parameters_form_template.md) | Reference to a Linked Document or Documents. This is the primary hierarchical reference to a related document. @@ -276,6 +280,10 @@ The following must be true for a valid reference: | Format | [Document Reference](metadata.md#document-reference) | | Valid References | [Proposal Form Template](./docs/proposal_form_template.md) | | | [Proposal Comment Form Template](./docs/proposal_comment_form_template.md) | +| | [Brand Parameters Form Template](./docs/brand_parameters_form_template.md) | +| | [Campaign Parameters Form Template](./docs/campaign_parameters_form_template.md) | +| | [Category Parameters Form Template](./docs/category_parameters_form_template.md) | +| | [Contest Parameters Form Template](./docs/contest_parameters_form_template.md) | Reference to the template used to create and/or validate this document. @@ -355,7 +363,7 @@ addition to the author. | Valid References | [Brand Parameters](./docs/brand_parameters.md) | | | [Campaign Parameters](./docs/campaign_parameters.md) | | | [Category Parameters](./docs/category_parameters.md) | -| | [Decision Parameters](./docs/decision_parameters.md) | +| | [Contest Parameters](./docs/contest_parameters.md) | A reference to the Parameters Document this document lies under. @@ -406,7 +414,7 @@ Not just the current document. ``` mermaid - classDiagram +classDiagram direction LR class Last { type: "=Intermediate.Document Type" @@ -459,7 +467,7 @@ as they are signed by the author of the chain. ``` mermaid - classDiagram +classDiagram direction LR class Last { @@ -540,7 +548,7 @@ as its not signed by the author of the chained documents. ``` mermaid - classDiagram +classDiagram direction LR class Last { type: "=Intermediate.Document Type" diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index b7a432dba49..aa6efe33233 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -11,9 +11,10 @@ All Document Types are defined by composing these base document types: | Campaign | `5ef32d5d-f240-462c-a7a4-ba4af221fa23` | `37(h'5ef32d5df240462ca7a4ba4af221fa23')` | | Category | `818938c3-3139-4daa-afe6-974c78488e95` | `37(h'818938c331394daaafe6974c78488e95')` | | Comment | `b679ded3-0e7c-41ba-89f8-da62a17898ea` | `37(h'b679ded30e7c41ba89f8da62a17898ea')` | -| Decision | `788ff4c6-d65a-451f-bb33-575fe056b411` | `37(h'788ff4c6d65a451fbb33575fe056b411')` | +| Contest | `788ff4c6-d65a-451f-bb33-575fe056b411` | `37(h'788ff4c6d65a451fbb33575fe056b411')` | | FormTemplate | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | `37(h'0ce8ab3892584fbca62e7faa6e58318f')` | | ModerationAction | `a5d232b8-5e03-4117-9afd-be32b878fcdd` | `37(h'a5d232b85e0341179afdbe32b878fcdd')` | +| Parameters | `60185874-7e13-407c-a06c-238ffe637ae6` | `37(h'601858747e13407ca06c238ffe637ae6')` | | PresentationTemplate | `cb99b9bd-681a-49d8-9836-89107c02e8ef` | `37(h'cb99b9bd681a49d8983689107c02e8ef')` | | Proposal | `7808d2ba-d511-40af-84e8-c0d1625fdfdc` | `37(h'7808d2bad51140af84e8c0d1625fdfdc')` | | SubmissionAction | `78927329-cfd9-4ea1-9c71-0e019b126a65` | `37(h'78927329cfd94ea19c710e019b126a65')` | @@ -25,11 +26,15 @@ All Defined Document Types | Document Type | Base Types | [CBOR][RFC8949] | | :--- | :--- | :--- | -| [Brand Parameters](./docs/brand_parameters.md) | Brand | [37(h'ebcabeeb5bc54f9591e8cab8ca724172')] | -| [Campaign Parameters](./docs/campaign_parameters.md) | Campaign | [37(h'5ef32d5df240462ca7a4ba4af221fa23')] | -| [Category Parameters](./docs/category_parameters.md) | Category | [37(h'818938c331394daaafe6974c78488e95')] | +| [Brand Parameters](./docs/brand_parameters.md) | Brand/Parameters | [37(h'ebcabeeb5bc54f9591e8cab8ca724172'),
37(h'601858747e13407ca06c238ffe637ae6')] | +| [Brand Parameters Form Template](./docs/brand_parameters_form_template.md) | Brand/Parameters/FormTemplate | [37(h'ebcabeeb5bc54f9591e8cab8ca724172'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'0ce8ab3892584fbca62e7faa6e58318f')] | +| [Campaign Parameters](./docs/campaign_parameters.md) | Campaign/Parameters | [37(h'5ef32d5df240462ca7a4ba4af221fa23'),
37(h'601858747e13407ca06c238ffe637ae6')] | +| [Campaign Parameters Form Template](./docs/campaign_parameters_form_template.md) | Campaign/Parameters/FormTemplate | [37(h'5ef32d5df240462ca7a4ba4af221fa23'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'0ce8ab3892584fbca62e7faa6e58318f')] | +| [Category Parameters](./docs/category_parameters.md) | Category/Parameters | [37(h'818938c331394daaafe6974c78488e95'),
37(h'601858747e13407ca06c238ffe637ae6')] | +| [Category Parameters Form Template](./docs/category_parameters_form_template.md) | Category/Parameters/FormTemplate | [37(h'818938c331394daaafe6974c78488e95'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'0ce8ab3892584fbca62e7faa6e58318f')] | | [Comment Moderation Action](./docs/comment_moderation_action.md) | Action/Comment/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | -| [Decision Parameters](./docs/decision_parameters.md) | Decision | [37(h'788ff4c6d65a451fbb33575fe056b411')] | +| [Contest Parameters](./docs/contest_parameters.md) | Contest/Parameters | [37(h'788ff4c6d65a451fbb33575fe056b411'),
37(h'601858747e13407ca06c238ffe637ae6')] | +| [Contest Parameters Form Template](./docs/contest_parameters_form_template.md) | Contest/Parameters/FormTemplate | [37(h'788ff4c6d65a451fbb33575fe056b411'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'0ce8ab3892584fbca62e7faa6e58318f')] | | [Proposal](./docs/proposal.md) | Proposal | [37(h'7808d2bad51140af84e8c0d1625fdfdc')] | | [Proposal Comment](./docs/proposal_comment.md) | Comment/Proposal | [37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | | [Proposal Comment Form Template](./docs/proposal_comment_form_template.md) | FormTemplate/Comment/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | diff --git a/specs/definitions/signed_docs/docs/all.cue b/specs/definitions/signed_docs/docs/all.cue index 7c03a764cc8..9c0d5e402ec 100644 --- a/specs/definitions/signed_docs/docs/all.cue +++ b/specs/definitions/signed_docs/docs/all.cue @@ -17,7 +17,8 @@ _allDocTypes: { Brand: "ebcabeeb-5bc5-4f95-91e8-cab8ca724172" Campaign: "5ef32d5d-f240-462c-a7a4-ba4af221fa23" Category: "818938c3-3139-4daa-afe6-974c78488e95" - Decision: "788ff4c6-d65a-451f-bb33-575fe056b411" + Contest: "788ff4c6-d65a-451f-bb33-575fe056b411" + Parameters: "60185874-7e13-407c-a06c-238ffe637ae6" } // Source of truth for ALL Document Types and their matching UUID's. @@ -67,17 +68,40 @@ _allDocs: { ] "Brand Parameters": [ _allDocTypes["Brand"], + _allDocTypes["Parameters"], + ] + "Brand Parameters Form Template": [ + _allDocTypes["Brand"], + _allDocTypes["Parameters"], + _allDocTypes["FormTemplate"], ] "Campaign Parameters": [ _allDocTypes["Campaign"], + _allDocTypes["Parameters"], + ] + "Campaign Parameters Form Template": [ + _allDocTypes["Campaign"], + _allDocTypes["Parameters"], + _allDocTypes["FormTemplate"], ] "Category Parameters": [ _allDocTypes["Category"], + _allDocTypes["Parameters"], ] - "Decision Parameters": [ - _allDocTypes["Decision"], + "Category Parameters Form Template": [ + _allDocTypes["Category"], + _allDocTypes["Parameters"], + _allDocTypes["FormTemplate"], + ] + "Contest Parameters": [ + _allDocTypes["Contest"], + _allDocTypes["Parameters"], + ] + "Contest Parameters Form Template": [ + _allDocTypes["Contest"], + _allDocTypes["Parameters"], + _allDocTypes["FormTemplate"], ] - } // Document Cluster Definition @@ -88,7 +112,7 @@ _allDocs: { #DocClusters: [string]: #DocumentCluster doc_clusters: #DocClusters & { - // System parameters define the system, excludes Decisions. + // System parameters define the system, excludes Contests. "System Parameters": { docs: [ "Brand Parameters", diff --git a/specs/definitions/signed_docs/docs/brand_parameters.cue b/specs/definitions/signed_docs/docs/brand_parameters.cue deleted file mode 100644 index d8499e7735e..00000000000 --- a/specs/definitions/signed_docs/docs/brand_parameters.cue +++ /dev/null @@ -1,23 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Brand Parameters": { - - description: """ - Parameters which define this brand within the system. - """ - - headers: "content type": value: "application/json" - - versions: [ - { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - ]} -} diff --git a/specs/definitions/signed_docs/docs/campaign_parameters.cue b/specs/definitions/signed_docs/docs/campaign_parameters.cue deleted file mode 100644 index 8fb1fd93e0a..00000000000 --- a/specs/definitions/signed_docs/docs/campaign_parameters.cue +++ /dev/null @@ -1,33 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Campaign Parameters": { - description: """ - Parameters which define a Campaign within a Brand in the system. - """ - headers: "content type": value: "application/json" - - metadata: parameters: { - required: "yes" - type: "Brand Parameters" - } - - versions: [ - { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - { - version: "0.03" - modified: "2025-05-05" - changes: """ - * Use generalized parameters. - """ - }, - ]} -} diff --git a/specs/definitions/signed_docs/docs/category_parameters.cue b/specs/definitions/signed_docs/docs/category_parameters.cue deleted file mode 100644 index eaee58ca392..00000000000 --- a/specs/definitions/signed_docs/docs/category_parameters.cue +++ /dev/null @@ -1,35 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Category Parameters": { - - description: """ - Parameters which define a Category withing a Campaign under a Brand in the system. - """ - - headers: "content type": value: "application/json" - - metadata: parameters: { - required: "yes" - type: "Campaign Parameters" - } - - versions: [ - { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - { - version: "0.03" - modified: "2025-05-05" - changes: """ - * Use generalized parameters. - """ - }, - ]} -} diff --git a/specs/definitions/signed_docs/docs/decision_parameters.cue b/specs/definitions/signed_docs/docs/decision_parameters.cue deleted file mode 100644 index 16bc7e5c25a..00000000000 --- a/specs/definitions/signed_docs/docs/decision_parameters.cue +++ /dev/null @@ -1,33 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Decision Parameters": { - description: """ - Parameters which define an individual voting event. - """ - headers: "content type": value: "application/json" - - metadata: parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - } - - versions: [ - { - version: "0.01" - modified: "2025-04-04" - changes: """ - * First Published Version - """ - }, - { - version: "0.03" - modified: "2025-05-05" - changes: """ - * Use generalized parameters. - """ - }, - ]} -} diff --git a/specs/definitions/signed_docs/docs/generic_form_template.cue b/specs/definitions/signed_docs/docs/generic_form_template.cue index f357918bc2b..91bc12654e8 100644 --- a/specs/definitions/signed_docs/docs/generic_form_template.cue +++ b/specs/definitions/signed_docs/docs/generic_form_template.cue @@ -1,10 +1,7 @@ -package signed_docs - // Template Standardized Descriptions +package signed_docs _form_template_description: """ - ## {{ .doc }} Form Template Document - A {{ .doc }} Form Template defines both: * The data that is entered in the Form. @@ -57,9 +54,8 @@ _form_template_payload_description: """ user: [] // Brand Admin and Lower may publish this document. - admin: [ + admin: _ | *[ "Brand Admin", - "Campaign Admin", ] } diff --git a/specs/definitions/signed_docs/docs/generic_parameters.cue b/specs/definitions/signed_docs/docs/generic_parameters.cue new file mode 100644 index 00000000000..361241f7a96 --- /dev/null +++ b/specs/definitions/signed_docs/docs/generic_parameters.cue @@ -0,0 +1,88 @@ +// Parameters Standardized Document Definition +package signed_docs + +_parameters_description: """ + {{ .doc }} Parameters define the parameter data required for the + system at the {{ .doc }} level. + + Parameter Data includes things such as: + + * Functional parameters + * Timeline data + * Branded Content and Copy + + The content of the parameters is defined solely by the + {{ .doc }} Parameters Form Template. + + This allows parameters to vary based on individual system + requirements over time. + + Functional Parameters are mapped using the (TBD Functional Parameters Map). + + The payload of a {{ .doc }} is controlled by its template. + """ + +_parameters_parent_validation: """ + The {{ .doc }} Parameters Document *MUST* be linked through `parameters` to + its {{ .doc_parent }} Parameters Document. + """ + +_parameters_payload_description: """ + {{ .doc }} Parameters Document controlling the {{ .doc }} + within a {{ .doc_parent }}. + + Must be valid according to the schema contained within the + `Document Reference` from the `template` metadata. + """ + +#generic_parameters: #signedDocument & { + + description: _ + + metadata: { + template: required: "yes" + + collaborators: required: "optional" + + revocations: required: "optional" + + parameters: required: _ | *"yes" + } + + headers: "content type": value: "application/json" + + payload: description: _ + + signers: { + roles: { + user: [] + admin: [ + "Brand Admin", + ] + } + update: collaborators: true + } + + authors: { + "Steven Johnson": "steven.johnson@iohk.io" + "Nathan Bogale": "nathan.bogale@iohk.io" + } + +} + +_generic_parameters_versions: [ + { + version: "0.01" + modified: "2025-04-04" + changes: """ + * First Published Version + """ + }, + { + version: "0.02" + modified: "2025-06-20" + changes: """ + * Generalized as another kind of form data document + """ + }, +] diff --git a/specs/definitions/signed_docs/docs/generic_presentation_template.cue b/specs/definitions/signed_docs/docs/generic_presentation_template.cue index 3556eb900b5..20c2846d14d 100644 --- a/specs/definitions/signed_docs/docs/generic_presentation_template.cue +++ b/specs/definitions/signed_docs/docs/generic_presentation_template.cue @@ -3,8 +3,6 @@ package signed_docs // Template Standardized Descriptions _presentation_template_description: """ - ## {{ .doc }} Presentation Template Document - A {{ .doc }} Presentation Template defines how the data captured by the {{ .doc }} Form Template is to be displayed. diff --git a/specs/definitions/signed_docs/docs/parameters_brand.cue b/specs/definitions/signed_docs/docs/parameters_brand.cue new file mode 100644 index 00000000000..9912db59e8e --- /dev/null +++ b/specs/definitions/signed_docs/docs/parameters_brand.cue @@ -0,0 +1,21 @@ +// Brand Parameters Document Definition +package signed_docs + +import "text/template" + +docs: "Brand Parameters": #generic_parameters & { + + _data: { + doc: "Brand" + doc_parent: "Brand" + } + + description: template.Execute(_parameters_description, _data) + validation: "No extra validation defined." + metadata: { + template: type: "\(_data.doc) Parameters Form Template" + parameters: required: "excluded" + } + payload: description: template.Execute(_parameters_payload_description, _data) + versions: _generic_parameters_versions +} diff --git a/specs/definitions/signed_docs/docs/parameters_brand_form_template.cue b/specs/definitions/signed_docs/docs/parameters_brand_form_template.cue new file mode 100644 index 00000000000..d0ebca07e35 --- /dev/null +++ b/specs/definitions/signed_docs/docs/parameters_brand_form_template.cue @@ -0,0 +1,11 @@ +// Proposal Form Template Document Definition +package signed_docs + +import "text/template" + +docs: "Brand Parameters Form Template": #generic_form_template & { + _data: doc: "Brand Parameters" + description: template.Execute(_form_template_description, _data) + payload: description: template.Execute(_form_template_payload_description, _data) + versions: _generic_form_template_versions +} diff --git a/specs/definitions/signed_docs/docs/parameters_campaign.cue b/specs/definitions/signed_docs/docs/parameters_campaign.cue new file mode 100644 index 00000000000..f6746e18d6a --- /dev/null +++ b/specs/definitions/signed_docs/docs/parameters_campaign.cue @@ -0,0 +1,24 @@ +// Brand Parameters Document Definition +package signed_docs + +import "text/template" + +docs: "Campaign Parameters": #generic_parameters & { + + _data: { + doc: "Campaign" + doc_parent: "Brand" + } + + description: template.Execute(_parameters_description, _data) + validation: template.Execute(_parameters_parent_validation, _data) + metadata: { + template: type: "\(_data.doc) Parameters Form Template" + parameters: { + required: "yes" + type: "\(_data.doc_parent) Parameters" + } + } + payload: description: template.Execute(_parameters_payload_description, _data) + versions: _generic_parameters_versions +} diff --git a/specs/definitions/signed_docs/docs/parameters_campaign_form_template.cue b/specs/definitions/signed_docs/docs/parameters_campaign_form_template.cue new file mode 100644 index 00000000000..0fd85abd1e2 --- /dev/null +++ b/specs/definitions/signed_docs/docs/parameters_campaign_form_template.cue @@ -0,0 +1,12 @@ +// Campaign Form Template Document Definition +package signed_docs + +import "text/template" + +docs: "Campaign Parameters Form Template": #generic_form_template & { + _data: doc: "Campaign Parameters" + + description: template.Execute(_form_template_description, _data) + payload: description: template.Execute(_form_template_payload_description, _data) + versions: _generic_form_template_versions +} diff --git a/specs/definitions/signed_docs/docs/parameters_category.cue b/specs/definitions/signed_docs/docs/parameters_category.cue new file mode 100644 index 00000000000..97a94003e13 --- /dev/null +++ b/specs/definitions/signed_docs/docs/parameters_category.cue @@ -0,0 +1,24 @@ +// Category Parameters Document Definition +package signed_docs + +import "text/template" + +docs: "Category Parameters": #generic_parameters & { + + _data: { + doc: "Category" + doc_parent: "Campaign" + } + + description: template.Execute(_parameters_description, _data) + validation: template.Execute(_parameters_parent_validation, _data) + metadata: { + template: type: "\(_data.doc) Parameters Form Template" + parameters: { + required: "yes" + type: "\(_data.doc_parent) Parameters" + } + } + payload: description: template.Execute(_parameters_payload_description, _data) + versions: _generic_parameters_versions +} diff --git a/specs/definitions/signed_docs/docs/parameters_category_form_template.cue b/specs/definitions/signed_docs/docs/parameters_category_form_template.cue new file mode 100644 index 00000000000..01191d5209a --- /dev/null +++ b/specs/definitions/signed_docs/docs/parameters_category_form_template.cue @@ -0,0 +1,12 @@ +// Category Form Template Document Definition +package signed_docs + +import "text/template" + +docs: "Category Parameters Form Template": #generic_form_template & { + _data: doc: "Category Parameters" + + description: template.Execute(_form_template_description, _data) + payload: description: template.Execute(_form_template_payload_description, _data) + versions: _generic_form_template_versions +} diff --git a/specs/definitions/signed_docs/docs/parameters_contest.cue b/specs/definitions/signed_docs/docs/parameters_contest.cue new file mode 100644 index 00000000000..a57facf650d --- /dev/null +++ b/specs/definitions/signed_docs/docs/parameters_contest.cue @@ -0,0 +1,24 @@ +// Contest Parameters Document Definition +package signed_docs + +import "text/template" + +docs: "Contest Parameters": #generic_parameters & { + + _data: { + doc: "Contest" + doc_parent: "Brand/Campaign/Category" + } + + description: template.Execute(_parameters_description, _data) + validation: template.Execute(_parameters_parent_validation, _data) + metadata: { + template: type: "\(_data.doc) Parameters Form Template" + parameters: { + required: "yes" + type: doc_clusters."System Parameters".docs + } + } + payload: description: template.Execute(_parameters_payload_description, _data) + versions: _generic_parameters_versions +} diff --git a/specs/definitions/signed_docs/docs/parameters_contest_form_template.cue b/specs/definitions/signed_docs/docs/parameters_contest_form_template.cue new file mode 100644 index 00000000000..9b3e0bef0f8 --- /dev/null +++ b/specs/definitions/signed_docs/docs/parameters_contest_form_template.cue @@ -0,0 +1,12 @@ +// Contest Form Template Document Definition +package signed_docs + +import "text/template" + +docs: "Contest Parameters Form Template": #generic_form_template & { + _data: doc: "Contest Parameters" + + description: template.Execute(_form_template_description, _data) + payload: description: template.Execute(_form_template_payload_description, _data) + versions: _generic_form_template_versions +} diff --git a/specs/definitions/signed_docs/docs/proposal_submission_action.cue b/specs/definitions/signed_docs/docs/proposal_submission_action.cue index 8115e5ecb0b..00c66f94a1b 100644 --- a/specs/definitions/signed_docs/docs/proposal_submission_action.cue +++ b/specs/definitions/signed_docs/docs/proposal_submission_action.cue @@ -6,7 +6,7 @@ package signed_docs docs: #DocumentDefinitions & { "Proposal Submission Action": { description: """ - ## Proposal Submission Action + Proposal Submission Action A Proposal Submission Action is a document which can attempt to either submit a particular version of a proposal into a campaign, or withdraw it. diff --git a/specs/definitions/signed_docs/metadata_chain.cue b/specs/definitions/signed_docs/metadata_chain.cue index 4c2000e9002..313f8313df0 100644 --- a/specs/definitions/signed_docs/metadata_chain.cue +++ b/specs/definitions/signed_docs/metadata_chain.cue @@ -33,7 +33,7 @@ _chain_validation_examples: """ ``` mermaid - \(_chainValidMermaid) + \(_chainValidMermaid) ``` @@ -45,7 +45,7 @@ _chain_validation_examples: """ ``` mermaid - \(_chainInvalidMermaid) + \(_chainInvalidMermaid) ``` @@ -56,7 +56,7 @@ _chain_validation_examples: """ ``` mermaid - \(_chainFraudulentMermaid) + \(_chainFraudulentMermaid) ``` """ diff --git a/specs/generators/src/docs/doc_generator.py b/specs/generators/src/docs/doc_generator.py index aa48adf3301..8fc062d1c76 100644 --- a/specs/generators/src/docs/doc_generator.py +++ b/specs/generators/src/docs/doc_generator.py @@ -187,7 +187,7 @@ def remove_tabs(self, tabstop: int = 4) -> None: Args: text (str): The input text containing tabs. - tabstop (int): The number of characters per tab stop. Default is 8. + tabstop (int): The number of characters per tab stop. Default is 4. Returns: str: Text with tabs replaced by spaces, aligned at each tab stop. @@ -202,9 +202,15 @@ def replace_tab(match: re.Match[str]) -> str: return " " * (tabstop - (position % tabstop)) # Substitute tabs with spaces, using a custom replacement function - no_tabs_text = re.sub(pattern, replace_tab, self._filedata) + lines = list[str]( + self._filedata.splitlines() # type: ignore # noqa: PGH003 + ) + no_tabs: list[str] = [] + for line in lines: + new_line = re.sub(pattern, replace_tab, line) + no_tabs.append(new_line) - self._filedata = no_tabs_text + self._filedata = "\n".join(no_tabs) def insert_copyright(self, *, changelog: bool = True) -> str: """Generate a copyright notice into the given document data. diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 8816e1d9b85..2d77a3e5987 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -9,9 +9,10 @@ "Campaign": "5ef32d5d-f240-462c-a7a4-ba4af221fa23", "Category": "818938c3-3139-4daa-afe6-974c78488e95", "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea", - "Decision": "788ff4c6-d65a-451f-bb33-575fe056b411", + "Contest": "788ff4c6-d65a-451f-bb33-575fe056b411", "FormTemplate": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "ModerationAction": "a5d232b8-5e03-4117-9afd-be32b878fcdd", + "Parameters": "60185874-7e13-407c-a06c-238ffe637ae6", "PresentationTemplate": "cb99b9bd-681a-49d8-9836-89107c02e8ef", "Proposal": "7808d2ba-d511-40af-84e8-c0d1625fdfdc", "SubmissionAction": "78927329-cfd9-4ea1-9c71-0e019b126a65" @@ -378,15 +379,412 @@ }, "docs": { "Brand Parameters": { + "authors": { + "Nathan Bogale": "nathan.bogale@iohk.io", + "Steven Johnson": "steven.johnson@iohk.io" + }, + "description": "Brand Parameters define the parameter data required for the\nsystem at the Brand level.\n\nParameter Data includes things such as:\n\n* Functional parameters\n* Timeline data\n* Branded Content and Copy\n\nThe content of the parameters is defined solely by the \nBrand Parameters Form Template.\n\nThis allows parameters to vary based on individual system\nrequirements over time.\n\nFunctional Parameters are mapped using the (TBD Functional Parameters Map).\n\nThe payload of a Brand is controlled by its template.", + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": "application/json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "optional", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "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": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "required": "excluded", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "optional", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "excluded", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Brand Parameters Form Template", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "notes": [], + "payload": { + "description": "Brand Parameters Document controlling the Brand \nwithin a Brand.\n\nMust be valid according to the schema contained within the \n`Document Reference` from the `template` metadata." + }, + "signers": { + "roles": { + "admin": [ + "Brand Admin" + ], + "user": [] + }, + "update": { + "author": true, + "collaborators": true + } + }, + "type": [ + "ebcabeeb-5bc5-4f95-91e8-cab8ca724172", + "60185874-7e13-407c-a06c-238ffe637ae6" + ], + "validation": "No extra validation defined.", + "versions": [ + { + "changes": "* First Published Version", + "modified": "2025-04-04", + "version": "0.01" + }, + { + "changes": "* Generalized as another kind of form data document", + "modified": "2025-06-20", + "version": "0.02" + } + ] + }, + "Brand Parameters Form Template": { + "authors": {}, + "description": "A Brand Parameters Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Brand Parameters Form Template is a JSON Schema Document.\n\nBrand Parameters entry *SHOULD* use the hints when collecting \ndata defined by the Brand Parameters Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Brand Parameters Presentation Template can be used to\nformat the Brand Parameters data for presentation.\n\nThe Brand Parameters Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Brand Parameters.\n\nThe payload of a Brand Parameters is controlled by its template.", + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": "application/schema+json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "excluded", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "linked_refs": [ + "template" + ], + "multiple": false, + "required": "yes", + "type": [ + "Brand Parameters", + "Campaign Parameters", + "Category 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": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "required": "excluded", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "excluded", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "excluded", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "notes": [], + "payload": { + "description": "JSON Schema document which defines the valid contents and \nformatting hints for the collection of data for a \nBrand Parameters Document." + }, + "signers": { + "roles": { + "admin": [ + "Brand Admin" + ], + "user": [] + }, + "update": { + "author": true + } + }, + "type": [ + "ebcabeeb-5bc5-4f95-91e8-cab8ca724172", + "60185874-7e13-407c-a06c-238ffe637ae6", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + ], + "versions": [ + { + "changes": "* First Published Version", + "modified": "2025-04-04", + "version": "0.01" + }, + { + "changes": "* Use generalized parameters.", + "modified": "2025-05-05", + "version": "0.03" + }, + { + "changes": "* Generalize the Form Template definitions.", + "modified": "2025-05-05", + "version": "0.04" + } + ] + }, + "Campaign Parameters": { + "authors": { + "Nathan Bogale": "nathan.bogale@iohk.io", + "Steven Johnson": "steven.johnson@iohk.io" + }, + "description": "Campaign Parameters define the parameter data required for the\nsystem at the Campaign level.\n\nParameter Data includes things such as:\n\n* Functional parameters\n* Timeline data\n* Branded Content and Copy\n\nThe content of the parameters is defined solely by the \nCampaign Parameters Form Template.\n\nThis allows parameters to vary based on individual system\nrequirements over time.\n\nFunctional Parameters are mapped using the (TBD Functional Parameters Map).\n\nThe payload of a Campaign is controlled by its template.", + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": "application/json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "optional", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Brand Parameters", + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "required": "excluded", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "optional", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "excluded", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Campaign Parameters Form Template", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "notes": [], + "payload": { + "description": "Campaign Parameters Document controlling the Campaign \nwithin a Brand.\n\nMust be valid according to the schema contained within the \n`Document Reference` from the `template` metadata." + }, + "signers": { + "roles": { + "admin": [ + "Brand Admin" + ], + "user": [] + }, + "update": { + "author": true, + "collaborators": true + } + }, + "type": [ + "5ef32d5d-f240-462c-a7a4-ba4af221fa23", + "60185874-7e13-407c-a06c-238ffe637ae6" + ], + "validation": "The Campaign Parameters Document *MUST* be linked through `parameters` to \nits Brand Parameters Document.", + "versions": [ + { + "changes": "* First Published Version", + "modified": "2025-04-04", + "version": "0.01" + }, + { + "changes": "* Generalized as another kind of form data document", + "modified": "2025-06-20", + "version": "0.02" + } + ] + }, + "Campaign Parameters Form Template": { "authors": {}, - "description": "Parameters which define this brand within the system.", + "description": "A Campaign Parameters Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Campaign Parameters Form Template is a JSON Schema Document.\n\nCampaign Parameters entry *SHOULD* use the hints when collecting \ndata defined by the Campaign Parameters Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Campaign Parameters Presentation Template can be used to\nformat the Campaign Parameters data for presentation.\n\nThe Campaign Parameters Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Campaign Parameters.\n\nThe payload of a Campaign Parameters is controlled by its template.", "headers": { "content type": { "coseLabel": 3, "description": "Media Type/s allowed in the Payload", "format": "Media Type", "required": "yes", - "value": "application/json" + "value": "application/schema+json" }, "content-encoding": { "coseLabel": "content-encoding", @@ -420,7 +818,16 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "required": "excluded", + "linked_refs": [ + "template" + ], + "multiple": false, + "required": "yes", + "type": [ + "Brand Parameters", + "Campaign Parameters", + "Category 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": { @@ -467,30 +874,49 @@ } }, "notes": [], + "payload": { + "description": "JSON Schema document which defines the valid contents and \nformatting hints for the collection of data for a \nCampaign Parameters Document." + }, "signers": { "roles": { - "user": [ - "Registered" - ] + "admin": [ + "Brand Admin" + ], + "user": [] }, "update": { "author": true } }, "type": [ - "ebcabeeb-5bc5-4f95-91e8-cab8ca724172" + "5ef32d5d-f240-462c-a7a4-ba4af221fa23", + "60185874-7e13-407c-a06c-238ffe637ae6", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" ], "versions": [ { "changes": "* First Published Version", "modified": "2025-04-04", "version": "0.01" + }, + { + "changes": "* Use generalized parameters.", + "modified": "2025-05-05", + "version": "0.03" + }, + { + "changes": "* Generalize the Form Template definitions.", + "modified": "2025-05-05", + "version": "0.04" } ] }, - "Campaign Parameters": { - "authors": {}, - "description": "Parameters which define a Campaign within a Brand in the system.", + "Category Parameters": { + "authors": { + "Nathan Bogale": "nathan.bogale@iohk.io", + "Steven Johnson": "steven.johnson@iohk.io" + }, + "description": "Category Parameters define the parameter data required for the\nsystem at the Category level.\n\nParameter Data includes things such as:\n\n* Functional parameters\n* Timeline data\n* Branded Content and Copy\n\nThe content of the parameters is defined solely by the \nCategory Parameters Form Template.\n\nThis allows parameters to vary based on individual system\nrequirements over time.\n\nFunctional Parameters are mapped using the (TBD Functional Parameters Map).\n\nThe payload of a Category is controlled by its template.", "headers": { "content type": { "coseLabel": 3, @@ -519,7 +945,7 @@ "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", - "required": "excluded", + "required": "optional", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { @@ -534,7 +960,7 @@ "linked_refs": null, "multiple": false, "required": "yes", - "type": "Brand Parameters", + "type": "Campaign Parameters", "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document." }, "ref": { @@ -552,7 +978,7 @@ "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", "format": "Version Revocations", - "required": "excluded", + "required": "optional", "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." }, "section": { @@ -564,7 +990,10 @@ "template": { "description": "Reference to the template used to create and/or validate this document.", "format": "Document Reference", - "required": "excluded", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Category Parameters Form Template", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, "type": { @@ -581,19 +1010,26 @@ } }, "notes": [], + "payload": { + "description": "Category Parameters Document controlling the Category \nwithin a Campaign.\n\nMust be valid according to the schema contained within the \n`Document Reference` from the `template` metadata." + }, "signers": { "roles": { - "user": [ - "Registered" - ] + "admin": [ + "Brand Admin" + ], + "user": [] }, "update": { - "author": true + "author": true, + "collaborators": true } }, "type": [ - "5ef32d5d-f240-462c-a7a4-ba4af221fa23" + "818938c3-3139-4daa-afe6-974c78488e95", + "60185874-7e13-407c-a06c-238ffe637ae6" ], + "validation": "The Category Parameters Document *MUST* be linked through `parameters` to \nits Campaign Parameters Document.", "versions": [ { "changes": "* First Published Version", @@ -601,22 +1037,22 @@ "version": "0.01" }, { - "changes": "* Use generalized parameters.", - "modified": "2025-05-05", - "version": "0.03" + "changes": "* Generalized as another kind of form data document", + "modified": "2025-06-20", + "version": "0.02" } ] }, - "Category Parameters": { + "Category Parameters Form Template": { "authors": {}, - "description": "Parameters which define a Category withing a Campaign under a Brand in the system.", + "description": "A Category Parameters Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Category Parameters Form Template is a JSON Schema Document.\n\nCategory Parameters entry *SHOULD* use the hints when collecting \ndata defined by the Category Parameters Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Category Parameters Presentation Template can be used to\nformat the Category Parameters data for presentation.\n\nThe Category Parameters Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Category Parameters.\n\nThe payload of a Category Parameters is controlled by its template.", "headers": { "content type": { "coseLabel": 3, "description": "Media Type/s allowed in the Payload", "format": "Media Type", "required": "yes", - "value": "application/json" + "value": "application/schema+json" }, "content-encoding": { "coseLabel": "content-encoding", @@ -650,10 +1086,16 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": null, + "linked_refs": [ + "template" + ], "multiple": false, "required": "yes", - "type": "Campaign Parameters", + "type": [ + "Brand Parameters", + "Campaign Parameters", + "Category 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": { @@ -700,18 +1142,24 @@ } }, "notes": [], + "payload": { + "description": "JSON Schema document which defines the valid contents and \nformatting hints for the collection of data for a \nCategory Parameters Document." + }, "signers": { "roles": { - "user": [ - "Registered" - ] + "admin": [ + "Brand Admin" + ], + "user": [] }, "update": { "author": true } }, "type": [ - "818938c3-3139-4daa-afe6-974c78488e95" + "818938c3-3139-4daa-afe6-974c78488e95", + "60185874-7e13-407c-a06c-238ffe637ae6", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" ], "versions": [ { @@ -723,6 +1171,11 @@ "changes": "* Use generalized parameters.", "modified": "2025-05-05", "version": "0.03" + }, + { + "changes": "* Generalize the Form Template definitions.", + "modified": "2025-05-05", + "version": "0.04" } ] }, @@ -844,9 +1297,12 @@ } ] }, - "Decision Parameters": { - "authors": {}, - "description": "Parameters which define an individual voting event.", + "Contest Parameters": { + "authors": { + "Nathan Bogale": "nathan.bogale@iohk.io", + "Steven Johnson": "steven.johnson@iohk.io" + }, + "description": "Contest Parameters define the parameter data required for the\nsystem at the Contest level.\n\nParameter Data includes things such as:\n\n* Functional parameters\n* Timeline data\n* Branded Content and Copy\n\nThe content of the parameters is defined solely by the \nContest Parameters Form Template.\n\nThis allows parameters to vary based on individual system\nrequirements over time.\n\nFunctional Parameters are mapped using the (TBD Functional Parameters Map).\n\nThe payload of a Contest is controlled by its template.", "headers": { "content type": { "coseLabel": 3, @@ -875,7 +1331,7 @@ "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", "format": "Collaborators Reference List", - "required": "excluded", + "required": "optional", "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." }, "id": { @@ -909,6 +1365,141 @@ "required": "excluded", "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "optional", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "excluded", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Contest Parameters Form Template", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "notes": [], + "payload": { + "description": "Contest Parameters Document controlling the Contest \nwithin a Brand/Campaign/Category.\n\nMust be valid according to the schema contained within the \n`Document Reference` from the `template` metadata." + }, + "signers": { + "roles": { + "admin": [ + "Brand Admin" + ], + "user": [] + }, + "update": { + "author": true, + "collaborators": true + } + }, + "type": [ + "788ff4c6-d65a-451f-bb33-575fe056b411", + "60185874-7e13-407c-a06c-238ffe637ae6" + ], + "validation": "The Contest Parameters Document *MUST* be linked through `parameters` to \nits Brand/Campaign/Category Parameters Document.", + "versions": [ + { + "changes": "* First Published Version", + "modified": "2025-04-04", + "version": "0.01" + }, + { + "changes": "* Generalized as another kind of form data document", + "modified": "2025-06-20", + "version": "0.02" + } + ] + }, + "Contest Parameters Form Template": { + "authors": {}, + "description": "A Contest Parameters Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Contest Parameters Form Template is a JSON Schema Document.\n\nContest Parameters entry *SHOULD* use the hints when collecting \ndata defined by the Contest Parameters Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Contest Parameters Presentation Template can be used to\nformat the Contest Parameters data for presentation.\n\nThe Contest Parameters Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Contest Parameters.\n\nThe payload of a Contest Parameters is controlled by its template.", + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": "application/schema+json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "excluded", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "linked_refs": [ + "template" + ], + "multiple": false, + "required": "yes", + "type": [ + "Brand Parameters", + "Campaign Parameters", + "Category 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": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "required": "excluded", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, "revocations": { "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", "format": "Version Revocations", @@ -941,18 +1532,24 @@ } }, "notes": [], + "payload": { + "description": "JSON Schema document which defines the valid contents and \nformatting hints for the collection of data for a \nContest Parameters Document." + }, "signers": { "roles": { - "user": [ - "Registered" - ] + "admin": [ + "Brand Admin" + ], + "user": [] }, "update": { "author": true } }, "type": [ - "788ff4c6-d65a-451f-bb33-575fe056b411" + "788ff4c6-d65a-451f-bb33-575fe056b411", + "60185874-7e13-407c-a06c-238ffe637ae6", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" ], "versions": [ { @@ -964,6 +1561,11 @@ "changes": "* Use generalized parameters.", "modified": "2025-05-05", "version": "0.03" + }, + { + "changes": "* Generalize the Form Template definitions.", + "modified": "2025-05-05", + "version": "0.04" } ] }, @@ -1252,7 +1854,7 @@ }, "Proposal Comment Form Template": { "authors": {}, - "description": "## Proposal Comment Form Template Document\n\t\nA Proposal Comment Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Proposal Comment Form Template is a JSON Schema Document.\n\nProposal Comment entry *SHOULD* use the hints when collecting \ndata defined by the Proposal Comment Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Proposal Comment Presentation Template can be used to\nformat the Proposal Comment data for presentation.\n\nThe Proposal Comment Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Proposal Comment.\n\nThe payload of a Proposal Comment is controlled by its template.", + "description": "A Proposal Comment Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Proposal Comment Form Template is a JSON Schema Document.\n\nProposal Comment entry *SHOULD* use the hints when collecting \ndata defined by the Proposal Comment Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Proposal Comment Presentation Template can be used to\nformat the Proposal Comment data for presentation.\n\nThe Proposal Comment Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Proposal Comment.\n\nThe payload of a Proposal Comment is controlled by its template.", "headers": { "content type": { "coseLabel": 3, @@ -1355,8 +1957,7 @@ "signers": { "roles": { "admin": [ - "Brand Admin", - "Campaign Admin" + "Brand Admin" ], "user": [] }, @@ -1389,7 +1990,7 @@ }, "Proposal Comment Presentation Template": { "authors": {}, - "description": "## Proposal Comment Presentation Template Document\n\t\nA Proposal Comment Presentation Template defines how the data\ncaptured by the Proposal Comment Form Template is to be displayed.\n\nMultiple Proposal Comment Presentation Templates can exist for the \nsame Proposal Comment Form Template.\nEach can be used to display the form data under different \ncircumstances.\n\nProposal Comment Presentation Templates can reference any data contained\nin the Proposal Comment Document, as well as any documents linked by:\n\n* `ref`\n* `reply`\n* `parameters`\n\nThe presentation of the payload of a Proposal Comment is controlled by \nits Proposal Comment Presentation Template/s.", + "description": "A Proposal Comment Presentation Template defines how the data\ncaptured by the Proposal Comment Form Template is to be displayed.\n\nMultiple Proposal Comment Presentation Templates can exist for the \nsame Proposal Comment Form Template.\nEach can be used to display the form data under different \ncircumstances.\n\nProposal Comment Presentation Templates can reference any data contained\nin the Proposal Comment Document, as well as any documents linked by:\n\n* `ref`\n* `reply`\n* `parameters`\n\nThe presentation of the payload of a Proposal Comment is controlled by \nits Proposal Comment Presentation Template/s.", "headers": { "content type": { "coseLabel": 3, @@ -1514,7 +2115,7 @@ }, "Proposal Form Template": { "authors": {}, - "description": "## Proposal Form Template Document\n\t\nA Proposal Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Proposal Form Template is a JSON Schema Document.\n\nProposal entry *SHOULD* use the hints when collecting \ndata defined by the Proposal Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Proposal Presentation Template can be used to\nformat the Proposal data for presentation.\n\nThe Proposal Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Proposal.\n\nThe payload of a Proposal is controlled by its template.", + "description": "A Proposal Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Proposal Form Template is a JSON Schema Document.\n\nProposal entry *SHOULD* use the hints when collecting \ndata defined by the Proposal Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Proposal Presentation Template can be used to\nformat the Proposal data for presentation.\n\nThe Proposal Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Proposal.\n\nThe payload of a Proposal is controlled by its template.", "headers": { "content type": { "coseLabel": 3, @@ -1617,8 +2218,7 @@ "signers": { "roles": { "admin": [ - "Brand Admin", - "Campaign Admin" + "Brand Admin" ], "user": [] }, @@ -1766,7 +2366,7 @@ }, "Proposal Presentation Template": { "authors": {}, - "description": "## Proposal Presentation Template Document\n\t\nA Proposal Presentation Template defines how the data\ncaptured by the Proposal Form Template is to be displayed.\n\nMultiple Proposal Presentation Templates can exist for the \nsame Proposal Form Template.\nEach can be used to display the form data under different \ncircumstances.\n\nProposal Presentation Templates can reference any data contained\nin the Proposal Document, as well as any documents linked by:\n\n* `ref`\n* `reply`\n* `parameters`\n\nThe presentation of the payload of a Proposal is controlled by \nits Proposal Presentation Template/s.", + "description": "A Proposal Presentation Template defines how the data\ncaptured by the Proposal Form Template is to be displayed.\n\nMultiple Proposal Presentation Templates can exist for the \nsame Proposal Form Template.\nEach can be used to display the form data under different \ncircumstances.\n\nProposal Presentation Templates can reference any data contained\nin the Proposal Document, as well as any documents linked by:\n\n* `ref`\n* `reply`\n* `parameters`\n\nThe presentation of the payload of a Proposal is controlled by \nits Proposal Presentation Template/s.", "headers": { "content type": { "coseLabel": 3, @@ -1894,7 +2494,7 @@ "back_end": "A Submitted proposal with collaborators *MUST* have \na `final` submission by *ALL* listed `collaborators`.\nIf any `collaborator` has not submitted a `final` submission by the deadline, then the proposal \nis not considered `final` and will not be considered in the category it was being submitted to.", "front_end": "A proposal with `collaborators` will not be shown as having a confirmed collaborator,\nunless there exists a `draft` or `final` proposal submission from that collaborator.\n\nAny document that lists a collaborator should be highlighted to that collaborator so\nthey can take appropriate action, such as:\n\n* Confirm they are a collaborator by submitting this document as `draft`\n* Agree to being a collaborator on the final submission by submitting this document as `final`\n* Hide themselves from the collaborators list but do not remove themselves by submitting `hide`\n* Remove themselves permanently as a collaborator by publishing a new version with them removed.\n\nTo eliminate the necessity for collaborators to accept collaboration on every version, \nthey will be considered as agreeing to be a collaborator on any version of the document\nthat lists them, if their latest submission is `draft` or `final`.\n\nIf their latest submission on a document is `hide` they should be considered to not\nhave agreed to be a collaborator.\n\n*NOTE* `final` status ONLY applies to the exactly referenced document and version." }, - "description": "## Proposal Submission Action\n\nA Proposal Submission Action is a document which can attempt to either submit a \nparticular version of a proposal into a campaign, or withdraw it.\n\nThe last action on the document ts the action which takes effect at the deadline.\n\nFor multiple collaborators, multiple submission actions can be posted independently, \nbut none of them will take effect until ALL collaborators have posted equivalent actions.\n\nFor example, three collaborators Alice/Bob/Claire can each post one submission action\nfor the same document. \nUnless they all submit the same version of the proposal\nthe proposal will not be seen as submitted.\n\nThe payload is a fixed format.", + "description": "Proposal Submission Action\n\nA Proposal Submission Action is a document which can attempt to either submit a \nparticular version of a proposal into a campaign, or withdraw it.\n\nThe last action on the document ts the action which takes effect at the deadline.\n\nFor multiple collaborators, multiple submission actions can be posted independently, \nbut none of them will take effect until ALL collaborators have posted equivalent actions.\n\nFor example, three collaborators Alice/Bob/Claire can each post one submission action\nfor the same document. \nUnless they all submit the same version of the proposal\nthe proposal will not be seen as submitted.\n\nThe payload is a fixed format.", "headers": { "content type": { "coseLabel": 3, @@ -3355,7 +3955,7 @@ "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", "format": "Chain Link", "required": "optional", - "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n\n``` mermaid\n\tclassDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n\n``` mermaid\n\tclassDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n\n``` mermaid\n\tclassDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```\n" + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document.\n\n##### Example of a Valid Chain\n\n\n``` mermaid\nclassDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n\n```\n\n\n##### Example of an Invalid Chain\n\nEither of the two documents being present invalidates the data\nin the entire chain,\nas they are signed by the author of the chain.\n\n\n``` mermaid\nclassDiagram\n direction LR\n\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#f60,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#f60,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#f60,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Invalid_Chain {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n\n Invalid_Chain --|> First : Invalidly chains to\n style Invalid_Chain fill:#100,stroke:#f00,stroke-width:4px\n\n\n class After_Final {\n type: \"=Final.Document Type\"\n id: \"=Final.Document ID\"\n ver: \">Final.Document ID\"\n parameters: \"=Final.Document Parameters\"\n chain.height: 3\n chain.document_ref: \"=Last\"\n\n author(Last.Catalyst ID)\n }\n\n After_Final --|> Last : Invalidly chains to\n style After_Final fill:#100,stroke:#f00,stroke-width:4px\n\n```\n\n\n##### Example of a Fraudulent Chain Document\n\nThe invalid document does not invalidate the chain,\nas its not signed by the author of the chained documents.\n\n\n``` mermaid\nclassDiagram\n direction LR\n class Last {\n type: \"=Intermediate.Document Type\"\n id: \"=Intermediate.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: -2\n chain.document_ref: \"=Intermediate\"\n\n author(Intermediate.Catalyst ID)\n }\n style Last stroke:#060,stroke-width:4px\n\n class Intermediate {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">First.Document ID\"\n parameters: \"=First.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(First.Catalyst ID)\n }\n style Intermediate stroke:#060,stroke-width:4px\n\n class First {\n type: \"Document Type\"\n id: \"Document ID\"\n ver: \"=Document ID\"\n parameters: \"Document Parameters\"\n chain.height: 0\n chain.document_ref: None\n\n author(Catalyst ID)\n }\n style First stroke:#060,stroke-width:4px\n\n Last --|> Intermediate : chains to\n Intermediate --|> First : chains to\n\n class Rejected {\n type: \"=First.Document Type\"\n id: \"=First.Document ID\"\n ver: \">Intermediate.Document ID\"\n parameters: \"=Intermediate.Document Parameters\"\n chain.height: 1\n chain.document_ref: \"=First\"\n\n author(Other.Catalyst ID)\n }\n\n Rejected --|> Intermediate : Invalidly chains to\n style Rejected fill:#100,stroke:#f00,stroke-width:4px \n\n```\n" }, "collaborators": { "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", @@ -3379,7 +3979,7 @@ "Brand Parameters", "Campaign Parameters", "Category Parameters", - "Decision Parameters" + "Contest Parameters" ], "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document." }, @@ -3400,9 +4000,13 @@ "Proposal Moderation Action", "Comment Moderation Action", "Brand Parameters", + "Brand Parameters Form Template", "Campaign Parameters", + "Campaign Parameters Form Template", "Category Parameters", - "Decision Parameters" + "Category Parameters Form Template", + "Contest Parameters", + "Contest Parameters Form Template" ], "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, @@ -3437,7 +4041,11 @@ "required": "optional", "type": [ "Proposal Form Template", - "Proposal Comment Form Template" + "Proposal Comment Form Template", + "Brand Parameters Form Template", + "Campaign Parameters Form Template", + "Category Parameters Form Template", + "Contest Parameters Form Template" ], "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, From 2cd237e7bf29614f72b326185860118cfd28d6f3 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 23 Jun 2025 13:21:43 +0700 Subject: [PATCH 26/42] fix(docs): form templates do not have templates --- .../docs/brand_parameters_form_template.md | 4 ---- .../docs/campaign_parameters_form_template.md | 4 ---- .../docs/category_parameters_form_template.md | 4 ---- .../docs/contest_parameters_form_template.md | 4 ---- .../docs/proposal_comment_form_template.md | 4 ---- .../signed_doc/docs/proposal_form_template.md | 4 ---- .../docs/generic_form_template.cue | 3 --- specs/signed_doc.json | 24 +++++-------------- 8 files changed, 6 insertions(+), 45 deletions(-) diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md index a45bdf723eb..d5a97705a3e 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md @@ -120,7 +120,6 @@ The document version must always be >= the document ID. | Valid References | [Brand Parameters](brand_parameters.md) | | | [Campaign Parameters](campaign_parameters.md) | | | [Category Parameters](category_parameters.md) | -| Linked Reference Metadata | [`template`](#template) | A reference to the Parameters Document this document lies under. @@ -130,9 +129,6 @@ In addition to the validation performed for [Document Reference](../metadata.md# * Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the [`parameters`](../metadata.md#parameters) of the referencing document. -* The Document referenced by [`template`](../metadata.md#template) - * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND - * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md index 60bd9ecaff8..cb682396f95 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md @@ -120,7 +120,6 @@ The document version must always be >= the document ID. | Valid References | [Brand Parameters](brand_parameters.md) | | | [Campaign Parameters](campaign_parameters.md) | | | [Category Parameters](category_parameters.md) | -| Linked Reference Metadata | [`template`](#template) | A reference to the Parameters Document this document lies under. @@ -130,9 +129,6 @@ In addition to the validation performed for [Document Reference](../metadata.md# * Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the [`parameters`](../metadata.md#parameters) of the referencing document. -* The Document referenced by [`template`](../metadata.md#template) - * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND - * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md index da22ca30edb..55fa9ca449e 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md @@ -120,7 +120,6 @@ The document version must always be >= the document ID. | Valid References | [Brand Parameters](brand_parameters.md) | | | [Campaign Parameters](campaign_parameters.md) | | | [Category Parameters](category_parameters.md) | -| Linked Reference Metadata | [`template`](#template) | A reference to the Parameters Document this document lies under. @@ -130,9 +129,6 @@ In addition to the validation performed for [Document Reference](../metadata.md# * Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the [`parameters`](../metadata.md#parameters) of the referencing document. -* The Document referenced by [`template`](../metadata.md#template) - * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND - * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md index 13183bb0e5f..2ceb002c9bb 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md @@ -120,7 +120,6 @@ The document version must always be >= the document ID. | Valid References | [Brand Parameters](brand_parameters.md) | | | [Campaign Parameters](campaign_parameters.md) | | | [Category Parameters](category_parameters.md) | -| Linked Reference Metadata | [`template`](#template) | A reference to the Parameters Document this document lies under. @@ -130,9 +129,6 @@ In addition to the validation performed for [Document Reference](../metadata.md# * Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the [`parameters`](../metadata.md#parameters) of the referencing document. -* The Document referenced by [`template`](../metadata.md#template) - * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND - * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md index 70d80cddd7a..afee4feadcc 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md @@ -120,7 +120,6 @@ The document version must always be >= the document ID. | Valid References | [Brand Parameters](brand_parameters.md) | | | [Campaign Parameters](campaign_parameters.md) | | | [Category Parameters](category_parameters.md) | -| Linked Reference Metadata | [`template`](#template) | A reference to the Parameters Document this document lies under. @@ -130,9 +129,6 @@ In addition to the validation performed for [Document Reference](../metadata.md# * Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the [`parameters`](../metadata.md#parameters) of the referencing document. -* The Document referenced by [`template`](../metadata.md#template) - * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND - * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md index 9cf27f72eee..9fdf85cd2c5 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md @@ -120,7 +120,6 @@ The document version must always be >= the document ID. | Valid References | [Brand Parameters](brand_parameters.md) | | | [Campaign Parameters](campaign_parameters.md) | | | [Category Parameters](category_parameters.md) | -| Linked Reference Metadata | [`template`](#template) | A reference to the Parameters Document this document lies under. @@ -130,9 +129,6 @@ In addition to the validation performed for [Document Reference](../metadata.md# * Any linked referenced document that includes a [`parameters`](../metadata.md#parameters) metadata must match the [`parameters`](../metadata.md#parameters) of the referencing document. -* The Document referenced by [`template`](../metadata.md#template) - * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND - * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. ## Payload diff --git a/specs/definitions/signed_docs/docs/generic_form_template.cue b/specs/definitions/signed_docs/docs/generic_form_template.cue index 91bc12654e8..be758db38e1 100644 --- a/specs/definitions/signed_docs/docs/generic_form_template.cue +++ b/specs/definitions/signed_docs/docs/generic_form_template.cue @@ -41,9 +41,6 @@ _form_template_payload_description: """ parameters: { required: "yes" type: doc_clusters."System Parameters".docs - linked_refs: [ - "template", - ] } } diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 2d77a3e5987..94b646257f6 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -550,9 +550,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": [ - "template" - ], + "linked_refs": null, "multiple": false, "required": "yes", "type": [ @@ -818,9 +816,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": [ - "template" - ], + "linked_refs": null, "multiple": false, "required": "yes", "type": [ @@ -1086,9 +1082,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": [ - "template" - ], + "linked_refs": null, "multiple": false, "required": "yes", "type": [ @@ -1476,9 +1470,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": [ - "template" - ], + "linked_refs": null, "multiple": false, "required": "yes", "type": [ @@ -1895,9 +1887,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": [ - "template" - ], + "linked_refs": null, "multiple": false, "required": "yes", "type": [ @@ -2156,9 +2146,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": [ - "template" - ], + "linked_refs": null, "multiple": false, "required": "yes", "type": [ From ddf75b4136577ea8d8cd691856bee9d67bbc6688 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 23 Jun 2025 17:16:58 +0700 Subject: [PATCH 27/42] fix(docs): remove the parameters from templates on the parameters documents themselves (redundant). --- .../08_concepts/signed_doc/diagrams/all.dot | 44 ---------- .../signed_doc/diagrams/brand_parameters.dot | 49 ----------- .../brand_parameters_form_template.dot | 83 +++++-------------- .../diagrams/campaign_parameters.dot | 49 ----------- .../campaign_parameters_form_template.dot | 83 +++++-------------- .../diagrams/category_parameters.dot | 49 ----------- .../category_parameters_form_template.dot | 83 +++++-------------- .../contest_parameters_form_template.dot | 62 -------------- .../docs/brand_parameters_form_template.md | 20 ----- .../docs/campaign_parameters_form_template.md | 20 ----- .../docs/category_parameters_form_template.md | 20 ----- .../docs/contest_parameters_form_template.md | 20 ----- .../docs/generic_form_template.cue | 15 ++-- .../docs/proposal_comment_form_template.cue | 1 + .../docs/proposal_form_template.cue | 1 + specs/signed_doc.json | 36 +------- 16 files changed, 76 insertions(+), 559 deletions(-) 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 6a3eb523512..40a42e6e0d4 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot @@ -61,16 +61,6 @@ digraph "All" { - - - - - - - -
parametersBrand Parameters
Campaign Parameters
Category Parameters
- - > @@ -126,16 +116,6 @@ digraph "All" { - - - - - - - -
parametersBrand Parameters
Campaign Parameters
Category Parameters
- - > @@ -191,16 +171,6 @@ digraph "All" { - - - - - - - -
parametersBrand Parameters
Campaign Parameters
Category Parameters
- - > @@ -436,16 +406,6 @@ digraph "All" { - - - - - - - -
parametersBrand Parameters
Campaign Parameters
Category Parameters
- - > @@ -1324,17 +1284,13 @@ digraph "All" { } "Brand Parameters":"template":e -> "Brand Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Brand Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Campaign Parameters":"template":e -> "Campaign Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Campaign Parameters":"parameters":e -> "Brand Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Campaign Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Category Parameters":"template":e -> "Category Parameters Form Template":"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="*"] - "Category Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Comment Moderation Action":"ref":e -> "Proposal Comment":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Contest Parameters":"template":e -> "Contest Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Contest Parameters":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Contest Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal":"template":e -> "Proposal Form 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 d537924e337..3850886cb95 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 @@ -28,36 +28,6 @@ Relationships" ]; - "Campaign Parameters Form Template" [ - id="Campaign Parameters Form Template"; - label=< - - - - - -
- Campaign Parameters Form Template -
- > - ]; - - - "Category Parameters Form Template" [ - id="Category Parameters Form Template"; - label=< - - - - - -
- Category Parameters Form Template -
- > - ]; - - "Contest Parameters" [ id="Contest Parameters"; label=< @@ -73,21 +43,6 @@ Relationships" ]; - "Contest Parameters Form Template" [ - id="Contest Parameters Form Template"; - label=< - - - - - -
- Contest Parameters Form Template -
- > - ]; - - "Proposal" [ id="Proposal"; label=< @@ -300,12 +255,8 @@ Relationships" } "Brand Parameters":"template":e -> "Brand Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Brand Parameters Form Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Campaign Parameters":"title":e -> "Brand Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Campaign Parameters Form Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Category Parameters Form Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Contest Parameters":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Contest Parameters Form Template":"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 Form 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/brand_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters_form_template.dot index 9d421279b56..68f6d10ece6 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters_form_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters_form_template.dot @@ -13,57 +13,6 @@ Document 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 -
- > - ]; - - } - "Brand Parameters Form Template" [ id="Brand Parameters Form Template"; label=< @@ -113,22 +62,32 @@ Document Relationships" - - - - - - - -
parametersBrand Parameters
Campaign Parameters
Category Parameters
- - > ]; - "Brand Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 + + "Brand Parameters" [ + id="Brand Parameters"; + label=< + + + + + +
+ Brand Parameters +
+ > + ]; + + } + "Brand Parameters":"title":e -> "Brand Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } 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 b8a11fc2f86..2b0e4c1abf8 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 @@ -28,36 +28,6 @@ Relationships" ]; - "Brand Parameters Form Template" [ - id="Brand Parameters Form Template"; - label=< - - - - - -
- Brand Parameters Form Template -
- > - ]; - - - "Category Parameters Form Template" [ - id="Category Parameters Form Template"; - label=< - - - - - -
- Category Parameters Form Template -
- > - ]; - - "Contest Parameters" [ id="Contest Parameters"; label=< @@ -73,21 +43,6 @@ Relationships" ]; - "Contest Parameters Form Template" [ - id="Contest Parameters Form Template"; - label=< - - - - - -
- Contest Parameters Form Template -
- > - ]; - - "Proposal" [ id="Proposal"; label=< @@ -326,12 +281,8 @@ Relationships" "Campaign Parameters":"template":e -> "Campaign Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Campaign Parameters":"parameters":e -> "Brand Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Brand Parameters Form Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Campaign Parameters Form Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Category Parameters":"title":e -> "Campaign Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] - "Category Parameters Form Template":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Contest Parameters":"title":e -> "Campaign Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Contest Parameters Form Template":"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 Form 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/campaign_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot index aff620a00e3..6353661624e 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot @@ -14,57 +14,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 -
- > - ]; - - } - "Campaign Parameters Form Template" [ id="Campaign Parameters Form Template"; label=< @@ -114,22 +63,32 @@ Relationships" - - - - - - - -
parametersBrand Parameters
Campaign Parameters
Category Parameters
- - > ]; - "Campaign Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 + + "Campaign Parameters" [ + id="Campaign Parameters"; + label=< + + + + + +
+ Campaign Parameters +
+ > + ]; + + } + "Campaign Parameters":"title":e -> "Campaign Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } 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 0e4a3ba08e3..3a54fd48b38 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 @@ -28,36 +28,6 @@ Relationships" ]; - "Brand Parameters Form Template" [ - id="Brand Parameters Form Template"; - label=< - - - - - -
- Brand Parameters Form Template -
- > - ]; - - - "Campaign Parameters Form Template" [ - id="Campaign Parameters Form Template"; - label=< - - - - - -
- Campaign Parameters Form Template -
- > - ]; - - "Contest Parameters" [ id="Contest Parameters"; label=< @@ -73,21 +43,6 @@ Relationships" ]; - "Contest Parameters Form Template" [ - id="Contest Parameters Form Template"; - label=< - - - - - -
- Contest Parameters Form Template -
- > - ]; - - "Proposal" [ id="Proposal"; label=< @@ -311,11 +266,7 @@ Relationships" "Category Parameters":"template":e -> "Category Parameters Form Template":"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="*"] - "Brand Parameters Form Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Campaign Parameters Form Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Category Parameters Form Template":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Contest Parameters":"title":e -> "Category Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] - "Contest Parameters Form Template":"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 Form 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/category_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot index fca38408d6a..1e7709ead5e 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot @@ -14,57 +14,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 -
- > - ]; - - } - "Category Parameters Form Template" [ id="Category Parameters Form Template"; label=< @@ -114,22 +63,32 @@ Relationships" - - - - - - - -
parametersBrand Parameters
Campaign Parameters
Category Parameters
- - > ]; - "Category Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 + + "Category Parameters" [ + id="Category Parameters"; + label=< + + + + + +
+ Category Parameters +
+ > + ]; + + } + "Category Parameters":"title":e -> "Category Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot index 8c2f1edf674..860d3c9b3cf 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot @@ -14,57 +14,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 -
- > - ]; - - } - "Contest Parameters Form Template" [ id="Contest Parameters Form Template"; label=< @@ -114,16 +63,6 @@ Relationships" - - - - - - - -
parametersBrand Parameters
Campaign Parameters
Category Parameters
- - > @@ -145,6 +84,5 @@ Relationships" ]; - "Contest Parameters Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Contest Parameters":"title":e -> "Contest Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md index d5a97705a3e..05897f06f45 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md @@ -110,26 +110,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) | -| | [Campaign Parameters](campaign_parameters.md) | -| | [Category Parameters](category_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 [JSON Schema][JSON Schema-2020-12] document which defines the valid contents and diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md index cb682396f95..7442249be18 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md @@ -110,26 +110,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) | -| | [Campaign Parameters](campaign_parameters.md) | -| | [Category Parameters](category_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 [JSON Schema][JSON Schema-2020-12] document which defines the valid contents and diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md index 55fa9ca449e..37fc6203137 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md @@ -110,26 +110,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) | -| | [Campaign Parameters](campaign_parameters.md) | -| | [Category Parameters](category_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 [JSON Schema][JSON Schema-2020-12] document which defines the valid contents and diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md index 2ceb002c9bb..e8fce9081cb 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md @@ -110,26 +110,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) | -| | [Campaign Parameters](campaign_parameters.md) | -| | [Category Parameters](category_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 [JSON Schema][JSON Schema-2020-12] document which defines the valid contents and diff --git a/specs/definitions/signed_docs/docs/generic_form_template.cue b/specs/definitions/signed_docs/docs/generic_form_template.cue index be758db38e1..2f5980c0a77 100644 --- a/specs/definitions/signed_docs/docs/generic_form_template.cue +++ b/specs/definitions/signed_docs/docs/generic_form_template.cue @@ -30,19 +30,18 @@ _form_template_payload_description: """ {{ .doc }} Document. """ +_metadataFieldSystemParameters: #metadataField & { + // Is the field required to be present. + required: "yes" + type: doc_clusters."System Parameters".docs +} + #generic_form_template: #signedDocument & { description: _ headers: "content type": value: "application/schema+json" - metadata: { - template: required: "excluded" - - parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - } - } + metadata: template: required: "excluded" payload: description: _ diff --git a/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue b/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue index 2898956cbc9..6adceecbbb6 100644 --- a/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue +++ b/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue @@ -8,6 +8,7 @@ _proposal_comment_form_data: doc: "Proposal Comment" docs: #DocumentDefinitions & { "Proposal Comment Form Template": #generic_form_template & { description: template.Execute(_form_template_description, _proposal_comment_form_data) + metadata: parameters: _metadataFieldSystemParameters payload: description: template.Execute(_form_template_payload_description, _proposal_comment_form_data) versions: _generic_form_template_versions } diff --git a/specs/definitions/signed_docs/docs/proposal_form_template.cue b/specs/definitions/signed_docs/docs/proposal_form_template.cue index 2786514c821..b91b9be612f 100644 --- a/specs/definitions/signed_docs/docs/proposal_form_template.cue +++ b/specs/definitions/signed_docs/docs/proposal_form_template.cue @@ -8,6 +8,7 @@ _proposal_form_data: doc: "Proposal" docs: #DocumentDefinitions & { "Proposal Form Template": #generic_form_template & { description: template.Execute(_form_template_description, _proposal_form_data) + metadata: parameters: _metadataFieldSystemParameters payload: description: template.Execute(_form_template_payload_description, _proposal_form_data) versions: _generic_form_template_versions //metadata: template: type: "Proposal Presentation Template" diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 94b646257f6..6409e30a560 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -550,14 +550,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "yes", - "type": [ - "Brand Parameters", - "Campaign Parameters", - "Category 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": { @@ -816,14 +809,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "yes", - "type": [ - "Brand Parameters", - "Campaign Parameters", - "Category 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": { @@ -1082,14 +1068,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "yes", - "type": [ - "Brand Parameters", - "Campaign Parameters", - "Category 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": { @@ -1470,14 +1449,7 @@ "parameters": { "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", - "linked_refs": null, - "multiple": false, - "required": "yes", - "type": [ - "Brand Parameters", - "Campaign Parameters", - "Category 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": { From b474b05ccd9068d128f1f8d600ae72431cdddaaa Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Mon, 23 Jun 2025 17:21:07 +0700 Subject: [PATCH 28/42] fix(docs): use common parameters definition --- specs/definitions/signed_docs/docs/parameters_contest.cue | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/specs/definitions/signed_docs/docs/parameters_contest.cue b/specs/definitions/signed_docs/docs/parameters_contest.cue index a57facf650d..d464bf91b36 100644 --- a/specs/definitions/signed_docs/docs/parameters_contest.cue +++ b/specs/definitions/signed_docs/docs/parameters_contest.cue @@ -14,10 +14,7 @@ docs: "Contest Parameters": #generic_parameters & { validation: template.Execute(_parameters_parent_validation, _data) metadata: { template: type: "\(_data.doc) Parameters Form Template" - parameters: { - required: "yes" - type: doc_clusters."System Parameters".docs - } + parameters: _metadataFieldSystemParameters } payload: description: template.Execute(_parameters_payload_description, _data) versions: _generic_parameters_versions From 1add926d6fc1361dc550f48efc4dc7f370b90566 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Tue, 24 Jun 2025 08:31:33 +0700 Subject: [PATCH 29/42] feat(docs): Add Representative Profiles and Nomination Forms --- .config/dictionaries/project.dic | 1 + .../08_concepts/signed_doc/diagrams/all.dot | 333 +++++++++- .../signed_doc/diagrams/brand_parameters.dot | 34 +- .../brand_parameters_form_template.dot | 2 +- .../diagrams/campaign_parameters.dot | 2 +- .../campaign_parameters_form_template.dot | 2 +- .../diagrams/category_parameters.dot | 2 +- .../category_parameters_form_template.dot | 2 +- .../diagrams/contest_parameters.dot | 34 +- .../contest_parameters_form_template.dot | 2 +- .../signed_doc/diagrams/rep_nomination.dot | 159 +++++ .../diagrams/rep_nomination_form_template.dot | 113 ++++ .../signed_doc/diagrams/rep_profile.dot | 155 +++++ .../diagrams/rep_profile_form_template.dot | 119 ++++ .../signed_doc/docs/brand_parameters.md | 2 +- .../docs/brand_parameters_form_template.md | 2 +- .../signed_doc/docs/campaign_parameters.md | 13 +- .../docs/campaign_parameters_form_template.md | 2 +- .../signed_doc/docs/category_parameters.md | 13 +- .../docs/category_parameters_form_template.md | 2 +- .../signed_doc/docs/contest_parameters.md | 13 +- .../docs/contest_parameters_form_template.md | 2 +- .../08_concepts/signed_doc/docs/proposal.md | 11 +- .../signed_doc/docs/proposal_comment.md | 11 +- .../docs/proposal_comment_form_template.md | 11 +- .../proposal_comment_presentation_template.md | 11 +- .../signed_doc/docs/proposal_form_template.md | 11 +- .../docs/proposal_presentation_template.md | 11 +- .../docs/proposal_submission_action.md | 11 +- .../signed_doc/docs/rep_nomination.md | 271 ++++++++ .../docs/rep_nomination_form_template.md | 183 ++++++ .../signed_doc/docs/rep_profile.md | 211 ++++++ .../docs/rep_profile_form_template.md | 183 ++++++ .../08_concepts/signed_doc/metadata.md | 17 +- .../08_concepts/signed_doc/types.md | 25 +- specs/definitions/signed_docs/docs/all.cue | 63 +- .../docs/generic_form_template.cue | 15 + .../docs/generic_presentation_template.cue | 2 +- .../docs/proposal_comment_form_template.cue | 14 +- ...proposal_comment_presentation_template.cue | 11 +- .../docs/proposal_form_template.cue | 15 +- .../docs/proposal_presentation_template.cue | 11 +- .../docs/rep_nomination_form_template.cue | 14 + .../signed_docs/docs/rep_nomintion.cue | 101 +++ .../signed_docs/docs/rep_profile.cue | 79 +++ .../docs/rep_profile_form_template.cue | 14 + specs/definitions/signed_docs/metadata.cue | 12 - .../signed_docs/metadata_parameters.cue | 54 ++ specs/definitions/signed_docs/signed_doc.cue | 8 - specs/signed_doc.json | 612 ++++++++++++++++-- 50 files changed, 2852 insertions(+), 149 deletions(-) create mode 100644 docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination.dot create mode 100644 docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination_form_template.dot create mode 100644 docs/src/architecture/08_concepts/signed_doc/diagrams/rep_profile.dot create mode 100644 docs/src/architecture/08_concepts/signed_doc/diagrams/rep_profile_form_template.dot create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination_form_template.md create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/rep_profile.md create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/rep_profile_form_template.md create mode 100644 specs/definitions/signed_docs/docs/rep_nomination_form_template.cue create mode 100644 specs/definitions/signed_docs/docs/rep_nomintion.cue create mode 100644 specs/definitions/signed_docs/docs/rep_profile.cue create mode 100644 specs/definitions/signed_docs/docs/rep_profile_form_template.cue create mode 100644 specs/definitions/signed_docs/metadata_parameters.cue diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index 3c86b726ff9..924691fb19d 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -11,6 +11,7 @@ Arissara asyncio Attributes auditability +Auliffe auxdata babystep backpressure 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 40a42e6e0d4..2dfce1089b4 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot @@ -36,7 +36,7 @@ digraph "All" { - +
typeebcabeeb-5bc5-4f95-91e8-cab8ca724172
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
ebcabeeb-5bc5-4f95-91e8-cab8ca724172
@@ -91,7 +91,7 @@ digraph "All" { - +
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
5ef32d5d-f240-462c-a7a4-ba4af221fa23
@@ -146,7 +146,7 @@ digraph "All" { - +
type818938c3-3139-4daa-afe6-974c78488e95
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
818938c3-3139-4daa-afe6-974c78488e95
@@ -381,7 +381,7 @@ digraph "All" { - +
type788ff4c6-d65a-451f-bb33-575fe056b411
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
788ff4c6-d65a-451f-bb33-575fe056b411
@@ -436,7 +436,7 @@ digraph "All" { - +
type788ff4c6-d65a-451f-bb33-575fe056b411
60185874-7e13-407c-a06c-238ffe637ae6
60185874-7e13-407c-a06c-238ffe637ae6
788ff4c6-d65a-451f-bb33-575fe056b411
@@ -1002,6 +1002,316 @@ digraph "All" { ]; + "Rep Profile" [ + id="Rep Profile"; + label=< + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Rep Profile +
+ + + + + +
content typeapplication/json
+
+ + + + + +
type0f2c86a2-ffda-40b0-ad38-23709e1c10b3
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
templateRep Profile Form Template
+
+ + + + + +
revocationsVersion Revocations
+
+ + + + + +
parametersBrand Parameters
+
+ > + ]; + + + "Rep Nomination Form Template" [ + id="Rep Nomination Form Template"; + label=< + + + + + + + + + + + + + + + + + + + + +
+ Rep Nomination Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
bf9abd97-5d1f-4429-8e80-740fea371a9c
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersContest Parameters
+
+ > + ]; + + + "Rep Nomination" [ + id="Rep Nomination"; + label=< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Rep Nomination +
+ + + + + +
content typeapplication/json
+
+ + + + + +
typebf9abd97-5d1f-4429-8e80-740fea371a9c
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
refRep Profile
+
+ + + + + +
templateRep Nomination Form Template
+
+ + + + + +
revocationsVersion Revocations
+
+ + + + + +
parametersContest Parameters
+
+ > + ]; + + + "Rep Profile Form Template" [ + id="Rep Profile Form Template"; + label=< + + + + + + + + + + + + + + + + + + + + +
+ Rep Profile Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0f2c86a2-ffda-40b0-ad38-23709e1c10b3
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersBrand Parameters
+
+ > + ]; + + subgraph cluster_system_parameters { label = "System Parameters"; color=blue @@ -1031,7 +1341,7 @@ digraph "All" { - +
typeebcabeeb-5bc5-4f95-91e8-cab8ca724172
60185874-7e13-407c-a06c-238ffe637ae6
60185874-7e13-407c-a06c-238ffe637ae6
ebcabeeb-5bc5-4f95-91e8-cab8ca724172
@@ -1116,7 +1426,7 @@ digraph "All" { - +
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
60185874-7e13-407c-a06c-238ffe637ae6
60185874-7e13-407c-a06c-238ffe637ae6
5ef32d5d-f240-462c-a7a4-ba4af221fa23
@@ -1211,7 +1521,7 @@ digraph "All" { - +
type818938c3-3139-4daa-afe6-974c78488e95
60185874-7e13-407c-a06c-238ffe637ae6
60185874-7e13-407c-a06c-238ffe637ae6
818938c3-3139-4daa-afe6-974c78488e95
@@ -1304,4 +1614,11 @@ digraph "All" { "Proposal Presentation Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Submission Action":"ref":e -> "Proposal":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Proposal Submission Action":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Rep Nomination":"ref":e -> "Rep Profile":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Nomination":"template":e -> "Rep Nomination Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Nomination":"parameters":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Nomination Form Template":"parameters":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Profile":"template":e -> "Rep Profile Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Profile":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Rep Profile Form Template":"parameters":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/brand_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters.dot index 3850886cb95..f260bb12cce 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 @@ -148,6 +148,36 @@ Relationships" ]; + "Rep Profile" [ + id="Rep Profile"; + label=< + + + + + +
+ Rep Profile +
+ > + ]; + + + "Rep Profile Form Template" [ + id="Rep Profile Form Template"; + label=< + + + + + +
+ Rep Profile Form Template +
+ > + ]; + + subgraph cluster_system_parameters { label = "System Parameters"; color=blue @@ -177,7 +207,7 @@ Relationships" - +
typeebcabeeb-5bc5-4f95-91e8-cab8ca724172
60185874-7e13-407c-a06c-238ffe637ae6
60185874-7e13-407c-a06c-238ffe637ae6
ebcabeeb-5bc5-4f95-91e8-cab8ca724172
@@ -264,4 +294,6 @@ Relationships" "Proposal Form Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Presentation Template":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal Submission Action":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Rep Profile":"title":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Rep Profile Form 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/brand_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters_form_template.dot index 68f6d10ece6..d026ecbce4d 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters_form_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/brand_parameters_form_template.dot @@ -37,7 +37,7 @@ Document Relationships" - +
typeebcabeeb-5bc5-4f95-91e8-cab8ca724172
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
ebcabeeb-5bc5-4f95-91e8-cab8ca724172
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 2b0e4c1abf8..58d8fafabcd 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 @@ -192,7 +192,7 @@ Relationships" - +
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
60185874-7e13-407c-a06c-238ffe637ae6
60185874-7e13-407c-a06c-238ffe637ae6
5ef32d5d-f240-462c-a7a4-ba4af221fa23
diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot index 6353661624e..3f72dfb6aec 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/campaign_parameters_form_template.dot @@ -38,7 +38,7 @@ Relationships" - +
type5ef32d5d-f240-462c-a7a4-ba4af221fa23
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
5ef32d5d-f240-462c-a7a4-ba4af221fa23
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 3a54fd48b38..b010bf86aba 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 @@ -192,7 +192,7 @@ Relationships" - +
type818938c3-3139-4daa-afe6-974c78488e95
60185874-7e13-407c-a06c-238ffe637ae6
60185874-7e13-407c-a06c-238ffe637ae6
818938c3-3139-4daa-afe6-974c78488e95
diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot index 1e7709ead5e..a142233fc5c 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/category_parameters_form_template.dot @@ -38,7 +38,7 @@ Relationships" - +
type818938c3-3139-4daa-afe6-974c78488e95
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
818938c3-3139-4daa-afe6-974c78488e95
diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot index 092e7245e71..81160f952b9 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot @@ -52,7 +52,7 @@ Relationships" - +
type788ff4c6-d65a-451f-bb33-575fe056b411
60185874-7e13-407c-a06c-238ffe637ae6
60185874-7e13-407c-a06c-238ffe637ae6
788ff4c6-d65a-451f-bb33-575fe056b411
@@ -123,6 +123,36 @@ Relationships" ]; + "Rep Nomination" [ + id="Rep Nomination"; + label=< + + + + + +
+ Rep Nomination +
+ > + ]; + + + "Rep Nomination Form Template" [ + id="Rep Nomination Form Template"; + label=< + + + + + +
+ Rep Nomination Form Template +
+ > + ]; + + subgraph cluster_system_parameters { label = "System Parameters"; color=blue @@ -176,4 +206,6 @@ Relationships" "Contest Parameters":"template":e -> "Contest Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Contest Parameters":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Rep Nomination":"title":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Nomination Form Template":"title":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot index 860d3c9b3cf..3ea9b1438dc 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters_form_template.dot @@ -38,7 +38,7 @@ Relationships" - +
type788ff4c6-d65a-451f-bb33-575fe056b411
60185874-7e13-407c-a06c-238ffe637ae6
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
788ff4c6-d65a-451f-bb33-575fe056b411
diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination.dot new file mode 100644 index 00000000000..9bf0efefb11 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination.dot @@ -0,0 +1,159 @@ +digraph "Rep Nomination" { + rankdir="LR" + graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; + node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; + edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; + + labelloc="t" + label="Rep Nomination Document +Relationships" + fontcolor="#1d71b8" + fontsize=50 + compound=true + + + + "Rep Profile" [ + id="Rep Profile"; + label=< + + + + + +
+ Rep Profile +
+ > + ]; + + + "Rep Nomination Form Template" [ + id="Rep Nomination Form Template"; + label=< + + + + + +
+ Rep Nomination Form Template +
+ > + ]; + + + "Contest Parameters" [ + id="Contest Parameters"; + label=< + + + + + +
+ Contest Parameters +
+ > + ]; + + + "Rep Nomination" [ + id="Rep Nomination"; + label=< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Rep Nomination +
+ + + + + +
content typeapplication/json
+
+ + + + + +
typebf9abd97-5d1f-4429-8e80-740fea371a9c
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
refRep Profile
+
+ + + + + +
templateRep Nomination Form Template
+
+ + + + + +
revocationsVersion Revocations
+
+ + + + + +
parametersContest Parameters
+
+ > + ]; + + + "Rep Nomination":"ref":e -> "Rep Profile":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Nomination":"template":e -> "Rep Nomination Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Nomination":"parameters":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] +} diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination_form_template.dot new file mode 100644 index 00000000000..27e572ed62a --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination_form_template.dot @@ -0,0 +1,113 @@ +digraph "Rep Nomination Form Template" { + rankdir="LR" + graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; + node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; + edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; + + labelloc="t" + label="Rep Nomination Form Template +Document Relationships" + fontcolor="#1d71b8" + fontsize=50 + compound=true + + + + "Contest Parameters" [ + id="Contest Parameters"; + label=< + + + + + +
+ Contest Parameters +
+ > + ]; + + + "Rep Nomination Form Template" [ + id="Rep Nomination Form Template"; + label=< + + + + + + + + + + + + + + + + + + + + +
+ Rep Nomination Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
bf9abd97-5d1f-4429-8e80-740fea371a9c
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersContest Parameters
+
+ > + ]; + + + "Rep Nomination" [ + id="Rep Nomination"; + label=< + + + + + +
+ Rep Nomination +
+ > + ]; + + + "Rep Nomination Form Template":"parameters":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Nomination":"title":e -> "Rep Nomination Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] +} diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_profile.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_profile.dot new file mode 100644 index 00000000000..f7741a8b953 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_profile.dot @@ -0,0 +1,155 @@ +digraph "Rep Profile" { + rankdir="LR" + graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; + node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; + edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; + + labelloc="t" + label="Rep Profile Document +Relationships" + fontcolor="#1d71b8" + fontsize=50 + compound=true + + + + "Rep Profile Form Template" [ + id="Rep Profile Form Template"; + label=< + + + + + +
+ Rep Profile Form Template +
+ > + ]; + + + "Rep Profile" [ + id="Rep Profile"; + label=< + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Rep Profile +
+ + + + + +
content typeapplication/json
+
+ + + + + +
type0f2c86a2-ffda-40b0-ad38-23709e1c10b3
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
templateRep Profile Form Template
+
+ + + + + +
revocationsVersion Revocations
+
+ + + + + +
parametersBrand Parameters
+
+ > + ]; + + + "Rep Nomination" [ + id="Rep Nomination"; + label=< + + + + + +
+ Rep Nomination +
+ > + ]; + + + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 + + "Brand Parameters" [ + id="Brand Parameters"; + label=< + + + + + +
+ Brand Parameters +
+ > + ]; + + } + + "Rep Profile":"template":e -> "Rep Profile Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Rep Profile":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Rep Nomination":"title":e -> "Rep Profile":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] +} diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_profile_form_template.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_profile_form_template.dot new file mode 100644 index 00000000000..b06843a2c6f --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_profile_form_template.dot @@ -0,0 +1,119 @@ +digraph "Rep Profile Form Template" { + rankdir="LR" + graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; + node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; + edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; + + labelloc="t" + label="Rep Profile Form Template +Document Relationships" + fontcolor="#1d71b8" + fontsize=50 + compound=true + + + + subgraph cluster_system_parameters { + label = "System Parameters"; + color=blue + penwidth=20 + + "Brand Parameters" [ + id="Brand Parameters"; + label=< + + + + + +
+ Brand Parameters +
+ > + ]; + + } + + "Rep Profile Form Template" [ + id="Rep Profile Form Template"; + label=< + + + + + + + + + + + + + + + + + + + + +
+ Rep Profile Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
0f2c86a2-ffda-40b0-ad38-23709e1c10b3
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
parametersBrand Parameters
+
+ > + ]; + + + "Rep Profile" [ + id="Rep Profile"; + label=< + + + + + +
+ Rep Profile +
+ > + ]; + + + "Rep Profile Form Template":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Rep Profile":"title":e -> "Rep Profile Form Template":"title":w [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 d12cc399e90..9d24a1c94ad 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 @@ -63,7 +63,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `ebcabeeb-5bc5-4f95-91e8-cab8ca724172`,
`60185874-7e13-407c-a06c-238ffe637ae6` | +| Type | `60185874-7e13-407c-a06c-238ffe637ae6`,
`ebcabeeb-5bc5-4f95-91e8-cab8ca724172` | The document TYPE. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md index 05897f06f45..76e5c64df3c 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters_form_template.md @@ -68,7 +68,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `ebcabeeb-5bc5-4f95-91e8-cab8ca724172`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | +| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`ebcabeeb-5bc5-4f95-91e8-cab8ca724172` | The document TYPE. 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 877aae9468f..51d82900edb 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 @@ -64,7 +64,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `5ef32d5d-f240-462c-a7a4-ba4af221fa23`,
`60185874-7e13-407c-a06c-238ffe637ae6` | +| Type | `60185874-7e13-407c-a06c-238ffe637ae6`,
`5ef32d5d-f240-462c-a7a4-ba4af221fa23` | The document TYPE. @@ -188,7 +188,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md index 7442249be18..5f2874efd6f 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters_form_template.md @@ -68,7 +68,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `5ef32d5d-f240-462c-a7a4-ba4af221fa23`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | +| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`5ef32d5d-f240-462c-a7a4-ba4af221fa23` | The document TYPE. 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 df7ca591169..200be96a205 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 @@ -64,7 +64,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `818938c3-3139-4daa-afe6-974c78488e95`,
`60185874-7e13-407c-a06c-238ffe637ae6` | +| Type | `60185874-7e13-407c-a06c-238ffe637ae6`,
`818938c3-3139-4daa-afe6-974c78488e95` | The document TYPE. @@ -188,7 +188,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md index 37fc6203137..03f61374d8e 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters_form_template.md @@ -68,7 +68,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `818938c3-3139-4daa-afe6-974c78488e95`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | +| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`818938c3-3139-4daa-afe6-974c78488e95` | The document TYPE. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md index 478d189bc9d..8d493ec06b9 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md @@ -64,7 +64,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `788ff4c6-d65a-451f-bb33-575fe056b411`,
`60185874-7e13-407c-a06c-238ffe637ae6` | +| Type | `60185874-7e13-407c-a06c-238ffe637ae6`,
`788ff4c6-d65a-451f-bb33-575fe056b411` | The document TYPE. @@ -190,7 +190,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md index e8fce9081cb..2f6c3422312 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters_form_template.md @@ -68,7 +68,7 @@ This section will be included and updated in future iterations. | --- | --- | | Required | yes | | Format | [Document Type](../metadata.md#document-type) | -| Type | `788ff4c6-d65a-451f-bb33-575fe056b411`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | +| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`60185874-7e13-407c-a06c-238ffe637ae6`,
`788ff4c6-d65a-451f-bb33-575fe056b411` | The document TYPE. 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 d75bf311847..96cd451e873 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md @@ -199,7 +199,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. * The Document referenced by [`template`](../metadata.md#template) * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. 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 72be672baec..385dabe07b5 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 @@ -235,7 +235,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. * The Document referenced by [`ref`](../metadata.md#ref) * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md index afee4feadcc..daf9dc23f0f 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md @@ -128,7 +128,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md index d4f671d3300..01bdf0051f5 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md @@ -125,7 +125,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md index 9fdf85cd2c5..22818dd18c1 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md @@ -128,7 +128,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. ## Payload diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md index 7e6456af170..9d0d6f90ca8 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md @@ -125,7 +125,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. ## Payload 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 3eabaaf5376..f277e4dc686 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 @@ -183,7 +183,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](../metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. * The Document referenced by [`ref`](../metadata.md#ref) * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md new file mode 100644 index 00000000000..9f1dc5d56eb --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md @@ -0,0 +1,271 @@ +# Rep Nomination + +## Description + +A Representative Nomination Document is created to opt +in as a Representative Voter for a specific Contest on a Brand/Campaign or Category. + +This Document is a kind of `Profile` that is primarily used to +help justify the Representatives Nomination to prospective delegators. + +The user must have registered as a Representative. +The presence of this document signifies the user's intent to participate in that +contest as a Representative. + +The document's structure is defined by the associated +Rep Nomination Form Template. +This allows an Admin to specify contest-specific requirements. + +The Representative can retract their nomination by using the `revoke` metadata to +revoke this Nomination document. + +It is an extension of all other profiles attached to the same Catalyst ID. + +Profiles themselves are intentionally general, however they may be +linked to a Brand/Campaign/Category via the template used by the profile. + +The payload of a profile is controlled by its template. + + + +```graphviz dot rep_nomination.dot.svg +{{ include_file('./../diagrams/rep_nomination.dot', indent=4) }} +``` + + + +### Validation + +* The signer MUST be a registered 'Representative'. +* The 'ref' metadata field MUST point to a valid 'Representative Profile' document. +* The 'parameters' metadata field MUST point to a valid 'Contest Parameters' document. +* The 'template' metadata field MUST point to a valid 'Representative Nomination Form Template' document. +* The payload MUST be valid against the [JSON schema][JSON Schema-2020-12] defined in the referenced template. +* Other rules may apply as defined by the Contest or other parameters which can + control who may validly nominate as a representative in a Contest. + +### Business Logic + +#### Front End + +* Allows a Representative to create or update their profile for a category. +* The Representative sets their status to 'active' to be discoverable for delegation. +* The Representative can set their status to 'revoked' to signal they are no longer participating in the category, without having to revoke the document. + +#### Back End + +* The backend MUST verify the signer is a 'Representative' and that all referenced documents exist. +* The system will only consider Representatives with an 'active' status as eligible for delegation. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `bf9abd97-5d1f-4429-8e80-740fea371a9c`,
`94579df1-a6dc-433b-a8e8-910c5dc2f0e3` | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a document with +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +The document version must always be >= the document ID. + +### [`ref`](../metadata.md#ref) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Rep Profile](rep_profile.md) | + +Reference to a Linked Document or Documents. +This is the primary hierarchical reference to a related document. + +If a reference is defined as required, there must be at least 1 reference specified. +Some documents allow multiple references, and they are documented as required. + +The document reference serves two purposes: + +1. It ensures that the document referenced by an ID/Version is not substituted. + In other words, that the document intended to be referenced, is actually referenced. +2. It Allows the document to be unambiguously located in decentralized storage systems. + +There can be any number of Document Locations in any reference. +The currently defined locations are: + +* `cid` : A [CBOR Encoded IPLD Content Identifier][CBOR-TAG-42] ( AKA an [IPFS CID][IPFS-CID] ). +* Others may be added when further storage mechanisms are defined. + +The document location does not guarantee that the document is actually stored. +It only defines that if it were stored, this is the identifier +that is required to retrieve it. +Therefore it is required that Document References +are unique and reproducible, given a documents contents. + +#### [`ref`](../metadata.md#ref) Validation + +The following must be true for a valid reference: + +* The Referenced Document **MUST** Exist +* Every value in the `document_locator` must consistently reference the exact same document. +* The `document_id` and `document_ver` **MUST** match the values in the referenced document. + +### [`template`](../metadata.md#template) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Rep Nomination Form Template](rep_nomination_form_template.md) | + +Reference to the template used to create and/or validate this document. + +#### [`template`](../metadata.md#template) Validation + +In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields, +The document payload is not valid if it does not validate completely against the referenced template. + +### [`revocations`](../metadata.md#revocations) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Version Revocations](../metadata.md#version-revocations) | + +A document may include a list of any prior versions which are considered to be revoked. +Only the revocation list in the latest version of the document applies. +Revoked documents are flagged as no longer valid, and should not be displayed. +As a special case, if the revocations are set to `true` then all versions of the document +are revoked, including the latest document. + +In this case, when the latest document is revoked, the payload may be empty. +Any older document that has [`revocations`](../metadata.md#revocations) set to `true` is always to be filtered +and its payload is to be assumed to be invalid. + +This allows for an entire document and any/all published versions to be revoked. +A new version of the document that is published after this, may reinstate prior +document versions, by not listing them as revoked. +However, any document where revocations was set `true` can never be reinstated. + +#### [`revocations`](../metadata.md#revocations) Validation + +If the field is `true` the payload may be absent or invalid. +Such documents may never be submitted. + +### [`parameters`](../metadata.md#parameters) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Contest Parameters](contest_parameters.md) | +| Linked Reference Metadata | [`template`](#template) | + +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, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. +* The Document referenced by [`template`](../metadata.md#template) + * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND + * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. + +## Payload + +The Representative's profile data for a specific contest. +Its structure is defined by the referenced template document. + +In the case of Revoking a nomination the payload is `nil`. + +## Signers + +The following User roles may sign documents of this type: + +* Representative + +New versions of this document may be published by: + +* author + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-06-19 | +| Authors | Alex Pozhylenkov | +| | Neil McAuliffe | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-06-19) + +* First Published Version + +[CBOR-TAG-42]: https://github.com/ipld/cid-cbor/ +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[IPFS-CID]: https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination_form_template.md new file mode 100644 index 00000000000..4391eefd6ca --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination_form_template.md @@ -0,0 +1,183 @@ +# Rep Nomination Form Template + +## Description + +A Rep Nomination Form Template defines both: + +* The data that is entered in the Form. +* Formatting hints for the collection of the data in a form. + +A Rep Nomination Form Template is a [JSON Schema][JSON Schema-2020-12] Document. + +Rep Nomination entry *SHOULD* use the hints when collecting +data defined by the Rep Nomination Form Template to provide a +consistent user interface. +It *CAN* also use those hints when re-displaying the full forms data. + +Alternatively a Rep Nomination Presentation Template can be used to +format the Rep Nomination data for presentation. + +The Rep Nomination Document is intentionally general, +however it may be linked to a brand/campaign or category +via the template used by the Rep Nomination. + +The payload of a Rep Nomination is controlled by its template. + + + +```graphviz dot rep_nomination_form_template.dot.svg +{{ include_file('./../diagrams/rep_nomination_form_template.dot', indent=4) }} +``` + + + +### Validation + +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. + +### Business Logic + +#### Front End + +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. + +#### Back End + +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. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +* [content type](../spec.md#content-type) = `application/schema+json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`bf9abd97-5d1f-4429-8e80-740fea371a9c`,
`94579df1-a6dc-433b-a8e8-910c5dc2f0e3` | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a document with +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +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 | [Contest Parameters](contest_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, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. + +## Payload + +[JSON Schema][JSON Schema-2020-12] document which defines the valid contents and +formatting hints for the collection of data for a +Rep Nomination Document. + +## Signers + +The following Admin roles may sign documents of this type: + +* Brand Admin + +New versions of this document may be published by: + +* author + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-05-30 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-04-04) + +* First Published Version + +#### 0.03 (2025-05-05) + +* Use generalized parameters. + +#### 0.04 (2025-05-05) + +* Generalize the Form Template definitions. + +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile.md b/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile.md new file mode 100644 index 00000000000..5115aa77b14 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile.md @@ -0,0 +1,211 @@ +# Rep Profile + +## Description + +A Rep Profile allows a representative voter to publish information +about themselves to help explain who they are and why someone should +consider delegating to them. + +It is an extension of all other profiles attached to the same Catalyst ID. + +Profiles themselves are intentionally general, however they may be +linked to a brand via the template used by the profile. + +The payload of a profile is controlled by its template. + + + +```graphviz dot rep_profile.dot.svg +{{ include_file('./../diagrams/rep_profile.dot', indent=4) }} +``` + + + +### Validation + +* The signer MUST be a registered 'Representative'. +* The payload MUST be valid against the [JSON schema][JSON Schema-2020-12] defined in the referenced +'Rep Profile Template'. + +### Business Logic + +#### Front End + +* Display and allow editing of the Representative's core profile fields. +* This profile serves as the central hub for a Representative's public identity. + +#### Back End + +* Validate Representative profile data against the referenced 'Rep Profile Template' and store/index it. +* This global profile is the foundational document referenced by all of the Rep's contest specific profiles. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `0f2c86a2-ffda-40b0-ad38-23709e1c10b3`,
`94579df1-a6dc-433b-a8e8-910c5dc2f0e3` | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a document with +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +The document version must always be >= the document ID. + +### [`template`](../metadata.md#template) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Rep Profile Form Template](rep_profile_form_template.md) | + +Reference to the template used to create and/or validate this document. + +#### [`template`](../metadata.md#template) Validation + +In addition to the validation performed for [Document Reference](../metadata.md#document-reference) type fields, +The document payload is not valid if it does not validate completely against the referenced template. + +### [`revocations`](../metadata.md#revocations) + + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Version Revocations](../metadata.md#version-revocations) | + +A document may include a list of any prior versions which are considered to be revoked. +Only the revocation list in the latest version of the document applies. +Revoked documents are flagged as no longer valid, and should not be displayed. +As a special case, if the revocations are set to `true` then all versions of the document +are revoked, including the latest document. + +In this case, when the latest document is revoked, the payload may be empty. +Any older document that has [`revocations`](../metadata.md#revocations) set to `true` is always to be filtered +and its payload is to be assumed to be invalid. + +This allows for an entire document and any/all published versions to be revoked. +A new version of the document that is published after this, may reinstate prior +document versions, by not listing them as revoked. +However, any document where revocations was set `true` can never be reinstated. + +#### [`revocations`](../metadata.md#revocations) Validation + +If the field is `true` the payload may be absent or invalid. +Such documents may never be submitted. + +### [`parameters`](../metadata.md#parameters) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Brand Parameters](brand_parameters.md) | +| Linked Reference Metadata | [`template`](#template) | + +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, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. +* The Document referenced by [`template`](../metadata.md#template) + * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND + * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. + +## Payload + +The Representative profile payload contains all Representative-specific fields. +Its structure is defined by the referenced Rep Profile Template. + +Must be valid according to the schema contained within the +[Document Reference](../metadata.md#document-reference) from the [`template`](../metadata.md#template) metadata. + +## Signers + +The following User roles may sign documents of this type: + +* Representative + +New versions of this document may be published by: + +* author + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-06-19 | +| Authors | Alex Pozhylenkov | +| | Neil McAuliffe | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-06-19) + +* First Published Version + +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile_form_template.md new file mode 100644 index 00000000000..71da52c0096 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile_form_template.md @@ -0,0 +1,183 @@ +# Rep Profile Form Template + +## Description + +A Rep Profile Form Template defines both: + +* The data that is entered in the Form. +* Formatting hints for the collection of the data in a form. + +A Rep Profile Form Template is a [JSON Schema][JSON Schema-2020-12] Document. + +Rep Profile entry *SHOULD* use the hints when collecting +data defined by the Rep Profile Form Template to provide a +consistent user interface. +It *CAN* also use those hints when re-displaying the full forms data. + +Alternatively a Rep Profile Presentation Template can be used to +format the Rep Profile data for presentation. + +The Rep Profile Document is intentionally general, +however it may be linked to a brand/campaign or category +via the template used by the Rep Profile. + +The payload of a Rep Profile is controlled by its template. + + + +```graphviz dot rep_profile_form_template.dot.svg +{{ include_file('./../diagrams/rep_profile_form_template.dot', indent=4) }} +``` + + + +### Validation + +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. + +### Business Logic + +#### Front End + +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. + +#### Back End + +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. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +* [content type](../spec.md#content-type) = `application/schema+json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`0f2c86a2-ffda-40b0-ad38-23709e1c10b3`,
`94579df1-a6dc-433b-a8e8-910c5dc2f0e3` | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a document with +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +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, or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. + +## Payload + +[JSON Schema][JSON Schema-2020-12] document which defines the valid contents and +formatting hints for the collection of data for a +Rep Profile Document. + +## Signers + +The following Admin roles may sign documents of this type: + +* Brand Admin + +New versions of this document may be published by: + +* author + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-05-30 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-04-04) + +* First Published Version + +#### 0.03 (2025-05-05) + +* Use generalized parameters. + +#### 0.04 (2025-05-05) + +* Generalize the Form Template definitions. + +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema-2020-12]: https://json-schema.org/draft/2020-12 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 diff --git a/docs/src/architecture/08_concepts/signed_doc/metadata.md b/docs/src/architecture/08_concepts/signed_doc/metadata.md index 3f0e676f077..15486704d3c 100644 --- a/docs/src/architecture/08_concepts/signed_doc/metadata.md +++ b/docs/src/architecture/08_concepts/signed_doc/metadata.md @@ -238,6 +238,10 @@ The document version must always be >= the document ID. | | [Category Parameters Form Template](./docs/category_parameters_form_template.md) | | | [Contest Parameters](./docs/contest_parameters.md) | | | [Contest Parameters Form Template](./docs/contest_parameters_form_template.md) | +| | [Rep Profile](./docs/rep_profile.md) | +| | [Rep Profile Form Template](./docs/rep_profile_form_template.md) | +| | [Rep Nomination](./docs/rep_nomination.md) | +| | [Rep Nomination Form Template](./docs/rep_nomination_form_template.md) | Reference to a Linked Document or Documents. This is the primary hierarchical reference to a related document. @@ -284,6 +288,8 @@ The following must be true for a valid reference: | | [Campaign Parameters Form Template](./docs/campaign_parameters_form_template.md) | | | [Category Parameters Form Template](./docs/category_parameters_form_template.md) | | | [Contest Parameters Form Template](./docs/contest_parameters_form_template.md) | +| | [Rep Profile Form Template](./docs/rep_profile_form_template.md) | +| | [Rep Nomination Form Template](./docs/rep_nomination_form_template.md) | Reference to the template used to create and/or validate this document. @@ -372,7 +378,16 @@ A reference to the Parameters Document this document lies under. 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. +[`parameters`](metadata.md#parameters) of the referencing document, or a parent of those [`parameters`](metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](./docs/contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. ### `chain` diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index aa6efe33233..e0c1b99e6c3 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -14,9 +14,14 @@ All Document Types are defined by composing these base document types: | Contest | `788ff4c6-d65a-451f-bb33-575fe056b411` | `37(h'788ff4c6d65a451fbb33575fe056b411')` | | FormTemplate | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | `37(h'0ce8ab3892584fbca62e7faa6e58318f')` | | ModerationAction | `a5d232b8-5e03-4117-9afd-be32b878fcdd` | `37(h'a5d232b85e0341179afdbe32b878fcdd')` | +| Nomination | `bf9abd97-5d1f-4429-8e80-740fea371a9c` | `37(h'bf9abd975d1f44298e80740fea371a9c')` | | Parameters | `60185874-7e13-407c-a06c-238ffe637ae6` | `37(h'601858747e13407ca06c238ffe637ae6')` | | PresentationTemplate | `cb99b9bd-681a-49d8-9836-89107c02e8ef` | `37(h'cb99b9bd681a49d8983689107c02e8ef')` | +| Profile | `0f2c86a2-ffda-40b0-ad38-23709e1c10b3` | `37(h'0f2c86a2ffda40b0ad3823709e1c10b3')` | | Proposal | `7808d2ba-d511-40af-84e8-c0d1625fdfdc` | `37(h'7808d2bad51140af84e8c0d1625fdfdc')` | +| RegisteredProposer | `7311c63b-95c6-402e-a258-f9bf622093eb` | `37(h'7311c63b95c6402ea258f9bf622093eb')` | +| RegisteredRep | `94579df1-a6dc-433b-a8e8-910c5dc2f0e3` | `37(h'94579df1a6dc433ba8e8910c5dc2f0e3')` | +| RegisteredUser | `ff4b7724-3db5-44cd-a433-78ba6d29505e` | `37(h'ff4b77243db544cda43378ba6d29505e')` | | SubmissionAction | `78927329-cfd9-4ea1-9c71-0e019b126a65` | `37(h'78927329cfd94ea19c710e019b126a65')` | ## Document Types @@ -26,15 +31,15 @@ All Defined Document Types | Document Type | Base Types | [CBOR][RFC8949] | | :--- | :--- | :--- | -| [Brand Parameters](./docs/brand_parameters.md) | Brand/Parameters | [37(h'ebcabeeb5bc54f9591e8cab8ca724172'),
37(h'601858747e13407ca06c238ffe637ae6')] | -| [Brand Parameters Form Template](./docs/brand_parameters_form_template.md) | Brand/Parameters/FormTemplate | [37(h'ebcabeeb5bc54f9591e8cab8ca724172'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'0ce8ab3892584fbca62e7faa6e58318f')] | -| [Campaign Parameters](./docs/campaign_parameters.md) | Campaign/Parameters | [37(h'5ef32d5df240462ca7a4ba4af221fa23'),
37(h'601858747e13407ca06c238ffe637ae6')] | -| [Campaign Parameters Form Template](./docs/campaign_parameters_form_template.md) | Campaign/Parameters/FormTemplate | [37(h'5ef32d5df240462ca7a4ba4af221fa23'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'0ce8ab3892584fbca62e7faa6e58318f')] | -| [Category Parameters](./docs/category_parameters.md) | Category/Parameters | [37(h'818938c331394daaafe6974c78488e95'),
37(h'601858747e13407ca06c238ffe637ae6')] | -| [Category Parameters Form Template](./docs/category_parameters_form_template.md) | Category/Parameters/FormTemplate | [37(h'818938c331394daaafe6974c78488e95'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'0ce8ab3892584fbca62e7faa6e58318f')] | +| [Brand Parameters](./docs/brand_parameters.md) | Parameters/Brand | [37(h'601858747e13407ca06c238ffe637ae6'),
37(h'ebcabeeb5bc54f9591e8cab8ca724172')] | +| [Brand Parameters Form Template](./docs/brand_parameters_form_template.md) | FormTemplate/Parameters/Brand | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'ebcabeeb5bc54f9591e8cab8ca724172')] | +| [Campaign Parameters](./docs/campaign_parameters.md) | Parameters/Campaign | [37(h'601858747e13407ca06c238ffe637ae6'),
37(h'5ef32d5df240462ca7a4ba4af221fa23')] | +| [Campaign Parameters Form Template](./docs/campaign_parameters_form_template.md) | FormTemplate/Parameters/Campaign | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'5ef32d5df240462ca7a4ba4af221fa23')] | +| [Category Parameters](./docs/category_parameters.md) | Parameters/Category | [37(h'601858747e13407ca06c238ffe637ae6'),
37(h'818938c331394daaafe6974c78488e95')] | +| [Category Parameters Form Template](./docs/category_parameters_form_template.md) | FormTemplate/Parameters/Category | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'818938c331394daaafe6974c78488e95')] | | [Comment Moderation Action](./docs/comment_moderation_action.md) | Action/Comment/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | -| [Contest Parameters](./docs/contest_parameters.md) | Contest/Parameters | [37(h'788ff4c6d65a451fbb33575fe056b411'),
37(h'601858747e13407ca06c238ffe637ae6')] | -| [Contest Parameters Form Template](./docs/contest_parameters_form_template.md) | Contest/Parameters/FormTemplate | [37(h'788ff4c6d65a451fbb33575fe056b411'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'0ce8ab3892584fbca62e7faa6e58318f')] | +| [Contest Parameters](./docs/contest_parameters.md) | Parameters/Contest | [37(h'601858747e13407ca06c238ffe637ae6'),
37(h'788ff4c6d65a451fbb33575fe056b411')] | +| [Contest Parameters Form Template](./docs/contest_parameters_form_template.md) | FormTemplate/Parameters/Contest | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'788ff4c6d65a451fbb33575fe056b411')] | | [Proposal](./docs/proposal.md) | Proposal | [37(h'7808d2bad51140af84e8c0d1625fdfdc')] | | [Proposal Comment](./docs/proposal_comment.md) | Comment/Proposal | [37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | | [Proposal Comment Form Template](./docs/proposal_comment_form_template.md) | FormTemplate/Comment/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | @@ -43,6 +48,10 @@ All Defined Document Types | [Proposal Moderation Action](./docs/proposal_moderation_action.md) | Action/Proposal/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | | [Proposal Presentation Template](./docs/proposal_presentation_template.md) | PresentationTemplate/Proposal | [37(h'cb99b9bd681a49d8983689107c02e8ef'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | | [Proposal Submission Action](./docs/proposal_submission_action.md) | Action/Proposal/SubmissionAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'78927329cfd94ea19c710e019b126a65')] | +| [Rep Nomination](./docs/rep_nomination.md) | Nomination/RegisteredRep | [37(h'bf9abd975d1f44298e80740fea371a9c'),
37(h'94579df1a6dc433ba8e8910c5dc2f0e3')] | +| [Rep Nomination Form Template](./docs/rep_nomination_form_template.md) | FormTemplate/Nomination/RegisteredRep | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'bf9abd975d1f44298e80740fea371a9c'),
37(h'94579df1a6dc433ba8e8910c5dc2f0e3')] | +| [Rep Profile](./docs/rep_profile.md) | Profile/RegisteredRep | [37(h'0f2c86a2ffda40b0ad3823709e1c10b3'),
37(h'94579df1a6dc433ba8e8910c5dc2f0e3')] | +| [Rep Profile Form Template](./docs/rep_profile_form_template.md) | FormTemplate/Profile/RegisteredRep | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'0f2c86a2ffda40b0ad3823709e1c10b3'),
37(h'94579df1a6dc433ba8e8910c5dc2f0e3')] | ## Document Relationship Hierarchy diff --git a/specs/definitions/signed_docs/docs/all.cue b/specs/definitions/signed_docs/docs/all.cue index 9c0d5e402ec..18cb52b2667 100644 --- a/specs/definitions/signed_docs/docs/all.cue +++ b/specs/definitions/signed_docs/docs/all.cue @@ -19,6 +19,11 @@ _allDocTypes: { Category: "818938c3-3139-4daa-afe6-974c78488e95" Contest: "788ff4c6-d65a-451f-bb33-575fe056b411" Parameters: "60185874-7e13-407c-a06c-238ffe637ae6" + RegisteredUser: "ff4b7724-3db5-44cd-a433-78ba6d29505e" + RegisteredRep: "94579df1-a6dc-433b-a8e8-910c5dc2f0e3" + RegisteredProposer: "7311c63b-95c6-402e-a258-f9bf622093eb" + Profile: "0f2c86a2-ffda-40b0-ad38-23709e1c10b3" + Nomination: "bf9abd97-5d1f-4429-8e80-740fea371a9c" } // Source of truth for ALL Document Types and their matching UUID's. @@ -67,40 +72,58 @@ _allDocs: { _allDocTypes["ModerationAction"], // On Moderation ] "Brand Parameters": [ - _allDocTypes["Brand"], - _allDocTypes["Parameters"], + _allDocTypes["Parameters"], // Parameters + _allDocTypes["Brand"], // Of a Brand ] "Brand Parameters Form Template": [ - _allDocTypes["Brand"], - _allDocTypes["Parameters"], - _allDocTypes["FormTemplate"], + _allDocTypes["FormTemplate"], // Form Template + _allDocTypes["Parameters"], // For Parameters + _allDocTypes["Brand"], // Of a Brand ] "Campaign Parameters": [ - _allDocTypes["Campaign"], - _allDocTypes["Parameters"], + _allDocTypes["Parameters"], // Parameters + _allDocTypes["Campaign"], // Of a Campaign ] "Campaign Parameters Form Template": [ - _allDocTypes["Campaign"], - _allDocTypes["Parameters"], - _allDocTypes["FormTemplate"], + _allDocTypes["FormTemplate"], // Form Template + _allDocTypes["Parameters"], // For Parameters + _allDocTypes["Campaign"], // Of a Campaign ] "Category Parameters": [ - _allDocTypes["Category"], - _allDocTypes["Parameters"], + _allDocTypes["Parameters"], // Parameters + _allDocTypes["Category"], // Of a Category ] "Category Parameters Form Template": [ - _allDocTypes["Category"], - _allDocTypes["Parameters"], - _allDocTypes["FormTemplate"], + _allDocTypes["FormTemplate"], // Form Template + _allDocTypes["Parameters"], // For Parameters + _allDocTypes["Category"], // Of a Category ] "Contest Parameters": [ - _allDocTypes["Contest"], - _allDocTypes["Parameters"], + _allDocTypes["Parameters"], // Parameters + _allDocTypes["Contest"], // Of a Contest ] "Contest Parameters Form Template": [ - _allDocTypes["Contest"], - _allDocTypes["Parameters"], - _allDocTypes["FormTemplate"], + _allDocTypes["FormTemplate"], // Form Template + _allDocTypes["Parameters"], // For Parameters + _allDocTypes["Contest"], // Of a Contest + ] + "Rep Profile": [ + _allDocTypes["Profile"], // Profile + _allDocTypes["RegisteredRep"], // Of a Registered Rep + ] + "Rep Profile Form Template": [ + _allDocTypes["FormTemplate"], // Form Template + _allDocTypes["Profile"], // For a Profile + _allDocTypes["RegisteredRep"], // Of a Registered Rep + ] + "Rep Nomination": [ + _allDocTypes["Nomination"], // Nomination + _allDocTypes["RegisteredRep"], // Of a Registered Rep + ] + "Rep Nomination Form Template": [ + _allDocTypes["FormTemplate"], // Form Template + _allDocTypes["Nomination"], // For a Nomination + _allDocTypes["RegisteredRep"], // Of a Registered Rep ] } diff --git a/specs/definitions/signed_docs/docs/generic_form_template.cue b/specs/definitions/signed_docs/docs/generic_form_template.cue index 2f5980c0a77..555d18fd3d0 100644 --- a/specs/definitions/signed_docs/docs/generic_form_template.cue +++ b/specs/definitions/signed_docs/docs/generic_form_template.cue @@ -30,12 +30,27 @@ _form_template_payload_description: """ {{ .doc }} Document. """ +// Used for documents that can link to any system parameter. _metadataFieldSystemParameters: #metadataField & { // Is the field required to be present. required: "yes" type: doc_clusters."System Parameters".docs } +// Used for documents that can only link to brand parameters. +_metadataFieldBrandParameters: #metadataField & { + // Is the field required to be present. + required: "yes" + type: ["Brand Parameters"] +} + +// Used for documents that can only link to contest parameters. +_metadataFieldContestParameters: #metadataField & { + // Is the field required to be present. + required: "yes" + type: "Contest Parameters" +} + #generic_form_template: #signedDocument & { description: _ diff --git a/specs/definitions/signed_docs/docs/generic_presentation_template.cue b/specs/definitions/signed_docs/docs/generic_presentation_template.cue index 20c2846d14d..dfd8a3d5bf9 100644 --- a/specs/definitions/signed_docs/docs/generic_presentation_template.cue +++ b/specs/definitions/signed_docs/docs/generic_presentation_template.cue @@ -31,7 +31,7 @@ _presentation_template_payload_description: """ 3. A Handlebars templated HTML or Markdown file data which defines the presentation. """ -_generic_presentation_template: #signedDocument & { +#generic_presentation_template: #signedDocument & { description: _ headers: "content type": value: "application/schema+json" diff --git a/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue b/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue index 6adceecbbb6..111988d4e16 100644 --- a/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue +++ b/specs/definitions/signed_docs/docs/proposal_comment_form_template.cue @@ -3,13 +3,11 @@ package signed_docs import "text/template" -_proposal_comment_form_data: doc: "Proposal Comment" +docs: "Proposal Comment Form Template": #generic_form_template & { + _data: doc: "Proposal Comment" -docs: #DocumentDefinitions & { - "Proposal Comment Form Template": #generic_form_template & { - description: template.Execute(_form_template_description, _proposal_comment_form_data) - metadata: parameters: _metadataFieldSystemParameters - payload: description: template.Execute(_form_template_payload_description, _proposal_comment_form_data) - versions: _generic_form_template_versions - } + description: template.Execute(_form_template_description, _data) + metadata: parameters: _metadataFieldSystemParameters + payload: description: template.Execute(_form_template_payload_description, _data) + versions: _generic_form_template_versions } diff --git a/specs/definitions/signed_docs/docs/proposal_comment_presentation_template.cue b/specs/definitions/signed_docs/docs/proposal_comment_presentation_template.cue index 8103ada69f7..44ce2fe1c35 100644 --- a/specs/definitions/signed_docs/docs/proposal_comment_presentation_template.cue +++ b/specs/definitions/signed_docs/docs/proposal_comment_presentation_template.cue @@ -3,11 +3,10 @@ package signed_docs import "text/template" -_proposal_comment_presentation_data: doc: "Proposal Comment" +docs: "Proposal Comment Presentation Template": #generic_presentation_template & { + _data: doc: "Proposal Comment" -docs: #DocumentDefinitions & { - "Proposal Comment Presentation Template": _generic_presentation_template - "Proposal Comment Presentation Template": description: template.Execute(_presentation_template_description, _proposal_comment_presentation_data) - "Proposal Comment Presentation Template": payload: description: template.Execute(_presentation_template_payload_description, _proposal_comment_presentation_data) - "Proposal Comment Presentation Template": versions: _generic_presentation_template_versions + description: template.Execute(_presentation_template_description, _data) + payload: description: template.Execute(_presentation_template_payload_description, _data) + versions: _generic_presentation_template_versions } diff --git a/specs/definitions/signed_docs/docs/proposal_form_template.cue b/specs/definitions/signed_docs/docs/proposal_form_template.cue index b91b9be612f..10b22301a8a 100644 --- a/specs/definitions/signed_docs/docs/proposal_form_template.cue +++ b/specs/definitions/signed_docs/docs/proposal_form_template.cue @@ -3,14 +3,11 @@ package signed_docs import "text/template" -_proposal_form_data: doc: "Proposal" +docs: "Proposal Form Template": #generic_form_template & { + _data: doc: "Proposal" -docs: #DocumentDefinitions & { - "Proposal Form Template": #generic_form_template & { - description: template.Execute(_form_template_description, _proposal_form_data) - metadata: parameters: _metadataFieldSystemParameters - payload: description: template.Execute(_form_template_payload_description, _proposal_form_data) - versions: _generic_form_template_versions - //metadata: template: type: "Proposal Presentation Template" - } + description: template.Execute(_form_template_description, _data) + metadata: parameters: _metadataFieldSystemParameters + payload: description: template.Execute(_form_template_payload_description, _data) + versions: _generic_form_template_versions } diff --git a/specs/definitions/signed_docs/docs/proposal_presentation_template.cue b/specs/definitions/signed_docs/docs/proposal_presentation_template.cue index 2cbd5610acc..dc40e50b01f 100644 --- a/specs/definitions/signed_docs/docs/proposal_presentation_template.cue +++ b/specs/definitions/signed_docs/docs/proposal_presentation_template.cue @@ -3,11 +3,10 @@ package signed_docs import "text/template" -_proposal_presentation_data: doc: "Proposal" +docs: "Proposal Presentation Template": #generic_presentation_template & { + _data: doc: "Proposal" -docs: #DocumentDefinitions & { - "Proposal Presentation Template": _generic_presentation_template - "Proposal Presentation Template": description: template.Execute(_presentation_template_description, _proposal_form_data) - "Proposal Presentation Template": payload: description: template.Execute(_presentation_template_payload_description, _proposal_form_data) - "Proposal Presentation Template": versions: _generic_presentation_template_versions + description: template.Execute(_presentation_template_description, _data) + payload: description: template.Execute(_presentation_template_payload_description, _data) + versions: _generic_presentation_template_versions } diff --git a/specs/definitions/signed_docs/docs/rep_nomination_form_template.cue b/specs/definitions/signed_docs/docs/rep_nomination_form_template.cue new file mode 100644 index 00000000000..b06c8f012ed --- /dev/null +++ b/specs/definitions/signed_docs/docs/rep_nomination_form_template.cue @@ -0,0 +1,14 @@ +// Representative Profile Form Template Document Definition +package signed_docs + +import "text/template" + +docs: "Rep Nomination Form Template": #generic_form_template & { + + _data: doc: "Rep Nomination" + + description: template.Execute(_form_template_description, _data) + metadata: parameters: _metadataFieldContestParameters + payload: description: template.Execute(_form_template_payload_description, _data) + versions: _generic_form_template_versions +} diff --git a/specs/definitions/signed_docs/docs/rep_nomintion.cue b/specs/definitions/signed_docs/docs/rep_nomintion.cue new file mode 100644 index 00000000000..8cbd7ab9bdc --- /dev/null +++ b/specs/definitions/signed_docs/docs/rep_nomintion.cue @@ -0,0 +1,101 @@ +package signed_docs + +// Proposal Document Definition + +docs: "Rep Nomination": { + description: """ + A Representative Nomination Document is created to opt + in as a Representative Voter for a specific Contest on a Brand/Campaign or Category. + + This Document is a kind of `Profile` that is primarily used to + help justify the Representatives Nomination to prospective delegators. + + The user must have registered as a Representative. + The presence of this document signifies the user's intent to participate in that + contest as a Representative. + + The document's structure is defined by the associated + Rep Nomination Form Template. + This allows an Admin to specify contest-specific requirements. + + The Representative can retract their nomination by using the `revoke` metadata to + revoke this Nomination document. + + It is an extension of all other profiles attached to the same Catalyst ID. + + Profiles themselves are intentionally general, however they may be + linked to a Brand/Campaign/Category via the template used by the profile. + + The payload of a profile is controlled by its template. + """ + + validation: """ + * The signer MUST be a registered 'Representative'. + * The 'ref' metadata field MUST point to a valid 'Representative Profile' document. + * The 'parameters' metadata field MUST point to a valid 'Contest Parameters' document. + * The 'template' metadata field MUST point to a valid 'Representative Nomination Form Template' document. + * The payload MUST be valid against the JSON schema defined in the referenced template. + * Other rules may apply as defined by the Contest or other parameters which can + control who may validly nominate as a representative in a Contest. + """ + + business_logic: { + + front_end: """ + * Allows a Representative to create or update their profile for a category. + * The Representative sets their status to 'active' to be discoverable for delegation. + * The Representative can set their status to 'revoked' to signal they are no longer participating in the category, without having to revoke the document. + """ + + back_end: """ + * The backend MUST verify the signer is a 'Representative' and that all referenced documents exist. + * The system will only consider Representatives with an 'active' status as eligible for delegation. + """ + } + headers: "content type": value: "application/json" + + metadata: { + ref: { + required: "yes" + type: "Rep Profile" + } + + template: { + required: "yes" + type: "Rep Nomination Form Template" + } + + revocations: required: "optional" + + parameters: _metadataFieldContestParameters + parameters: linked_refs: [ + "template", + ] + } + + payload: description: """ + The Representative's profile data for a specific contest. + Its structure is defined by the referenced template document. + + In the case of Revoking a nomination the payload is `nil`. + """ + + signers: roles: user: [ + "Representative", + ] + + authors: { + "Neil McAuliffe": "neil.mcauliffe@iohk.io" + "Steven Johnson": "steven.johnson@iohk.io" + } + + versions: [ + { + version: "0.01" + modified: "2025-06-19" + changes: """ + * First Published Version + """ + }, + ] +} diff --git a/specs/definitions/signed_docs/docs/rep_profile.cue b/specs/definitions/signed_docs/docs/rep_profile.cue new file mode 100644 index 00000000000..77181b22d75 --- /dev/null +++ b/specs/definitions/signed_docs/docs/rep_profile.cue @@ -0,0 +1,79 @@ +package signed_docs + +// Proposal Document Definition + +docs: "Rep Profile": { + description: """ + A Rep Profile allows a representative voter to publish information + about themselves to help explain who they are and why someone should + consider delegating to them. + + It is an extension of all other profiles attached to the same Catalyst ID. + + Profiles themselves are intentionally general, however they may be + linked to a brand via the template used by the profile. + + The payload of a profile is controlled by its template. + """ + + validation: """ + * The signer MUST be a registered 'Representative'. + * The payload MUST be valid against the JSON schema defined in the referenced + 'Rep Profile Template'. + """ + + business_logic: { + + front_end: """ + * Display and allow editing of the Representative's core profile fields. + * This profile serves as the central hub for a Representative's public identity. + """ + + back_end: """ + * Validate Representative profile data against the referenced 'Rep Profile Template' and store/index it. + * This global profile is the foundational document referenced by all of the Rep's contest specific profiles. + """ + } + headers: "content type": value: "application/json" + + metadata: { + template: { + required: "yes" + type: "Rep Profile Form Template" + } + + revocations: required: "optional" + + parameters: _metadataFieldBrandParameters + parameters: linked_refs: [ + "template", + ] + } + + payload: description: """ + The Representative profile payload contains all Representative-specific fields. + Its structure is defined by the referenced Rep Profile Template. + + Must be valid according to the schema contained within the + `Document Reference` from the `template` metadata. + """ + + signers: roles: user: [ + "Representative", + ] + + authors: { + "Neil McAuliffe": "neil.mcauliffe@iohk.io" + "Steven Johnson": "steven.johnson@iohk.io" + } + + versions: [ + { + version: "0.01" + modified: "2025-06-19" + changes: """ + * First Published Version + """ + }, + ] +} diff --git a/specs/definitions/signed_docs/docs/rep_profile_form_template.cue b/specs/definitions/signed_docs/docs/rep_profile_form_template.cue new file mode 100644 index 00000000000..82b72171146 --- /dev/null +++ b/specs/definitions/signed_docs/docs/rep_profile_form_template.cue @@ -0,0 +1,14 @@ +// Representative Profile Form Template Document Definition +package signed_docs + +import "text/template" + +docs: "Rep Profile Form Template": #generic_form_template & { + + _data: doc: "Rep Profile" + + description: template.Execute(_form_template_description, _data) + metadata: parameters: _metadataFieldBrandParameters + payload: description: template.Execute(_form_template_payload_description, _data) + versions: _generic_form_template_versions +} diff --git a/specs/definitions/signed_docs/metadata.cue b/specs/definitions/signed_docs/metadata.cue index cd631647e59..cf70c2d4433 100644 --- a/specs/definitions/signed_docs/metadata.cue +++ b/specs/definitions/signed_docs/metadata.cue @@ -249,16 +249,6 @@ _allMetadataNames: or([ """ } - parameters: { - description: "A reference to the Parameters Document this document lies under." - validation: """ - In addition to the validation performed for `Document Reference` type fields: - - * Any linked referenced document that includes a `parameters` metadata must match the - `parameters` of the referencing document. - """ - } - } // Note: we make all normally excluded fields optional at the global level, because they are globally optional @@ -272,8 +262,6 @@ metadata: headers: { reply: type: #commentDocNamesList section: required: "optional" collaborators: required: "optional" - parameters: required: "optional" - parameters: type: #parameterDocNamesList } // Preferred display order diff --git a/specs/definitions/signed_docs/metadata_parameters.cue b/specs/definitions/signed_docs/metadata_parameters.cue new file mode 100644 index 00000000000..caa269f88df --- /dev/null +++ b/specs/definitions/signed_docs/metadata_parameters.cue @@ -0,0 +1,54 @@ +// Signed Document Definitions +// +// Metadata Types and Constraints +package signed_docs + +import ( + "strings" +) + +_metadata: _parameters: { + _description: """ + A reference to the Parameters Document this document lies under. + """ + + _validation: """ + In addition to the validation performed for `Document Reference` type fields: + + * Any linked referenced document that includes a `parameters` metadata must match the + `parameters` of the referencing document, or a parent of those `parameters`. + + For example, a linked reference to `Contest Parameters` is transitively a reference to + the Parameters document it references, and each parameters document they reference + until the `Brand` parameters document is reached. + + The use case here is for Templates. + The profile template, or proposal templates could be defined at any of these + levels, and as long as they all refer to the same chain of parameters in the + hierarchy they are all valid. + """ +} + +#metadata: parameters: { + + description: string | *""" + \(_metadata._parameters._description) + """ + validation: string | *""" + \(_metadata._parameters._validation) + """ +} + +// List of all Parameters Docs (not templates or actions) +#parameterDocNamesList: [...string] & [ + for k, _ in _allDocs + if strings.Contains(k, "Parameter") && + !strings.Contains(k, "Template") && + !strings.Contains(k, "Action") {k}, +] + +// Top Level general documentation for Parameters Metadata. +metadata: headers: parameters: { + required: "optional" + type: #parameterDocNamesList +} diff --git a/specs/definitions/signed_docs/signed_doc.cue b/specs/definitions/signed_docs/signed_doc.cue index 30e1a214428..b0abbe2b908 100644 --- a/specs/definitions/signed_docs/signed_doc.cue +++ b/specs/definitions/signed_docs/signed_doc.cue @@ -97,14 +97,6 @@ _allDocNamesList: [...string] & [ !strings.Contains(k, "Action") {k}, ] -// List of all Parameters Docs (not templates or actions) -#parameterDocNamesList: [...string] & [ - for k, _ in _allDocs - if strings.Contains(k, "Parameter") && - !strings.Contains(k, "Template") && - !strings.Contains(k, "Action") {k}, -] - // List of all the document names we have defined. _allDocNames: or(_allDocNamesList) diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 6409e30a560..11d44bc971c 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -12,9 +12,14 @@ "Contest": "788ff4c6-d65a-451f-bb33-575fe056b411", "FormTemplate": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "ModerationAction": "a5d232b8-5e03-4117-9afd-be32b878fcdd", + "Nomination": "bf9abd97-5d1f-4429-8e80-740fea371a9c", "Parameters": "60185874-7e13-407c-a06c-238ffe637ae6", "PresentationTemplate": "cb99b9bd-681a-49d8-9836-89107c02e8ef", + "Profile": "0f2c86a2-ffda-40b0-ad38-23709e1c10b3", "Proposal": "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "RegisteredProposer": "7311c63b-95c6-402e-a258-f9bf622093eb", + "RegisteredRep": "94579df1-a6dc-433b-a8e8-910c5dc2f0e3", + "RegisteredUser": "ff4b7724-3db5-44cd-a433-78ba6d29505e", "SubmissionAction": "78927329-cfd9-4ea1-9c71-0e019b126a65" }, "cddlDefinitions": { @@ -425,7 +430,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -490,8 +495,8 @@ } }, "type": [ - "ebcabeeb-5bc5-4f95-91e8-cab8ca724172", - "60185874-7e13-407c-a06c-238ffe637ae6" + "60185874-7e13-407c-a06c-238ffe637ae6", + "ebcabeeb-5bc5-4f95-91e8-cab8ca724172" ], "validation": "No extra validation defined.", "versions": [ @@ -551,7 +556,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -612,9 +617,9 @@ } }, "type": [ - "ebcabeeb-5bc5-4f95-91e8-cab8ca724172", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "60185874-7e13-407c-a06c-238ffe637ae6", - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + "ebcabeeb-5bc5-4f95-91e8-cab8ca724172" ], "versions": [ { @@ -684,7 +689,7 @@ "multiple": false, "required": "yes", "type": "Brand Parameters", - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -749,8 +754,8 @@ } }, "type": [ - "5ef32d5d-f240-462c-a7a4-ba4af221fa23", - "60185874-7e13-407c-a06c-238ffe637ae6" + "60185874-7e13-407c-a06c-238ffe637ae6", + "5ef32d5d-f240-462c-a7a4-ba4af221fa23" ], "validation": "The Campaign Parameters Document *MUST* be linked through `parameters` to \nits Brand Parameters Document.", "versions": [ @@ -810,7 +815,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -871,9 +876,9 @@ } }, "type": [ - "5ef32d5d-f240-462c-a7a4-ba4af221fa23", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "60185874-7e13-407c-a06c-238ffe637ae6", - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + "5ef32d5d-f240-462c-a7a4-ba4af221fa23" ], "versions": [ { @@ -943,7 +948,7 @@ "multiple": false, "required": "yes", "type": "Campaign Parameters", - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1008,8 +1013,8 @@ } }, "type": [ - "818938c3-3139-4daa-afe6-974c78488e95", - "60185874-7e13-407c-a06c-238ffe637ae6" + "60185874-7e13-407c-a06c-238ffe637ae6", + "818938c3-3139-4daa-afe6-974c78488e95" ], "validation": "The Category Parameters Document *MUST* be linked through `parameters` to \nits Campaign Parameters Document.", "versions": [ @@ -1069,7 +1074,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1130,9 +1135,9 @@ } }, "type": [ - "818938c3-3139-4daa-afe6-974c78488e95", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "60185874-7e13-407c-a06c-238ffe637ae6", - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + "818938c3-3139-4daa-afe6-974c78488e95" ], "versions": [ { @@ -1196,7 +1201,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1324,7 +1329,7 @@ "Campaign Parameters", "Category 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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1389,8 +1394,8 @@ } }, "type": [ - "788ff4c6-d65a-451f-bb33-575fe056b411", - "60185874-7e13-407c-a06c-238ffe637ae6" + "60185874-7e13-407c-a06c-238ffe637ae6", + "788ff4c6-d65a-451f-bb33-575fe056b411" ], "validation": "The Contest Parameters Document *MUST* be linked through `parameters` to \nits Brand/Campaign/Category Parameters Document.", "versions": [ @@ -1450,7 +1455,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1511,9 +1516,9 @@ } }, "type": [ - "788ff4c6-d65a-451f-bb33-575fe056b411", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "60185874-7e13-407c-a06c-238ffe637ae6", - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + "788ff4c6-d65a-451f-bb33-575fe056b411" ], "versions": [ { @@ -1592,7 +1597,7 @@ "Campaign Parameters", "Category 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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1730,7 +1735,7 @@ "Campaign Parameters", "Category 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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1867,7 +1872,7 @@ "Campaign Parameters", "Category 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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2001,7 +2006,7 @@ "Campaign Parameters", "Category 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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2126,7 +2131,7 @@ "Campaign Parameters", "Category 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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2252,7 +2257,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2375,7 +2380,7 @@ "Campaign Parameters", "Category 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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2505,7 +2510,7 @@ "Campaign Parameters", "Category 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." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2648,6 +2653,535 @@ "version": "0.03" } ] + }, + "Rep Nomination": { + "authors": { + "Neil McAuliffe": "neil.mcauliffe@iohk.io", + "Steven Johnson": "steven.johnson@iohk.io" + }, + "business_logic": { + "back_end": "* The backend MUST verify the signer is a 'Representative' and that all referenced documents exist.\n* The system will only consider Representatives with an 'active' status as eligible for delegation.", + "front_end": "* Allows a Representative to create or update their profile for a category.\n* The Representative sets their status to 'active' to be discoverable for delegation.\n* The Representative can set their status to 'revoked' to signal they are no longer participating in the category, without having to revoke the document." + }, + "description": "A Representative Nomination Document is created to opt\nin as a Representative Voter for a specific Contest on a Brand/Campaign or Category.\n\nThis Document is a kind of `Profile` that is primarily used to\nhelp justify the Representatives Nomination to prospective delegators.\n\nThe user must have registered as a Representative.\nThe presence of this document signifies the user's intent to participate in that \ncontest as a Representative.\n\nThe document's structure is defined by the associated \nRep Nomination Form Template.\nThis allows an Admin to specify contest-specific requirements.\n\nThe Representative can retract their nomination by using the `revoke` metadata to\nrevoke this Nomination document.\n\nIt is an extension of all other profiles attached to the same Catalyst ID.\n\nProfiles themselves are intentionally general, however they may be\nlinked to a Brand/Campaign/Category via the template used by the profile.\n\nThe payload of a profile is controlled by its template.", + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": "application/json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "excluded", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "linked_refs": [ + "template" + ], + "multiple": false, + "required": "yes", + "type": "Contest Parameters", + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Rep Profile", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "optional", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "excluded", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Rep Nomination Form Template", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "notes": [], + "payload": { + "description": "The Representative's profile data for a specific contest.\nIts structure is defined by the referenced template document.\n\nIn the case of Revoking a nomination the payload is `nil`." + }, + "signers": { + "roles": { + "user": [ + "Representative" + ] + }, + "update": { + "author": true + } + }, + "type": [ + "bf9abd97-5d1f-4429-8e80-740fea371a9c", + "94579df1-a6dc-433b-a8e8-910c5dc2f0e3" + ], + "validation": "* The signer MUST be a registered 'Representative'.\n* The 'ref' metadata field MUST point to a valid 'Representative Profile' document.\n* The 'parameters' metadata field MUST point to a valid 'Contest Parameters' document.\n* The 'template' metadata field MUST point to a valid 'Representative Nomination Form Template' document.\n* The payload MUST be valid against the JSON schema defined in the referenced template.\n* Other rules may apply as defined by the Contest or other parameters which can\n\tcontrol who may validly nominate as a representative in a Contest.", + "versions": [ + { + "changes": "* First Published Version", + "modified": "2025-06-19", + "version": "0.01" + } + ] + }, + "Rep Nomination Form Template": { + "authors": {}, + "description": "A Rep Nomination Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Rep Nomination Form Template is a JSON Schema Document.\n\nRep Nomination entry *SHOULD* use the hints when collecting \ndata defined by the Rep Nomination Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Rep Nomination Presentation Template can be used to\nformat the Rep Nomination data for presentation.\n\nThe Rep Nomination Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Rep Nomination.\n\nThe payload of a Rep Nomination is controlled by its template.", + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": "application/schema+json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "excluded", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Contest Parameters", + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "required": "excluded", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "excluded", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "excluded", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "notes": [], + "payload": { + "description": "JSON Schema document which defines the valid contents and \nformatting hints for the collection of data for a \nRep Nomination Document." + }, + "signers": { + "roles": { + "admin": [ + "Brand Admin" + ], + "user": [] + }, + "update": { + "author": true + } + }, + "type": [ + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "bf9abd97-5d1f-4429-8e80-740fea371a9c", + "94579df1-a6dc-433b-a8e8-910c5dc2f0e3" + ], + "versions": [ + { + "changes": "* First Published Version", + "modified": "2025-04-04", + "version": "0.01" + }, + { + "changes": "* Use generalized parameters.", + "modified": "2025-05-05", + "version": "0.03" + }, + { + "changes": "* Generalize the Form Template definitions.", + "modified": "2025-05-05", + "version": "0.04" + } + ] + }, + "Rep Profile": { + "authors": { + "Neil McAuliffe": "neil.mcauliffe@iohk.io", + "Steven Johnson": "steven.johnson@iohk.io" + }, + "business_logic": { + "back_end": "* Validate Representative profile data against the referenced 'Rep Profile Template' and store/index it.\n* This global profile is the foundational document referenced by all of the Rep's contest specific profiles.", + "front_end": "* Display and allow editing of the Representative's core profile fields.\n* This profile serves as the central hub for a Representative's public identity." + }, + "description": "A Rep Profile allows a representative voter to publish information\nabout themselves to help explain who they are and why someone should\nconsider delegating to them.\n\nIt is an extension of all other profiles attached to the same Catalyst ID.\n\nProfiles themselves are intentionally general, however they may be\nlinked to a brand via the template used by the profile.\n\nThe payload of a profile is controlled by its template.", + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": "application/json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "excluded", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "linked_refs": [ + "template" + ], + "multiple": false, + "required": "yes", + "type": [ + "Brand Parameters" + ], + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "required": "excluded", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "optional", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "excluded", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Rep Profile Form Template", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "notes": [], + "payload": { + "description": "The Representative profile payload contains all Representative-specific fields.\nIts structure is defined by the referenced Rep Profile Template.\n\nMust be valid according to the schema contained within the \n`Document Reference` from the `template` metadata." + }, + "signers": { + "roles": { + "user": [ + "Representative" + ] + }, + "update": { + "author": true + } + }, + "type": [ + "0f2c86a2-ffda-40b0-ad38-23709e1c10b3", + "94579df1-a6dc-433b-a8e8-910c5dc2f0e3" + ], + "validation": "* The signer MUST be a registered 'Representative'.\n* The payload MUST be valid against the JSON schema defined in the referenced \n'Rep Profile Template'.", + "versions": [ + { + "changes": "* First Published Version", + "modified": "2025-06-19", + "version": "0.01" + } + ] + }, + "Rep Profile Form Template": { + "authors": {}, + "description": "A Rep Profile Form Template defines both:\n\n* The data that is entered in the Form.\n* Formatting hints for the collection of the data in a form.\n\nA Rep Profile Form Template is a JSON Schema Document.\n\nRep Profile entry *SHOULD* use the hints when collecting \ndata defined by the Rep Profile Form Template to provide a \nconsistent user interface.\nIt *CAN* also use those hints when re-displaying the full forms data.\n\nAlternatively a Rep Profile Presentation Template can be used to\nformat the Rep Profile data for presentation.\n\nThe Rep Profile Document is intentionally general, \nhowever it may be linked to a brand/campaign or category \nvia the template used by the Rep Profile.\n\nThe payload of a Rep Profile is controlled by its template.", + "headers": { + "content type": { + "coseLabel": 3, + "description": "Media Type/s allowed in the Payload", + "format": "Media Type", + "required": "yes", + "value": "application/schema+json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload.\nIf no compression or encoding is used, then this field must not be present.", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "excluded", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": [ + "Brand Parameters" + ], + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "required": "excluded", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "excluded", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "excluded", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "notes": [], + "payload": { + "description": "JSON Schema document which defines the valid contents and \nformatting hints for the collection of data for a \nRep Profile Document." + }, + "signers": { + "roles": { + "admin": [ + "Brand Admin" + ], + "user": [] + }, + "update": { + "author": true + } + }, + "type": [ + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "0f2c86a2-ffda-40b0-ad38-23709e1c10b3", + "94579df1-a6dc-433b-a8e8-910c5dc2f0e3" + ], + "versions": [ + { + "changes": "* First Published Version", + "modified": "2025-04-04", + "version": "0.01" + }, + { + "changes": "* Use generalized parameters.", + "modified": "2025-05-05", + "version": "0.03" + }, + { + "changes": "* Generalize the Form Template definitions.", + "modified": "2025-05-05", + "version": "0.04" + } + ] } }, "documentation": { @@ -3941,7 +4475,7 @@ "Category Parameters", "Contest Parameters" ], - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document." + "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -3966,7 +4500,11 @@ "Category Parameters", "Category Parameters Form Template", "Contest Parameters", - "Contest Parameters Form Template" + "Contest Parameters Form Template", + "Rep Profile", + "Rep Profile Form Template", + "Rep Nomination", + "Rep Nomination Form Template" ], "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, @@ -4005,7 +4543,9 @@ "Brand Parameters Form Template", "Campaign Parameters Form Template", "Category Parameters Form Template", - "Contest Parameters Form Template" + "Contest Parameters Form Template", + "Rep Profile Form Template", + "Rep Nomination Form Template" ], "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." }, From 64c9e4e480019d95dca1323b49d13d0565de9635 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Tue, 24 Jun 2025 12:49:03 +0700 Subject: [PATCH 30/42] feat(docs): Add Rep Profiles, Nominations and Delegations documents --- .../08_concepts/signed_doc/diagrams/all.dot | 269 +++++++++++------- .../diagrams/contest_delegation.dot | 113 ++++++++ .../diagrams/contest_parameters.dot | 16 ++ .../signed_doc/diagrams/rep_nomination.dot | 16 ++ .../signed_doc/docs/campaign_parameters.md | 3 +- .../signed_doc/docs/category_parameters.md | 3 +- .../signed_doc/docs/contest_delegation.md | 230 +++++++++++++++ .../signed_doc/docs/contest_parameters.md | 3 +- .../08_concepts/signed_doc/docs/proposal.md | 4 +- .../signed_doc/docs/proposal_comment.md | 5 +- .../docs/proposal_comment_form_template.md | 3 +- .../proposal_comment_presentation_template.md | 3 +- .../signed_doc/docs/proposal_form_template.md | 3 +- .../docs/proposal_presentation_template.md | 3 +- .../docs/proposal_submission_action.md | 4 +- .../signed_doc/docs/rep_nomination.md | 31 +- .../docs/rep_nomination_form_template.md | 3 +- .../signed_doc/docs/rep_profile.md | 4 +- .../docs/rep_profile_form_template.md | 3 +- .../08_concepts/signed_doc/metadata.md | 4 +- .../08_concepts/signed_doc/types.md | 2 + specs/definitions/signed_docs/docs/all.cue | 5 + .../signed_docs/docs/contest_delegation.cue | 82 ++++++ .../signed_docs/docs/rep_nomintion.cue | 31 +- .../signed_docs/metadata_parameters.cue | 3 +- specs/definitions/signed_docs/payload.cue | 18 +- specs/definitions/signed_docs/signed_doc.cue | 6 +- .../packages/spec/src/spec/document.py | 4 +- .../packages/spec/src/spec/metadata.py | 1 + .../packages/spec/src/spec/payload.py | 8 + .../src/docs/doc_relationship_diagrams.py | 5 +- specs/generators/src/docs/docs_page_md.py | 4 + specs/signed_doc.json | 167 +++++++++-- 33 files changed, 901 insertions(+), 158 deletions(-) create mode 100644 docs/src/architecture/08_concepts/signed_doc/diagrams/contest_delegation.dot create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md create mode 100644 specs/definitions/signed_docs/docs/contest_delegation.cue 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 2dfce1089b4..63039cf1e53 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/all.dot @@ -357,13 +357,13 @@ digraph "All" { ]; - "Contest Parameters Form Template" [ - id="Contest Parameters Form Template"; + "Rep Nomination" [ + id="Rep Nomination"; label=< - @@ -371,7 +371,7 @@ digraph "All" {
- Contest Parameters Form Template + + Rep Nomination
- +
content typeapplication/schema+jsonapplication/json
@@ -381,7 +381,7 @@ digraph "All" { - +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
788ff4c6-d65a-451f-bb33-575fe056b411
bf9abd97-5d1f-4429-8e80-740fea371a9c
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
@@ -406,6 +406,46 @@ digraph "All" { + + + + + + + +
refRep Profile
+ + + + + + + + + +
templateRep Nomination Form Template
+ + + + + + + + + +
revocationsVersion Revocations
+ + + + + + + + + +
parametersContest Parameters
+ + > @@ -507,6 +547,126 @@ digraph "All" { ]; + "Contest Delegation" [ + id="Contest Delegation"; + label=< + + + + + + + + + + + + + + + + + + + + +
+ Contest Delegation +
+ + + + + +
type764f17fb-cc50-4979-b14a-b213dbac5994
788ff4c6-d65a-451f-bb33-575fe056b411
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
refRep Nomination
+
+ + + + + +
parametersContest Parameters
+
+ > + ]; + + + "Contest Parameters Form Template" [ + id="Contest Parameters Form Template"; + label=< + + + + + + + + + + + + + + + + + +
+ Contest Parameters Form Template +
+ + + + + +
content typeapplication/schema+json
+
+ + + + + +
type0ce8ab38-9258-4fbc-a62e-7faa6e58318f
60185874-7e13-407c-a06c-238ffe637ae6
788ff4c6-d65a-451f-bb33-575fe056b411
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ > + ]; + + "Proposal Form Template" [ id="Proposal Form Template"; label=< @@ -1152,101 +1312,6 @@ digraph "All" { ]; - "Rep Nomination" [ - id="Rep Nomination"; - label=< - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Rep Nomination -
- - - - - -
content typeapplication/json
-
- - - - - -
typebf9abd97-5d1f-4429-8e80-740fea371a9c
94579df1-a6dc-433b-a8e8-910c5dc2f0e3
-
- - - - - -
idDocument Id
-
- - - - - -
verDocument Ver
-
- - - - - -
refRep Profile
-
- - - - - -
templateRep Nomination Form Template
-
- - - - - -
revocationsVersion Revocations
-
- - - - - -
parametersContest Parameters
-
- > - ]; - - "Rep Profile Form Template" [ id="Rep Profile Form Template"; label=< @@ -1599,6 +1664,8 @@ digraph "All" { "Category Parameters":"template":e -> "Category Parameters Form Template":"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="*"] + "Contest Delegation":"ref":e -> "Rep Nomination":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Contest Delegation":"parameters":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Contest Parameters":"template":e -> "Contest Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Contest Parameters":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] "Proposal":"template":e -> "Proposal Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_delegation.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_delegation.dot new file mode 100644 index 00000000000..e271581e8c0 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_delegation.dot @@ -0,0 +1,113 @@ +digraph "Contest Delegation" { + rankdir="LR" + graph [fontname="helvetica", fontsize="32", fontcolor="#29235c", bgcolor="white"]; + node [penwidth="0", margin="0", fontname="helvetica", fontsize="32", fontcolor="#29235c"]; + edge [fontname="helvetica", fontsize="32", fontcolor="red", color="#29235c"]; + + labelloc="t" + label="Contest Delegation Document +Relationships" + fontcolor="#1d71b8" + fontsize=50 + compound=true + + + + "Rep Nomination" [ + id="Rep Nomination"; + label=< + + + + + +
+ Rep Nomination +
+ > + ]; + + + "Contest Parameters" [ + id="Contest Parameters"; + label=< + + + + + +
+ Contest Parameters +
+ > + ]; + + + "Contest Delegation" [ + id="Contest Delegation"; + label=< + + + + + + + + + + + + + + + + + + + + +
+ Contest Delegation +
+ + + + + +
type764f17fb-cc50-4979-b14a-b213dbac5994
788ff4c6-d65a-451f-bb33-575fe056b411
+
+ + + + + +
idDocument Id
+
+ + + + + +
verDocument Ver
+
+ + + + + +
refRep Nomination
+
+ + + + + +
parametersContest Parameters
+
+ > + ]; + + + "Contest Delegation":"ref":e -> "Rep Nomination":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Contest Delegation":"parameters":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] +} diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot index 81160f952b9..08485598c4c 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/contest_parameters.dot @@ -123,6 +123,21 @@ Relationships" ]; + "Contest Delegation" [ + id="Contest Delegation"; + label=< + + + + + +
+ Contest Delegation +
+ > + ]; + + "Rep Nomination" [ id="Rep Nomination"; label=< @@ -206,6 +221,7 @@ Relationships" "Contest Parameters":"template":e -> "Contest Parameters Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Contest Parameters":"parameters":e -> "Brand Parameters" [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*", lhead="cluster_system_parameters"] + "Contest Delegation":"title":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Rep Nomination":"title":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Rep Nomination Form Template":"title":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } diff --git a/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination.dot b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination.dot index 9bf0efefb11..bd83b20155c 100644 --- a/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination.dot +++ b/docs/src/architecture/08_concepts/signed_doc/diagrams/rep_nomination.dot @@ -153,7 +153,23 @@ Relationships" ]; + "Contest Delegation" [ + id="Contest Delegation"; + label=< + + + + + +
+ Contest Delegation +
+ > + ]; + + "Rep Nomination":"ref":e -> "Rep Profile":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Rep Nomination":"template":e -> "Rep Nomination Form Template":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] "Rep Nomination":"parameters":e -> "Contest Parameters":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] + "Contest Delegation":"title":e -> "Rep Nomination":"title":w [dir=forward, penwidth=6, color="#29235c", headlabel="1", taillabel="*"] } 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 51d82900edb..2202e9b9ec4 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 @@ -188,7 +188,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference 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 200be96a205..c5ece3413a9 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 @@ -188,7 +188,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md new file mode 100644 index 00000000000..ff96869665b --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md @@ -0,0 +1,230 @@ +# Contest Delegation + +## Description + +Delegation by a Registered User to a Representative for +a contest. + +This delegation allows votes cast by the Representative +to use the voting power of the delegating User, in addition +to their own personal voting power and that of all other Users +who delegate to the same Representative. + +Delegation is for a specific Contest. +Multiple Delegations must be published if there are multiple +Contests within a Brand/Campaign or Category. + +This is because different Contests may have different +rules. And not all Representatives will choose to nominate +for every Contest. + + + +```graphviz dot contest_delegation.dot.svg +{{ include_file('./../diagrams/contest_delegation.dot', indent=4) }} +``` + + + +### Validation + +* The [`parameters`](../metadata.md#parameters) metadata *MUST* point to the same Contest as the + Nomination of the Representative. +* The 'ref' metadata field MUST point to a valid 'Representative Nomination'. +* The payload MUST be nil. + +A Representative *MUST* Delegate to their latest Nomination for a Category, +otherwise their Nomination is invalid. + +This is because Delegation points to a *SPECIFIC* Nomination, and it +*MUST* be the latest for the Representative on the Contest. +As the Nomination contains information that the User relies on +when choosing to delegate, changing that information could have a +real and detrimental result in the Delegation choice. +Therefore, for a Delegation to be valid, it *MUST* point to the +latest Nomination for a Representative. + +### Business Logic + +#### Front End + +* Allows a voter to select a Representative from a list of eligible candidates for a category. +* The voter signs this document to confirm their delegation choice. + +#### Back End + +* Verifies that the voter and Representative are valid and registered for the category. +* Records the delegation of voting power from the voter to the Representative. + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +No Headers are defined for this document. + +## Metadata + +### [`type`](../metadata.md#type) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `764f17fb-cc50-4979-b14a-b213dbac5994`,
`788ff4c6-d65a-451f-bb33-575fe056b411` | + +The document TYPE. + +#### [`type`](../metadata.md#type) Validation + +**MUST** be a known document type. + +### [`id`](../metadata.md#id) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Id](../metadata.md#document-id) | + +Document ID, created the first time the document is created. +This must be a properly created [UUIDv7][RFC9562-V7] which contains the +timestamp of when the document was created. + +#### [`id`](../metadata.md#id) Validation + +IF [`ver`](../metadata.md#ver) does not == [`id`](../metadata.md#id) then a document with +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) being equal *MUST* exist. + +### [`ver`](../metadata.md#ver) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Ver](../metadata.md#document-ver) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +[`ver`](../metadata.md#ver) represents new versions of the same document as it changes over time. + +#### [`ver`](../metadata.md#ver) Validation + +The document version must always be >= the document ID. + +### [`ref`](../metadata.md#ref) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Rep Nomination](rep_nomination.md) | + +Reference to a Linked Document or Documents. +This is the primary hierarchical reference to a related document. + +If a reference is defined as required, there must be at least 1 reference specified. +Some documents allow multiple references, and they are documented as required. + +The document reference serves two purposes: + +1. It ensures that the document referenced by an ID/Version is not substituted. + In other words, that the document intended to be referenced, is actually referenced. +2. It Allows the document to be unambiguously located in decentralized storage systems. + +There can be any number of Document Locations in any reference. +The currently defined locations are: + +* `cid` : A [CBOR Encoded IPLD Content Identifier][CBOR-TAG-42] ( AKA an [IPFS CID][IPFS-CID] ). +* Others may be added when further storage mechanisms are defined. + +The document location does not guarantee that the document is actually stored. +It only defines that if it were stored, this is the identifier +that is required to retrieve it. +Therefore it is required that Document References +are unique and reproducible, given a documents contents. + +#### [`ref`](../metadata.md#ref) Validation + +The following must be true for a valid reference: + +* The Referenced Document **MUST** Exist +* Every value in the `document_locator` must consistently reference the exact same document. +* The `document_id` and `document_ver` **MUST** match the values in the referenced document. + +### [`parameters`](../metadata.md#parameters) + + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Contest Parameters](contest_parameters.md) | +| Linked Reference Metadata | [`ref`](#ref) | + +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, +or a parent of those [`parameters`](../metadata.md#parameters). + +For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to +the Parameters document it references, and each parameters document they reference +until the `Brand` parameters document is reached. + +The use case here is for Templates. +The profile template, or proposal templates could be defined at any of these +levels, and as long as they all refer to the same chain of parameters in the +hierarchy they are all valid. + +* The Document referenced by [`ref`](../metadata.md#ref) + * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND + * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. + +## Payload + + A minimal payload indicating the intended status of the delegation. + 'active' creates or affirms the delegation. + 'revoked' withdraws the delegation. + +This document has no payload. +It must be encoded as a [CBOR][RFC8949] `null (0xf6)`. + + +## Signers + +The following User roles may sign documents of this type: + +* Registered + +New versions of this document may be published by: + +* author + +## Copyright + +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-06-19 | +| Authors | Alex Pozhylenkov | +| | Neil McAuliffe | +| | Steven Johnson | + +### Changelog + +#### 0.01 (2025-06-19) + +* First Published Version + +[CBOR-TAG-42]: https://github.com/ipld/cid-cbor/ +[RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[IPFS-CID]: https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 +[RFC8949]: https://www.rfc-editor.org/rfc/rfc8949.html diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md index 8d493ec06b9..ef506039263 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_parameters.md @@ -190,7 +190,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference 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 96cd451e873..964e4120b31 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md @@ -199,7 +199,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference @@ -209,6 +210,7 @@ The use case here is for Templates. The profile template, or proposal templates could be defined at any of these levels, and as long as they all refer to the same chain of parameters in the hierarchy they are all valid. + * The Document referenced by [`template`](../metadata.md#template) * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. 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 385dabe07b5..61a0e724673 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 @@ -235,7 +235,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference @@ -245,9 +246,11 @@ The use case here is for Templates. The profile template, or proposal templates could be defined at any of these levels, and as long as they all refer to the same chain of parameters in the hierarchy they are all valid. + * The Document referenced by [`ref`](../metadata.md#ref) * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. + * The Document referenced by [`template`](../metadata.md#template) * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md index daf9dc23f0f..944ba4e4f45 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_form_template.md @@ -128,7 +128,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md index 01bdf0051f5..e39ad021eef 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_presentation_template.md @@ -125,7 +125,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md index 22818dd18c1..20b266c6519 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_form_template.md @@ -128,7 +128,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md index 9d0d6f90ca8..7080b8204bb 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_presentation_template.md @@ -125,7 +125,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference 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 f277e4dc686..b512a5e41c0 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 @@ -183,7 +183,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference @@ -193,6 +194,7 @@ The use case here is for Templates. The profile template, or proposal templates could be defined at any of these levels, and as long as they all refer to the same chain of parameters in the hierarchy they are all valid. + * The Document referenced by [`ref`](../metadata.md#ref) * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md index 9f1dc5d56eb..08b14f1773e 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination.md @@ -44,18 +44,41 @@ The payload of a profile is controlled by its template. * Other rules may apply as defined by the Contest or other parameters which can control who may validly nominate as a representative in a Contest. +No Nomination is valid unless the latest Contest Delegation of the Delegate +refers to their own Nomination. +This requires that Nominating is a two step process: + +1. Post the Nomination Document. +2. Post a Contest Delegation delegating to the new Nomination Document. + +Updating the Nomination Document will invalidate all Nominations to the +Representative. + +This is because Delegation points to a *SPECIFIC* Nomination, and it +*MUST* be the latest for the Representative on the Contest. +As the Nomination contains information that the User relies on +when choosing to delegate, changing that information could have a +real and detrimental result in the Delegation choice. +Therefore, for a Delegation to be valid, it *MUST* point to the +latest Nomination for a Representative. + ### Business Logic #### Front End * Allows a Representative to create or update their profile for a category. * The Representative sets their status to 'active' to be discoverable for delegation. -* The Representative can set their status to 'revoked' to signal they are no longer participating in the category, without having to revoke the document. +* The Representative `revokes` the Nomination to signal they are no longer + participating in the category. +* Nominations are not valid if the latest Delegation by the Representative does NOT + reference their latest Nomination. #### Back End * The backend MUST verify the signer is a 'Representative' and that all referenced documents exist. -* The system will only consider Representatives with an 'active' status as eligible for delegation. +* The system will only consider Representatives as having valid Nominations if: + * Their latest Nomination in a Contest is not Revoked. + * Their latest Delegation in a Contest references their latest Nomination. ## [COSE Header Parameters][RFC9052-HeaderParameters] @@ -215,7 +238,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference @@ -225,6 +249,7 @@ The use case here is for Templates. The profile template, or proposal templates could be defined at any of these levels, and as long as they all refer to the same chain of parameters in the hierarchy they are all valid. + * The Document referenced by [`template`](../metadata.md#template) * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination_form_template.md index 4391eefd6ca..4e739a9e967 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/rep_nomination_form_template.md @@ -126,7 +126,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile.md b/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile.md index 5115aa77b14..d246251f890 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile.md @@ -156,7 +156,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference @@ -166,6 +167,7 @@ The use case here is for Templates. The profile template, or proposal templates could be defined at any of these levels, and as long as they all refer to the same chain of parameters in the hierarchy they are all valid. + * The Document referenced by [`template`](../metadata.md#template) * MUST contain [`parameters`](../metadata.md#parameters) metadata; AND * MUST match the referencing documents [`parameters`](../metadata.md#parameters) value. diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile_form_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile_form_template.md index 71da52c0096..ce9de58497d 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile_form_template.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/rep_profile_form_template.md @@ -126,7 +126,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](../metadata.md#parameters). +[`parameters`](../metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](../metadata.md#parameters). For example, a linked reference to [Contest Parameters](contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference diff --git a/docs/src/architecture/08_concepts/signed_doc/metadata.md b/docs/src/architecture/08_concepts/signed_doc/metadata.md index 15486704d3c..c534104c9f1 100644 --- a/docs/src/architecture/08_concepts/signed_doc/metadata.md +++ b/docs/src/architecture/08_concepts/signed_doc/metadata.md @@ -242,6 +242,7 @@ The document version must always be >= the document ID. | | [Rep Profile Form Template](./docs/rep_profile_form_template.md) | | | [Rep Nomination](./docs/rep_nomination.md) | | | [Rep Nomination Form Template](./docs/rep_nomination_form_template.md) | +| | [Contest Delegation](./docs/contest_delegation.md) | Reference to a Linked Document or Documents. This is the primary hierarchical reference to a related document. @@ -378,7 +379,8 @@ A reference to the Parameters Document this document lies under. 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, or a parent of those [`parameters`](metadata.md#parameters). +[`parameters`](metadata.md#parameters) of the referencing document, +or a parent of those [`parameters`](metadata.md#parameters). For example, a linked reference to [Contest Parameters](./docs/contest_parameters.md) is transitively a reference to the Parameters document it references, and each parameters document they reference diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index e0c1b99e6c3..2a2ff9b9aeb 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -12,6 +12,7 @@ All Document Types are defined by composing these base document types: | Category | `818938c3-3139-4daa-afe6-974c78488e95` | `37(h'818938c331394daaafe6974c78488e95')` | | Comment | `b679ded3-0e7c-41ba-89f8-da62a17898ea` | `37(h'b679ded30e7c41ba89f8da62a17898ea')` | | Contest | `788ff4c6-d65a-451f-bb33-575fe056b411` | `37(h'788ff4c6d65a451fbb33575fe056b411')` | +| Delegation | `764f17fb-cc50-4979-b14a-b213dbac5994` | `37(h'764f17fbcc504979b14ab213dbac5994')` | | FormTemplate | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f` | `37(h'0ce8ab3892584fbca62e7faa6e58318f')` | | ModerationAction | `a5d232b8-5e03-4117-9afd-be32b878fcdd` | `37(h'a5d232b85e0341179afdbe32b878fcdd')` | | Nomination | `bf9abd97-5d1f-4429-8e80-740fea371a9c` | `37(h'bf9abd975d1f44298e80740fea371a9c')` | @@ -38,6 +39,7 @@ All Defined Document Types | [Category Parameters](./docs/category_parameters.md) | Parameters/Category | [37(h'601858747e13407ca06c238ffe637ae6'),
37(h'818938c331394daaafe6974c78488e95')] | | [Category Parameters Form Template](./docs/category_parameters_form_template.md) | FormTemplate/Parameters/Category | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'818938c331394daaafe6974c78488e95')] | | [Comment Moderation Action](./docs/comment_moderation_action.md) | Action/Comment/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | +| [Contest Delegation](./docs/contest_delegation.md) | Delegation/Contest | [37(h'764f17fbcc504979b14ab213dbac5994'),
37(h'788ff4c6d65a451fbb33575fe056b411')] | | [Contest Parameters](./docs/contest_parameters.md) | Parameters/Contest | [37(h'601858747e13407ca06c238ffe637ae6'),
37(h'788ff4c6d65a451fbb33575fe056b411')] | | [Contest Parameters Form Template](./docs/contest_parameters_form_template.md) | FormTemplate/Parameters/Contest | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'601858747e13407ca06c238ffe637ae6'),
37(h'788ff4c6d65a451fbb33575fe056b411')] | | [Proposal](./docs/proposal.md) | Proposal | [37(h'7808d2bad51140af84e8c0d1625fdfdc')] | diff --git a/specs/definitions/signed_docs/docs/all.cue b/specs/definitions/signed_docs/docs/all.cue index 18cb52b2667..71c8645faec 100644 --- a/specs/definitions/signed_docs/docs/all.cue +++ b/specs/definitions/signed_docs/docs/all.cue @@ -24,6 +24,7 @@ _allDocTypes: { RegisteredProposer: "7311c63b-95c6-402e-a258-f9bf622093eb" Profile: "0f2c86a2-ffda-40b0-ad38-23709e1c10b3" Nomination: "bf9abd97-5d1f-4429-8e80-740fea371a9c" + Delegation: "764f17fb-cc50-4979-b14a-b213dbac5994" } // Source of truth for ALL Document Types and their matching UUID's. @@ -125,6 +126,10 @@ _allDocs: { _allDocTypes["Nomination"], // For a Nomination _allDocTypes["RegisteredRep"], // Of a Registered Rep ] + "Contest Delegation": [ + _allDocTypes["Delegation"], // A Delegation + _allDocTypes["Contest"], // For a Contest + ] } // Document Cluster Definition diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue new file mode 100644 index 00000000000..6f24cc8db20 --- /dev/null +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -0,0 +1,82 @@ +@extern(embed) + +package signed_docs + +docs: "Contest Delegation": { + description: """ + Delegation by a Registered User to a Representative for + a contest. + + This delegation allows votes cast by the Representative + to use the voting power of the delegating User, in addition + to their own personal voting power and that of all other Users + who delegate to the same Representative. + + Delegation is for a specific Contest. + Multiple Delegations must be published if there are multiple + Contests within a Brand/Campaign or Category. + + This is because different Contests may have different + rules. And not all Representatives will choose to nominate + for every Contest. + """ + validation: """ + * The `parameters` metadata *MUST* point to the same Contest as the + Nomination of the Representative. + * The 'ref' metadata field MUST point to a valid 'Representative Nomination'. + * The payload MUST be nil. + + A Representative *MUST* Delegate to their latest Nomination for a Category, + otherwise their Nomination is invalid. + + \(docs."Rep Nomination"._latest_nomination_note) + """ + business_logic: { + front_end: """ + * Allows a voter to select a Representative from a list of eligible candidates for a category. + * The voter signs this document to confirm their delegation choice. + """ + back_end: """ + * Verifies that the voter and Representative are valid and registered for the category. + * Records the delegation of voting power from the voter to the Representative. + """ + } + + //headers: "content type": value: "application/cbor" + metadata: { + ref: { + required: "yes" + type: "Rep Nomination" + } + parameters: { + required: "yes" + type: "Contest Parameters" + linked_refs: [ + "ref", + ] + } + } + payload: { + description: """ + A minimal payload indicating the intended status of the delegation. + 'active' creates or affirms the delegation. + 'revoked' withdraws the delegation. + """ + + nil: true + } + + signers: roles: user: [ + "Registered", + ] + authors: "Neil McAuliffe": "neil.mcauliffe@iohk.io" + versions: [ + { + version: "0.01" + modified: "2025-06-19" + changes: """ + * First Published Version + """ + }, + ] +} diff --git a/specs/definitions/signed_docs/docs/rep_nomintion.cue b/specs/definitions/signed_docs/docs/rep_nomintion.cue index 8cbd7ab9bdc..617016dbd83 100644 --- a/specs/definitions/signed_docs/docs/rep_nomintion.cue +++ b/specs/definitions/signed_docs/docs/rep_nomintion.cue @@ -3,6 +3,16 @@ package signed_docs // Proposal Document Definition docs: "Rep Nomination": { + _latest_nomination_note: """ + This is because Delegation points to a *SPECIFIC* Nomination, and it + *MUST* be the latest for the Representative on the Contest. + As the Nomination contains information that the User relies on + when choosing to delegate, changing that information could have a + real and detrimental result in the Delegation choice. + Therefore, for a Delegation to be valid, it *MUST* point to the + latest Nomination for a Representative. + """ + description: """ A Representative Nomination Document is created to opt in as a Representative Voter for a specific Contest on a Brand/Campaign or Category. @@ -37,6 +47,18 @@ docs: "Rep Nomination": { * The payload MUST be valid against the JSON schema defined in the referenced template. * Other rules may apply as defined by the Contest or other parameters which can control who may validly nominate as a representative in a Contest. + + No Nomination is valid unless the latest Contest Delegation of the Delegate + refers to their own Nomination. + This requires that Nominating is a two step process: + + 1. Post the Nomination Document. + 2. Post a Contest Delegation delegating to the new Nomination Document. + + Updating the Nomination Document will invalidate all Nominations to the + Representative. + + \(_latest_nomination_note) """ business_logic: { @@ -44,12 +66,17 @@ docs: "Rep Nomination": { front_end: """ * Allows a Representative to create or update their profile for a category. * The Representative sets their status to 'active' to be discoverable for delegation. - * The Representative can set their status to 'revoked' to signal they are no longer participating in the category, without having to revoke the document. + * The Representative `revokes` the Nomination to signal they are no longer + participating in the category. + * Nominations are not valid if the latest Delegation by the Representative does NOT + reference their latest Nomination. """ back_end: """ * The backend MUST verify the signer is a 'Representative' and that all referenced documents exist. - * The system will only consider Representatives with an 'active' status as eligible for delegation. + * The system will only consider Representatives as having valid Nominations if: + * Their latest Nomination in a Contest is not Revoked. + * Their latest Delegation in a Contest references their latest Nomination. """ } headers: "content type": value: "application/json" diff --git a/specs/definitions/signed_docs/metadata_parameters.cue b/specs/definitions/signed_docs/metadata_parameters.cue index caa269f88df..664ce5def64 100644 --- a/specs/definitions/signed_docs/metadata_parameters.cue +++ b/specs/definitions/signed_docs/metadata_parameters.cue @@ -16,7 +16,8 @@ _metadata: _parameters: { In addition to the validation performed for `Document Reference` type fields: * Any linked referenced document that includes a `parameters` metadata must match the - `parameters` of the referencing document, or a parent of those `parameters`. + `parameters` of the referencing document, + or a parent of those `parameters`. For example, a linked reference to `Contest Parameters` is transitively a reference to the Parameters document it references, and each parameters document they reference diff --git a/specs/definitions/signed_docs/payload.cue b/specs/definitions/signed_docs/payload.cue index b7e1a379dfe..f302163be1e 100644 --- a/specs/definitions/signed_docs/payload.cue +++ b/specs/definitions/signed_docs/payload.cue @@ -18,10 +18,16 @@ import ( _payload: { // Description of the payload description: string - // 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] | *[] + // Is the Payload nil? + nil?: true + + // Only have these when the payload isn't nil. + if nil == _|_ { + // 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] | *[] + } } diff --git a/specs/definitions/signed_docs/signed_doc.cue b/specs/definitions/signed_docs/signed_doc.cue index b0abbe2b908..fbf1b152549 100644 --- a/specs/definitions/signed_docs/signed_doc.cue +++ b/specs/definitions/signed_docs/signed_doc.cue @@ -35,8 +35,10 @@ import ( notes: [...string] | *[] - // Fixed headers in every document - headers: _coseHeaders + if payload.nil == _|_ { + // Fixed headers in every document with a payload. + headers: _coseHeaders + } // The Metadata fields in this document (non cose standard) metadata: #metadata diff --git a/specs/generators/packages/spec/src/spec/document.py b/specs/generators/packages/spec/src/spec/document.py index dbf9db7de85..a7788f6fe71 100644 --- a/specs/generators/packages/spec/src/spec/document.py +++ b/specs/generators/packages/spec/src/spec/document.py @@ -39,7 +39,7 @@ class Document(BaseModel): default_factory=DocumentBusinessLogic, ) notes: list[str] - headers: CoseHeaders + headers: CoseHeaders | None = Field(default=None) metadata: MetadataHeaders payload: Payload | None = Field(default=None) signers: Signers @@ -98,6 +98,8 @@ def all_docs_referencing(self) -> list[str]: @property def content_type(self) -> str | list[str]: """Get document content type.""" + if self.headers is None: + return "Undefined" content_type = self.headers.get("content type") if content_type.value is None: return "Undefined" diff --git a/specs/generators/packages/spec/src/spec/metadata.py b/specs/generators/packages/spec/src/spec/metadata.py index a9aec5b08e4..b41c9ef96b4 100644 --- a/specs/generators/packages/spec/src/spec/metadata.py +++ b/specs/generators/packages/spec/src/spec/metadata.py @@ -60,6 +60,7 @@ def get_validation(self) -> str: for ref in self.linked_refs: validation += f""" + * The Document referenced by `{ref}` * MUST contain `{self._name}` metadata; AND * MUST match the referencing documents `{self._name}` value.""" diff --git a/specs/generators/packages/spec/src/spec/payload.py b/specs/generators/packages/spec/src/spec/payload.py index dfe075d969a..bc821a05eb2 100644 --- a/specs/generators/packages/spec/src/spec/payload.py +++ b/specs/generators/packages/spec/src/spec/payload.py @@ -53,6 +53,7 @@ class Payload(BaseModel): """Payload Deserialized Specification.""" description: str + nil: bool = Field(default=False) doc_schema: HttpUrl | dict[str, Any] | None = Field(default=None, alias="schema") examples: list[PayloadExample] = Field(default_factory=PayloadExample.default) @@ -97,6 +98,13 @@ def __str__(self) -> str: """Get the examples properly formatted as markdown.""" docs = self.description + "\n" + if self.nil: + docs += """ +This document has no payload. +It must be encoded as a CBOR `null (0xf6)`. +""" + return docs + schema = self.doc_schema if schema is not None: if isinstance(schema, HttpUrl): diff --git a/specs/generators/src/docs/doc_relationship_diagrams.py b/specs/generators/src/docs/doc_relationship_diagrams.py index b64cb8a50fc..d61c3033e26 100644 --- a/specs/generators/src/docs/doc_relationship_diagrams.py +++ b/specs/generators/src/docs/doc_relationship_diagrams.py @@ -67,8 +67,9 @@ def generate(self) -> bool: # noqa: C901 doc_data = self._spec.docs.get(doc) doc_type = doc_data.type.formatted_ids(prefix="", separator="
", suffix="", cbor=False) - # Add content type explicitely to table. - doc_table.add_row(TableRow(name="content type", value=doc_data.content_type)) + if doc_data.headers is not None: + # Add content type explicitely to table. + doc_table.add_row(TableRow(name="content type", value=doc_data.content_type)) # Add all used Metadata to table. for meta in self._spec.metadata.headers.names: diff --git a/specs/generators/src/docs/docs_page_md.py b/specs/generators/src/docs/docs_page_md.py index 7223fb0e596..7d34640b5e8 100644 --- a/specs/generators/src/docs/docs_page_md.py +++ b/specs/generators/src/docs/docs_page_md.py @@ -46,6 +46,10 @@ def description_or_todo(self, desc: str | None) -> str: def header_parameter_summary(self) -> str: """Generate concrete Cose header parameter settings for a specific document.""" headers = self._doc.headers + + if headers is None: + return "No Headers are defined for this document." + header_docs = "" for header in headers.names: value = headers.get(header).value diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 11d44bc971c..9b85ccaddac 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -10,6 +10,7 @@ "Category": "818938c3-3139-4daa-afe6-974c78488e95", "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea", "Contest": "788ff4c6-d65a-451f-bb33-575fe056b411", + "Delegation": "764f17fb-cc50-4979-b14a-b213dbac5994", "FormTemplate": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "ModerationAction": "a5d232b8-5e03-4117-9afd-be32b878fcdd", "Nomination": "bf9abd97-5d1f-4429-8e80-740fea371a9c", @@ -430,7 +431,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -556,7 +557,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -689,7 +690,7 @@ "multiple": false, "required": "yes", "type": "Brand Parameters", - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -815,7 +816,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -948,7 +949,7 @@ "multiple": false, "required": "yes", "type": "Campaign Parameters", - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1074,7 +1075,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1201,7 +1202,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1275,6 +1276,119 @@ } ] }, + "Contest Delegation": { + "authors": { + "Neil McAuliffe": "neil.mcauliffe@iohk.io" + }, + "business_logic": { + "back_end": "* Verifies that the voter and Representative are valid and registered for the category.\n* Records the delegation of voting power from the voter to the Representative.", + "front_end": "* Allows a voter to select a Representative from a list of eligible candidates for a category.\n* The voter signs this document to confirm their delegation choice." + }, + "description": "Delegation by a Registered User to a Representative for \na contest.\n\nThis delegation allows votes cast by the Representative\nto use the voting power of the delegating User, in addition\nto their own personal voting power and that of all other Users \nwho delegate to the same Representative.\n\nDelegation is for a specific Contest.\nMultiple Delegations must be published if there are multiple\nContests within a Brand/Campaign or Category.\n\nThis is because different Contests may have different\nrules. And not all Representatives will choose to nominate\nfor every Contest.", + "metadata": { + "chain": { + "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", + "format": "Chain Link", + "required": "excluded", + "validation": "Chained Documents do not support collaborators.\nAny document which is attempted to be published in the sequence\nwhich is *NOT* published by the author of the first document in the\nsequence is fraudulent, and to be discarded.\n\nIn addition, the chained document *MUST*:\n\n* Not have `collaborators`;\n* Have the same `id` as the document being chained to;\n* Have a `ver` that is greater than the `ver` being chained to;\n* Have the same `type` as the chained document;\n* Have `parameters` match;\n* Have not be chaining to a document already chained to by another document;\n* Have its absolute `height` exactly one more than the `height` of the document being chained to.\n\nIF any of these validations fail, then the entire sequence of documents is INVALID.\nNot just the current document." + }, + "collaborators": { + "description": "A list of collaborators who may also publish updates to versions of this document.\nThis should include all parties who have not signed this document directly.\n\nEvery subsequent version can amend the collaborators list.\nHowever, the initial Author can never be removed from being able to\npublish a new version of the document.", + "format": "Collaborators Reference List", + "required": "excluded", + "validation": "This list does not imply these collaborators have consented to collaborate, only that the author/s\nare permitting these potential collaborators to participate in the drafting and submission process.\nHowever, any document submission referencing a proposal MUST be signed by all collaborators in\naddition to the author." + }, + "id": { + "description": "Document ID, created the first time the document is created.\nThis must be a properly created UUIDv7 which contains the \ntimestamp of when the document was created.", + "format": "Document Id", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." + }, + "parameters": { + "description": "A reference to the Parameters Document this document lies under.", + "format": "Document Reference", + "linked_refs": [ + "ref" + ], + "multiple": false, + "required": "yes", + "type": "Contest Parameters", + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", + "format": "Document Reference", + "linked_refs": null, + "multiple": false, + "required": "yes", + "type": "Rep Nomination", + "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "revocations": { + "description": "A document may include a list of any prior versions which are considered to be revoked.\nOnly the revocation list in the latest version of the document applies.\nRevoked documents are flagged as no longer valid, and should not be displayed.\nAs a special case, if the revocations are set to `true` then all versions of the document\nare revoked, including the latest document.\n\nIn this case, when the latest document is revoked, the payload may be empty.\nAny older document that has `revocations` set to `true` is always to be filtered\nand its payload is to be assumed to be invalid.\n\nThis allows for an entire document and any/all published versions to be revoked.\nA new version of the document that is published after this, may reinstate prior\ndocument versions, by not listing them as revoked. \nHowever, any document where revocations was set `true` can never be reinstated.", + "format": "Version Revocations", + "required": "excluded", + "validation": "If the field is `true` the payload may be absent or invalid.\nSuch documents may never be submitted." + }, + "section": { + "description": "A Reference to the original document, or the comment being replied to.", + "format": "Section Reference", + "required": "excluded", + "validation": "For a non-reply this must be a valid section reference into the referenced document.\nFor a reply, this must be a valid section reference into the comment being replied to." + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `Document Reference` type fields, \nThe document payload is not valid if it does not validate completely against the referenced template." + }, + "type": { + "description": "The document TYPE.", + "format": "Document Type", + "required": "yes", + "validation": "**MUST** be a known document type." + }, + "ver": { + "description": "The unique version of the document.\nThe first version of the document must set `ver` == `id`\n\n`ver` represents new versions of the same document as it changes over time.", + "format": "Document Ver", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "notes": [], + "payload": { + "description": " A minimal payload indicating the intended status of the delegation.\n 'active' creates or affirms the delegation.\n 'revoked' withdraws the delegation.", + "nil": true + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] + }, + "update": { + "author": true + } + }, + "type": [ + "764f17fb-cc50-4979-b14a-b213dbac5994", + "788ff4c6-d65a-451f-bb33-575fe056b411" + ], + "validation": "* The `parameters` metadata *MUST* point to the same Contest as the \n\tNomination of the Representative.\n* The 'ref' metadata field MUST point to a valid 'Representative Nomination'.\n* The payload MUST be nil.\n\nA Representative *MUST* Delegate to their latest Nomination for a Category,\notherwise their Nomination is invalid.\n\nThis is because Delegation points to a *SPECIFIC* Nomination, and it\n*MUST* be the latest for the Representative on the Contest.\nAs the Nomination contains information that the User relies on\nwhen choosing to delegate, changing that information could have a \nreal and detrimental result in the Delegation choice.\nTherefore, for a Delegation to be valid, it *MUST* point to the\nlatest Nomination for a Representative.", + "versions": [ + { + "changes": "* First Published Version", + "modified": "2025-06-19", + "version": "0.01" + } + ] + }, "Contest Parameters": { "authors": { "Nathan Bogale": "nathan.bogale@iohk.io", @@ -1329,7 +1443,7 @@ "Campaign Parameters", "Category 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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1455,7 +1569,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1597,7 +1711,7 @@ "Campaign Parameters", "Category 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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1735,7 +1849,7 @@ "Campaign Parameters", "Category 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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -1872,7 +1986,7 @@ "Campaign Parameters", "Category 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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2006,7 +2120,7 @@ "Campaign Parameters", "Category 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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2131,7 +2245,7 @@ "Campaign Parameters", "Category 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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2257,7 +2371,7 @@ "description": "A reference to the Parameters Document this document lies under.", "format": "Document Reference", "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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2380,7 +2494,7 @@ "Campaign Parameters", "Category 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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2510,7 +2624,7 @@ "Campaign Parameters", "Category 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, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2660,8 +2774,8 @@ "Steven Johnson": "steven.johnson@iohk.io" }, "business_logic": { - "back_end": "* The backend MUST verify the signer is a 'Representative' and that all referenced documents exist.\n* The system will only consider Representatives with an 'active' status as eligible for delegation.", - "front_end": "* Allows a Representative to create or update their profile for a category.\n* The Representative sets their status to 'active' to be discoverable for delegation.\n* The Representative can set their status to 'revoked' to signal they are no longer participating in the category, without having to revoke the document." + "back_end": "* The backend MUST verify the signer is a 'Representative' and that all referenced documents exist.\n* The system will only consider Representatives as having valid Nominations if:\n * Their latest Nomination in a Contest is not Revoked.\n * Their latest Delegation in a Contest references their latest Nomination.", + "front_end": "* Allows a Representative to create or update their profile for a category.\n* The Representative sets their status to 'active' to be discoverable for delegation.\n* The Representative `revokes` the Nomination to signal they are no longer \n\tparticipating in the category.\n* Nominations are not valid if the latest Delegation by the Representative does NOT\n\treference their latest Nomination." }, "description": "A Representative Nomination Document is created to opt\nin as a Representative Voter for a specific Contest on a Brand/Campaign or Category.\n\nThis Document is a kind of `Profile` that is primarily used to\nhelp justify the Representatives Nomination to prospective delegators.\n\nThe user must have registered as a Representative.\nThe presence of this document signifies the user's intent to participate in that \ncontest as a Representative.\n\nThe document's structure is defined by the associated \nRep Nomination Form Template.\nThis allows an Admin to specify contest-specific requirements.\n\nThe Representative can retract their nomination by using the `revoke` metadata to\nrevoke this Nomination document.\n\nIt is an extension of all other profiles attached to the same Catalyst ID.\n\nProfiles themselves are intentionally general, however they may be\nlinked to a Brand/Campaign/Category via the template used by the profile.\n\nThe payload of a profile is controlled by its template.", "headers": { @@ -2710,7 +2824,7 @@ "multiple": false, "required": "yes", "type": "Contest Parameters", - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2779,7 +2893,7 @@ "bf9abd97-5d1f-4429-8e80-740fea371a9c", "94579df1-a6dc-433b-a8e8-910c5dc2f0e3" ], - "validation": "* The signer MUST be a registered 'Representative'.\n* The 'ref' metadata field MUST point to a valid 'Representative Profile' document.\n* The 'parameters' metadata field MUST point to a valid 'Contest Parameters' document.\n* The 'template' metadata field MUST point to a valid 'Representative Nomination Form Template' document.\n* The payload MUST be valid against the JSON schema defined in the referenced template.\n* Other rules may apply as defined by the Contest or other parameters which can\n\tcontrol who may validly nominate as a representative in a Contest.", + "validation": "* The signer MUST be a registered 'Representative'.\n* The 'ref' metadata field MUST point to a valid 'Representative Profile' document.\n* The 'parameters' metadata field MUST point to a valid 'Contest Parameters' document.\n* The 'template' metadata field MUST point to a valid 'Representative Nomination Form Template' document.\n* The payload MUST be valid against the JSON schema defined in the referenced template.\n* Other rules may apply as defined by the Contest or other parameters which can\n\tcontrol who may validly nominate as a representative in a Contest.\n\nNo Nomination is valid unless the latest Contest Delegation of the Delegate\nrefers to their own Nomination.\nThis requires that Nominating is a two step process:\n\n1. Post the Nomination Document.\n2. Post a Contest Delegation delegating to the new Nomination Document.\n\nUpdating the Nomination Document will invalidate all Nominations to the \nRepresentative.\n\nThis is because Delegation points to a *SPECIFIC* Nomination, and it\n*MUST* be the latest for the Representative on the Contest.\nAs the Nomination contains information that the User relies on\nwhen choosing to delegate, changing that information could have a \nreal and detrimental result in the Delegation choice.\nTherefore, for a Delegation to be valid, it *MUST* point to the\nlatest Nomination for a Representative.", "versions": [ { "changes": "* First Published Version", @@ -2835,7 +2949,7 @@ "multiple": false, "required": "yes", "type": "Contest Parameters", - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -2976,7 +3090,7 @@ "type": [ "Brand Parameters" ], - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -3100,7 +3214,7 @@ "type": [ "Brand Parameters" ], - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -4475,7 +4589,7 @@ "Category Parameters", "Contest Parameters" ], - "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document, or a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." + "validation": "In addition to the validation performed for `Document Reference` type fields: \n\n* Any linked referenced document that includes a `parameters` metadata must match the \n`parameters` of the referencing document,\nor a parent of those `parameters`.\n\nFor example, a linked reference to `Contest Parameters` is transitively a reference to\nthe Parameters document it references, and each parameters document they reference \nuntil the `Brand` parameters document is reached.\n\nThe use case here is for Templates.\nThe profile template, or proposal templates could be defined at any of these\nlevels, and as long as they all refer to the same chain of parameters in the\nhierarchy they are all valid." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nIf a reference is defined as required, there must be at least 1 reference specified.\nSome documents allow multiple references, and they are documented as required.\n\nThe document reference serves two purposes:\n \n1. It ensures that the document referenced by an ID/Version is not substituted.\n\tIn other words, that the document intended to be referenced, is actually referenced.\n2. It Allows the document to be unambiguously located in decentralized storage systems.\n\nThere can be any number of Document Locations in any reference.\nThe currently defined locations are:\n\n* `cid` : A CBOR Encoded IPLD Content Identifier ( AKA an IPFS CID ).\n* Others may be added when further storage mechanisms are defined.\n\nThe document location does not guarantee that the document is actually stored.\nIt only defines that if it were stored, this is the identifier\nthat is required to retrieve it.\nTherefore it is required that Document References\nare unique and reproducible, given a documents contents.", @@ -4504,7 +4618,8 @@ "Rep Profile", "Rep Profile Form Template", "Rep Nomination", - "Rep Nomination Form Template" + "Rep Nomination Form Template", + "Contest Delegation" ], "validation": "The following must be true for a valid reference:\n\n* The Referenced Document **MUST** Exist\n* Every value in the `document_locator` must consistently reference the exact same document.\n* The `document_id` and `document_ver` **MUST** match the values in the referenced document." }, From 48237bcfa16eb36bb080a6cb27874aeab826218d Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 25 Jun 2025 18:09:07 +0700 Subject: [PATCH 31/42] Update contest_delegation.cue Break line with multiple sentences --- specs/definitions/signed_docs/docs/contest_delegation.cue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue index 6f24cc8db20..ae4c1890354 100644 --- a/specs/definitions/signed_docs/docs/contest_delegation.cue +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -17,7 +17,8 @@ docs: "Contest Delegation": { Contests within a Brand/Campaign or Category. This is because different Contests may have different - rules. And not all Representatives will choose to nominate + rules. + And not all Representatives will choose to nominate for every Contest. """ validation: """ From fdf88f9fb9f22da03ac6cbd7ec9cc2d187cf0522 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 25 Jun 2025 18:24:10 +0700 Subject: [PATCH 32/42] fix excess lines in null payload description --- specs/generators/packages/spec/src/spec/payload.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/generators/packages/spec/src/spec/payload.py b/specs/generators/packages/spec/src/spec/payload.py index bc821a05eb2..3cce36578f9 100644 --- a/specs/generators/packages/spec/src/spec/payload.py +++ b/specs/generators/packages/spec/src/spec/payload.py @@ -103,7 +103,7 @@ def __str__(self) -> str: This document has no payload. It must be encoded as a CBOR `null (0xf6)`. """ - return docs + return docs.strip() schema = self.doc_schema if schema is not None: From 626a1065033ca26c6bfaa3a66f45fb08ad106873 Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 15:57:04 +0300 Subject: [PATCH 33/42] fix(docs): contest delegation spacing --- specs/definitions/signed_docs/docs/contest_delegation.cue | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue index ae4c1890354..c06e475fe2b 100644 --- a/specs/definitions/signed_docs/docs/contest_delegation.cue +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -16,10 +16,8 @@ docs: "Contest Delegation": { Multiple Delegations must be published if there are multiple Contests within a Brand/Campaign or Category. - This is because different Contests may have different - rules. - And not all Representatives will choose to nominate - for every Contest. + This is because different Contests may have different rules. + And not all Representatives will choose to nominate for every Contest. """ validation: """ * The `parameters` metadata *MUST* point to the same Contest as the From 149360aa5f5a96b9684609c6e69be362ab95445f Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 17:57:18 +0300 Subject: [PATCH 34/42] fix(docs): contest structure fix --- .../signed_docs/docs/contest_delegation.cue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue index c06e475fe2b..ec6b2e09634 100644 --- a/specs/definitions/signed_docs/docs/contest_delegation.cue +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -6,18 +6,18 @@ docs: "Contest Delegation": { description: """ Delegation by a Registered User to a Representative for a contest. - + This delegation allows votes cast by the Representative to use the voting power of the delegating User, in addition - to their own personal voting power and that of all other Users - who delegate to the same Representative. + to their own personal voting power and that of all other Users who delegate to the same Representative. Delegation is for a specific Contest. Multiple Delegations must be published if there are multiple Contests within a Brand/Campaign or Category. - This is because different Contests may have different rules. - And not all Representatives will choose to nominate for every Contest. + This is because different Contests may have different + rules. And not all Representatives will choose to nominate + for every Contest. """ validation: """ * The `parameters` metadata *MUST* point to the same Contest as the From 02b27ffbd5d20ee02b4e47d4df67e126bb03cd61 Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 18:05:51 +0300 Subject: [PATCH 35/42] fix(docs): structure quick fix --- .../08_concepts/signed_doc/docs/contest_delegation.md | 4 ++-- specs/definitions/signed_docs/docs/contest_delegation.cue | 4 ++-- specs/signed_doc.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md index ff96869665b..482b290962f 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md @@ -14,8 +14,8 @@ Delegation is for a specific Contest. Multiple Delegations must be published if there are multiple Contests within a Brand/Campaign or Category. -This is because different Contests may have different -rules. And not all Representatives will choose to nominate +This is because different Contests may have different rules. +And not all Representatives will choose to nominate for every Contest. diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue index ec6b2e09634..4592c9c574a 100644 --- a/specs/definitions/signed_docs/docs/contest_delegation.cue +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -15,8 +15,8 @@ docs: "Contest Delegation": { Multiple Delegations must be published if there are multiple Contests within a Brand/Campaign or Category. - This is because different Contests may have different - rules. And not all Representatives will choose to nominate + This is because different Contests may have different rules. + And not all Representatives will choose to nominate for every Contest. """ validation: """ diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 9b85ccaddac..3c6027aad9c 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -1284,7 +1284,7 @@ "back_end": "* Verifies that the voter and Representative are valid and registered for the category.\n* Records the delegation of voting power from the voter to the Representative.", "front_end": "* Allows a voter to select a Representative from a list of eligible candidates for a category.\n* The voter signs this document to confirm their delegation choice." }, - "description": "Delegation by a Registered User to a Representative for \na contest.\n\nThis delegation allows votes cast by the Representative\nto use the voting power of the delegating User, in addition\nto their own personal voting power and that of all other Users \nwho delegate to the same Representative.\n\nDelegation is for a specific Contest.\nMultiple Delegations must be published if there are multiple\nContests within a Brand/Campaign or Category.\n\nThis is because different Contests may have different\nrules. And not all Representatives will choose to nominate\nfor every Contest.", + "description": "Delegation by a Registered User to a Representative for \na contest.\n\nThis delegation allows votes cast by the Representative\nto use the voting power of the delegating User, in addition\nto their own personal voting power and that of all other Users \nwho delegate to the same Representative.\n\nDelegation is for a specific Contest.\nMultiple Delegations must be published if there are multiple\nContests within a Brand/Campaign or Category.\n\nThis is because different Contests may have different rules.\nAnd not all Representatives will choose to nominate\nfor every Contest.", "metadata": { "chain": { "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", From 61753ff77d87cd82d5943ce8933553a50d7f016b Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 18:12:10 +0300 Subject: [PATCH 36/42] fix(docs): fixed indentation in contest md --- .../08_concepts/signed_doc/docs/contest_delegation.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md index 482b290962f..61408a4bc73 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md @@ -194,7 +194,6 @@ hierarchy they are all valid. This document has no payload. It must be encoded as a [CBOR][RFC8949] `null (0xf6)`. - ## Signers The following User roles may sign documents of this type: From 55791f6be7b9aaa7113ea7db415b262e5c2a35c7 Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 18:20:15 +0300 Subject: [PATCH 37/42] fix(docs): contest cue file fix --- .../signed_docs/docs/contest_delegation.cue | 11 ++++++----- specs/signed_doc.json | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue index 4592c9c574a..41cc3f3dd94 100644 --- a/specs/definitions/signed_docs/docs/contest_delegation.cue +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -4,17 +4,18 @@ package signed_docs docs: "Contest Delegation": { description: """ - Delegation by a Registered User to a Representative for + Delegation by a Registered User to a Representative for a contest. - + This delegation allows votes cast by the Representative to use the voting power of the delegating User, in addition - to their own personal voting power and that of all other Users who delegate to the same Representative. - + to their own personal voting power and that of all other Users + who delegate to the same Representative. + Delegation is for a specific Contest. Multiple Delegations must be published if there are multiple Contests within a Brand/Campaign or Category. - + This is because different Contests may have different rules. And not all Representatives will choose to nominate for every Contest. diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 3c6027aad9c..ab756c341ef 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -1284,7 +1284,7 @@ "back_end": "* Verifies that the voter and Representative are valid and registered for the category.\n* Records the delegation of voting power from the voter to the Representative.", "front_end": "* Allows a voter to select a Representative from a list of eligible candidates for a category.\n* The voter signs this document to confirm their delegation choice." }, - "description": "Delegation by a Registered User to a Representative for \na contest.\n\nThis delegation allows votes cast by the Representative\nto use the voting power of the delegating User, in addition\nto their own personal voting power and that of all other Users \nwho delegate to the same Representative.\n\nDelegation is for a specific Contest.\nMultiple Delegations must be published if there are multiple\nContests within a Brand/Campaign or Category.\n\nThis is because different Contests may have different rules.\nAnd not all Representatives will choose to nominate\nfor every Contest.", + "description": "Delegation by a Registered User to a Representative for\na contest.\n\nThis delegation allows votes cast by the Representative\nto use the voting power of the delegating User, in addition\nto their own personal voting power and that of all other Users\nwho delegate to the same Representative.\n\nDelegation is for a specific Contest.\nMultiple Delegations must be published if there are multiple\nContests within a Brand/Campaign or Category.\n\nThis is because different Contests may have different rules.\nAnd not all Representatives will choose to nominate\nfor every Contest.", "metadata": { "chain": { "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", From b0140dbd67e8e5db395c5bb0760f08e881583763 Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 18:27:01 +0300 Subject: [PATCH 38/42] fix(docs): quick fix on indentation --- specs/signed_doc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/signed_doc.json b/specs/signed_doc.json index ab756c341ef..280d2a240b5 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -1284,7 +1284,7 @@ "back_end": "* Verifies that the voter and Representative are valid and registered for the category.\n* Records the delegation of voting power from the voter to the Representative.", "front_end": "* Allows a voter to select a Representative from a list of eligible candidates for a category.\n* The voter signs this document to confirm their delegation choice." }, - "description": "Delegation by a Registered User to a Representative for\na contest.\n\nThis delegation allows votes cast by the Representative\nto use the voting power of the delegating User, in addition\nto their own personal voting power and that of all other Users\nwho delegate to the same Representative.\n\nDelegation is for a specific Contest.\nMultiple Delegations must be published if there are multiple\nContests within a Brand/Campaign or Category.\n\nThis is because different Contests may have different rules.\nAnd not all Representatives will choose to nominate\nfor every Contest.", + "description": "Delegation by a Registered User to a Representative for\na contest.\n\nThis delegation allows votes cast by the Representative\nto use the voting power of the delegating User, in addition\nto their own personal voting power and that of all other Users \nwho delegate to the same Representative.\n\nDelegation is for a specific Contest.\nMultiple Delegations must be published if there are multiple\nContests within a Brand/Campaign or Category.\n\nThis is because different Contests may have different rules.\nAnd not all Representatives will choose to nominate\nfor every Contest.", "metadata": { "chain": { "description": "An immutable link to the previous document in a chained sequence of documents.\nBecause ID/Ver only defines values for the current document, and is not intended \nby itself to prevent insertion of documents in a sequence, the `chain`\nmetadata allows for the latest document to directly point to its previous iteration.\n\nIt also aids in discoverability, where the latest document may be pinned but prior\ndocuments can be discovered automatically by following the chain.", From d4eb2d84c5f0d1cc37b904986f9ec1059b1fb621 Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 18:42:48 +0300 Subject: [PATCH 39/42] fix(docs): markdown indentation fix --- .../08_concepts/signed_doc/docs/contest_delegation.md | 2 +- specs/definitions/signed_docs/docs/contest_delegation.cue | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md index 61408a4bc73..b17850b1822 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md @@ -14,7 +14,7 @@ Delegation is for a specific Contest. Multiple Delegations must be published if there are multiple Contests within a Brand/Campaign or Category. -This is because different Contests may have different rules. +This is because different Contests may have different rules. And not all Representatives will choose to nominate for every Contest. diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue index 41cc3f3dd94..22183bff137 100644 --- a/specs/definitions/signed_docs/docs/contest_delegation.cue +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -16,10 +16,10 @@ docs: "Contest Delegation": { Multiple Delegations must be published if there are multiple Contests within a Brand/Campaign or Category. - This is because different Contests may have different rules. + This is because different Contests may have different rules. And not all Representatives will choose to nominate for every Contest. - """ + """"""" validation: """ * The `parameters` metadata *MUST* point to the same Contest as the Nomination of the Representative. From aed490af3c5bff8af277015cf08245b9bd7b5444 Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 16:42:26 +0000 Subject: [PATCH 40/42] fix(docs): minor character and structure fix --- specs/definitions/signed_docs/docs/contest_delegation.cue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue index 22183bff137..21332d06efa 100644 --- a/specs/definitions/signed_docs/docs/contest_delegation.cue +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -19,7 +19,7 @@ docs: "Contest Delegation": { This is because different Contests may have different rules. And not all Representatives will choose to nominate for every Contest. - """"""" + """ validation: """ * The `parameters` metadata *MUST* point to the same Contest as the Nomination of the Representative. From 187dc6e32240979be733c68c6ab95de3e5dfa11b Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 16:53:52 +0000 Subject: [PATCH 41/42] fix(docs): contest cue file fix --- specs/definitions/signed_docs/docs/contest_delegation.cue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/definitions/signed_docs/docs/contest_delegation.cue b/specs/definitions/signed_docs/docs/contest_delegation.cue index 21332d06efa..4352620a6e0 100644 --- a/specs/definitions/signed_docs/docs/contest_delegation.cue +++ b/specs/definitions/signed_docs/docs/contest_delegation.cue @@ -9,7 +9,7 @@ docs: "Contest Delegation": { This delegation allows votes cast by the Representative to use the voting power of the delegating User, in addition - to their own personal voting power and that of all other Users + to their own personal voting power and that of all other Users who delegate to the same Representative. Delegation is for a specific Contest. From 2ea491f2f734877b920c7bd1d1a8e018cfa438c6 Mon Sep 17 00:00:00 2001 From: Nathan Bogale Date: Wed, 25 Jun 2025 17:04:17 +0000 Subject: [PATCH 42/42] fix(docs): additional indentation fix --- .../08_concepts/signed_doc/docs/contest_delegation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md index b17850b1822..89ea30af963 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/contest_delegation.md @@ -187,7 +187,7 @@ hierarchy they are all valid. ## Payload - A minimal payload indicating the intended status of the delegation. +A minimal payload indicating the intended status of the delegation. 'active' creates or affirms the delegation. 'revoked' withdraws the delegation.