From bf256dd26e723029754b09bc42ac2e211541481b Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Fri, 14 Feb 2025 00:05:16 +0700 Subject: [PATCH 01/35] docs(docs): Add wip files for formal signed document schemas --- .../08_concepts/signed_doc/meta.md | 7 + .../08_concepts/signed_doc/spec/Justfile | 22 ++ .../08_concepts/signed_doc/spec/all_docs.cue | 11 + .../signed_doc/spec/obsolete/Earthfile | 34 +++ .../signed_doc/spec/obsolete/blueprint.cue | 2 + .../spec/obsolete/signed_doc_defs.schema.cue | 75 ++++++ .../spec/obsolete/signed_doc_defs.schema.json | 177 +++++++++++++ .../spec/obsolete/signed_doc_defs.yml | 115 +++++++++ .../signed_doc/spec/proposal_doc.cue | 13 + .../signed_doc/spec/signed_doc.json | 53 ++++ .../signed_doc/spec/signed_doc.yaml | 85 +++++++ .../signed_doc/spec/signed_doc_defs.cue | 235 ++++++++++++++++++ .../signed_doc/spec/template_doc.cue | 20 ++ .../08_concepts/signed_doc/types.md | 2 +- .../08_concepts/signed_doc/validation.md | 23 ++ 15 files changed, 873 insertions(+), 1 deletion(-) create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/Justfile create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/all_docs.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/obsolete/Earthfile create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/obsolete/blueprint.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.json create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.yml create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/proposal_doc.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.yaml create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/signed_doc_defs.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/template_doc.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/validation.md diff --git a/docs/src/architecture/08_concepts/signed_doc/meta.md b/docs/src/architecture/08_concepts/signed_doc/meta.md index 539f53a79a..6cd82ed729 100644 --- a/docs/src/architecture/08_concepts/signed_doc/meta.md +++ b/docs/src/architecture/08_concepts/signed_doc/meta.md @@ -10,6 +10,7 @@ * [Metadata Fields List](#metadata-fields-list) * [`ref` Document Reference](#ref-document-reference) + * [Validation](#validation) * [`ref_hash` Secured Document Reference](#ref_hash-secured-document-reference) * [`template` Template Reference](#template-template-reference) * [`reply` Reply Reference](#reply-reply-reference) @@ -33,6 +34,12 @@ If the `ref` is a [CBOR] array, it has the form `[,]` where: * `` - the [UUID] v7 of the referenced documents [`id`](./spec.md#id). * `` - the [UUID] v7 of the referenced documents [`ver`](./spec.md#ver). +### Validation + +For any document type, `ref` can refer to only 1 other document type which must be different than +the type of document `ref` appears in. +For example `ref` for a Proposal Comment Document, is always a Proposal type document. + ## `ref_hash` Secured Document Reference This is a cryptographically secured reference to another document. diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/Justfile b/docs/src/architecture/08_concepts/signed_doc/spec/Justfile new file mode 100644 index 0000000000..15348de834 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/Justfile @@ -0,0 +1,22 @@ +# use with https://github.com/casey/just +# +# Developer convenience functions + +default: + @just --list --unsorted + +# Fiz (where possible) and format cue files +format: + cue fix signed_docs + cue fmt . + +# Check the signed document cue files are valid. +check: format + cue vet -p signed_docs -c + +# Fix and Check Markdown files +regenerate: check + cue export -f -s -p signed_docs --out yaml --outfile signed_doc.yaml + +# Pre Push Checks - intended to be run by a git pre-push hook. +pre-push: regenerate diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/all_docs.cue b/docs/src/architecture/08_concepts/signed_doc/spec/all_docs.cue new file mode 100644 index 0000000000..f1ceebb6d8 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/all_docs.cue @@ -0,0 +1,11 @@ +// Master list of all document types. +package signed_docs + +// Source of truth for ALL Document Types and their matching UUID's. +// Format is : : +_allDocs: { + "Template": "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + "Proposal": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea" + "Action": "5e60e623-ad02-4a1b-a1ac-406db978ee48" +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/Earthfile b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/Earthfile new file mode 100644 index 0000000000..ca31162f8c --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/Earthfile @@ -0,0 +1,34 @@ +VERSION 0.8 + +# cspell: words cuelang + +# Get cue binary +cue-bin: + FROM cuelang/cue:0.12.0 + SAVE ARTIFACT /usr/bin/cue + + +# builder - debian plus cue binary +builder: + FROM debian:stable-20250203-slim + COPY +cue-bin/cue /usr/bin/cue + +# Copy all the source we need to build the docs +src: + FROM +builder + + WORKDIR /src + + COPY signed_doc_defs.* . + +check: + FROM +src + RUN cue --help + RUN ls -al + RUN cue vet signed_doc_defs.schema.cue -d '#SignedDoc' signed_doc_defs.yml + +# Regenerate +regen: + FROM src + + RUN ls -al \ No newline at end of file diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/blueprint.cue b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/blueprint.cue new file mode 100644 index 0000000000..e9144a9d01 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/blueprint.cue @@ -0,0 +1,2 @@ +version: "1.0.0" +project: name: "Signed-Docs-Specs" diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.cue b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.cue new file mode 100644 index 0000000000..a9a4375711 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.cue @@ -0,0 +1,75 @@ +package signed_docs + +#SignedDoc: { + // Signed Document Definitions Database + // + // Source of truth for definitions of all catalyst signed + // documents. + @jsonschema(schema="http://json-schema.org/draft-07/schema#") + null | bool | number | string | [...] | close({ + @jsonschema(id="https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/docs/src/architecture/08_concepts/signed_doc/signed_doc_defs.schema.json") + default?: #docDefinitionFields + + // Document Definition + docs?: { + {[=~".*"]: #docDefinition} + "Proposal Template"!: _ + Proposal!: _ + "Proposal Action"!: _ + "Proposal Comment Template"!: _ + "Proposal Comment"!: _ + "Category Parameters"!: _ + "Campaign Parameters"!: _ + "Brand Parameters"!: _ + "Public Vote Tx V2"!: _ + "Private Vote Tx V2"!: _ + "Immutable Ledger Block"!: _ + ... + } + }) + + #contentType: "application/json" | "application/cbor" + + #contentEncoding: "br" + + #contentEncodings: [...#contentEncoding] + + #docType: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" + + #docIdOrVer: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" + + #metadataFormat: "UUIDv7" | "COSE Algorithm" | "HTTP Content Type" | "HTTP Content Encoding" | "Document Reference" | "Document Hash" + + #requiredOrOptional: "yes" | "optional" | "no" + + #metadataFieldDescription: string + + #metadataFieldSpec: close({ + format?: #metadataFormat + required?: #requiredOrOptional + "ref type"?: string + description?: #metadataFieldDescription + validation?: #metadataFieldDescription + }) + + #docDefinitionFields: null | bool | number | string | [...] | { + contentType?: #contentType + contentEncodings?: #contentEncodings + metadata?: close({ + id?: #metadataFieldSpec + ver?: #metadataFieldSpec + alg?: #metadataFieldSpec + "content type"?: #metadataFieldSpec + "content encoding"?: #metadataFieldSpec + ref?: #metadataFieldSpec + "ref hash"?: #metadataFieldSpec + template?: #metadataFieldSpec + }) + ... + } + + #docDefinition: { + @jsonschema(id="https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/docs/src/architecture/08_concepts/signed_doc/docDefinition") + ... + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.json b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.json new file mode 100644 index 0000000000..8c42d457fb --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.json @@ -0,0 +1,177 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/docs/src/architecture/08_concepts/signed_doc/signed_doc_defs.schema.json", + "title": "Signed Document Definitions Database", + "description": "Source of truth for definitions of all catalyst signed documents.", + "maintainers": [ + { + "name": "Catalyst Team", + "url": "https://projectcatalyst.io/" + } + ], + "x-changelog": { + "2025-02-10": [ + "First Version Created." + ] + }, + "additionalProperties": false, + "definitions": { + "contentType": { + "type": "string", + "description": "The content type used for this document payload.", + "enum": [ + "application/json", + "application/cbor" + ] + }, + "contentEncoding": { + "type": "string", + "description": "The ways this content can be encoded. By default all content allows for no encoding.", + "enum": [ + "br" + ] + }, + "contentEncodings": { + "type": "array", + "description": "All content encodings allowed for this document payload.", + "items": { + "$ref": "#/definitions/contentEncoding" + } + }, + "docType": { + "type": "string", + "format": "uuid", + "pattern": "^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" + }, + "docIdOrVer": { + "description": "The ID or version of the document", + "type": "string", + "format": "uuid", + "pattern": "^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" + }, + "metadataFormat": { + "type": "string", + "enum": [ + "UUIDv7", + "COSE Algorithm", + "HTTP Content Type", + "HTTP Content Encoding", + "Document Reference", + "Document Hash" + ] + }, + "requiredOrOptional": { + "type": "string", + "enum": [ + "yes", + "optional", + "no" + ] + }, + "metadataFieldDescription": { + "type": "string", + "format": "markdown" + }, + "metadataFieldSpec": { + "type": "object", + "additionalProperties": false, + "properties": { + "format": { + "$ref": "#/definitions/metadataFormat" + }, + "required": { + "$ref": "#/definitions/requiredOrOptional" + }, + "ref type": { + "type": "string" + }, + "description": { + "$ref": "#/definitions/metadataFieldDescription" + }, + "validation": { + "$ref": "#/definitions/metadataFieldDescription" + } + } + }, + "docDefinitionFields": { + "properties": { + "contentType": { + "$ref": "#/definitions/contentType" + }, + "contentEncodings": { + "$ref": "#/definitions/contentEncodings" + }, + "metadata": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "$ref": "#/definitions/metadataFieldSpec" + }, + "ver": { + "$ref": "#/definitions/metadataFieldSpec" + }, + "alg": { + "$ref": "#/definitions/metadataFieldSpec" + }, + "content type": { + "$ref": "#/definitions/metadataFieldSpec" + }, + "content encoding": { + "$ref": "#/definitions/metadataFieldSpec" + }, + "ref": { + "$ref": "#/definitions/metadataFieldSpec" + }, + "ref hash": { + "$ref": "#/definitions/metadataFieldSpec" + }, + "template": { + "$ref": "#/definitions/metadataFieldSpec" + } + } + } + } + }, + "docDefinition": { + "$id": "docDefinition", + "title": "Individual Document Definition", + "description": "A single document definition", + "type": "object" + } + }, + "properties": { + "default": { + "type": "object", + "title": "Default Document Definition", + "$ref": "#/definitions/docDefinitionFields", + "required": [ + "contentType", + "contentEncodings", + "metadata" + ] + }, + "docs": { + "type": "object", + "title": "Document Definition", + "patternProperties": { + ".*": { + "$ref": "#/definitions/docDefinition" + } + }, + "required": [ + "Proposal Template", + "Proposal", + "Proposal Action", + "Proposal Comment Template", + "Proposal Comment", + "Category Parameters", + "Campaign Parameters", + "Brand Parameters", + "Public Vote Tx V2", + "Private Vote Tx V2", + "Immutable Ledger Block" + ] + } + } +} \ No newline at end of file diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.yml b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.yml new file mode 100644 index 0000000000..c4e05524bf --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.yml @@ -0,0 +1,115 @@ +# yaml-language-server: $schema=./signed_doc_defs.schema.json + +# Default values applied to all documents unless otherwise re-defined. +default: + contentType: application/json + contentEncodings: + - br + metadata: + id: + format: UUIDv7 + required: yes + description: | + [Document ID]. + ver: + format: UUIDv7 + required: yes + description: | + [Document Version]. + alg: + format: COSE Algorithm + required: yes + description: | + [COSE Algorithm]. + content type: + format: HTTP Content Type + required: yes + description: | + [HTTP Content Type]. + content encoding: + format: HTTP Content Encoding + required: optional + description: | + [HTTP Content Encoding]. + ref: + format: Document Reference + description: | + This is a reference to another document. + The purpose of the `ref` will vary depending on the [Document Type]. + + The `ref` can be either a single [UUIDv7] or a [CBOR] Array of Two [UUIDv7]. + + If the `ref` is a single [UUID] v7, it is a reference to the document of that [Document Id]. + If the `ref` is a [CBOR] array, it has the form `[,]` where: + + * `` - the [UUIDv7] of the referenced documents [Document Id]. + * `` - the [UUIDv7] of the referenced documents [Document Ver]. + validation: | + For any document type, `ref` can refer to only 1 other document type. + The referenced document type *MUST* be different than the type of document `ref` appears in. + For example `ref` for a Proposal Comment Document, is always a Proposal type document. + + ref hash: + format: Document Hash + description: | + This is a cryptographically secured reference to another document. + + It consists of a single field: + + * `hash` - the [CBOR] tagged hash of the signed document. + All data within the signed document is hashed, excluding the signatures. + + This field is not used every time a [Document Reference] is used, + however if it is defined to be used then the [Document Reference] *MUST* also be used. + validation: | + The hash must match the hash of th document referenced by the [Document Reference]. + template: + format: Document Reference + description: | + This is a reference to another documen + validation: | + The referenced document must be a [Template Document]. + +docs: + Proposal Template: + type: 7808d2ba-d511-40af-84e8-c0d1625fdfdc + metadata: + ref: + required: no + ref hash: + required: no + template: + required: no + ref type: Proposal Template Template + + Proposal: + type: 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + metadata: + template: + + template type: json schema + required: yes + ref type: Proposal Template + category: required + + Proposal Action: + type: 5e60e623-ad02-4a1b-a1ac-406db978ee48 + Proposal Comment Template: + type: 0b8424d4-ebfd-46e3-9577-1775a69d290c + Proposal Comment: + type: b679ded3-0e7c-41ba-89f8-da62a17898ea + Category Parameters: + type: 48c20109-362a-4d32-9bba-e0a9cf8b45be + Campaign Parameters: + type: 0110ea96-a555-47ce-8408-36efe6ed6f7c + Brand Parameters: + type: 3e4808cc-c86e-467b-9702-d60baa9d1fca + Public Vote Tx V2: + type: 8de5586c-e998-4b95-8742-7be3c8592803 + contentType: application/cbor + Private Vote Tx V2: + type: e78ee18d-f380-44c1-a852-80aa6ecb07fe + contentType: application/cbor + Immutable Ledger Block: + type: d9e7e6ce-2401-4d7d-9492-f4f7c64241c3 + contentType: application/cbor diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/proposal_doc.cue b/docs/src/architecture/08_concepts/signed_doc/spec/proposal_doc.cue new file mode 100644 index 0000000000..f10c826fae --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/proposal_doc.cue @@ -0,0 +1,13 @@ +package signed_docs + +// Proposal Document Definition + +docs: #DocumentDefinitions & { + "Proposal": { + description: """ + # This is my description. + + * Its markdown + """ + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json new file mode 100644 index 0000000000..ae86d4c3be --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json @@ -0,0 +1,53 @@ +{ + "docs": { + "Template": { + "type": "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "id": { + "format": "UUIDv7", + "required": "yes" + }, + "ver": { + "format": "UUIDv7", + "required": "yes" + }, + "alg": { + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": [ + "application/schema+json", + "application/cddl" + ], + "ref": { + "format": "Document Reference", + "required": "optional", + "ref type": "Proposal" + }, + "content encoding": [ + "br" + ] + }, + "Proposal": { + "description": "# This is my description.\n\n* Its markdown", + "type": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "id": { + "format": "UUIDv7", + "required": "yes" + }, + "ver": { + "format": "UUIDv7", + "required": "yes" + }, + "alg": { + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": [ + "application/json" + ], + "content encoding": [ + "br" + ] + } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.yaml b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.yaml new file mode 100644 index 0000000000..85382ae7e8 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.yaml @@ -0,0 +1,85 @@ +docs: + Proposal: + type: 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + description: |- + # This is my description. + + * Its markdown + headers: + alg: + coseLabel: 1 + required: optional + format: COSE Algorithm + content type: + coseLabel: 3 + format: IANA Media Type + content-encoding: + coseLabel: content-encoding + format: HTTP Content Encoding + required: optional + metadata: + id: + required: "yes" + ver: + required: "yes" + dogs: cats + Template: + type: 7808d2ba-d511-40af-84e8-c0d1625fdfdc + headers: + alg: + coseLabel: 1 + required: optional + format: COSE Algorithm + content type: + coseLabel: 3 + format: IANA Media Type + content-encoding: + coseLabel: content-encoding + format: HTTP Content Encoding + required: optional + metadata: + id: + required: "yes" + ver: + required: "yes" + dogs: cats + Comment: + type: b679ded3-0e7c-41ba-89f8-da62a17898ea + headers: + alg: + coseLabel: 1 + required: optional + format: COSE Algorithm + content type: + coseLabel: 3 + format: IANA Media Type + content-encoding: + coseLabel: content-encoding + format: HTTP Content Encoding + required: optional + metadata: + id: + required: "yes" + ver: + required: "yes" + dogs: cats + Action: + type: 5e60e623-ad02-4a1b-a1ac-406db978ee48 + headers: + alg: + coseLabel: 1 + required: optional + format: COSE Algorithm + content type: + coseLabel: 3 + format: IANA Media Type + content-encoding: + coseLabel: content-encoding + format: HTTP Content Encoding + required: optional + metadata: + id: + required: "yes" + ver: + required: "yes" + dogs: cats diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc_defs.cue b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc_defs.cue new file mode 100644 index 0000000000..b28015c7fc --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc_defs.cue @@ -0,0 +1,235 @@ +// Signed Document Definitions +// +// Base Types and Constraints +package signed_docs + +import "list" + +#optionalField: + "yes" | + "optional" | + *"excluded" + +// Supported Content Types (list of values) +#contentType: + *"application/json" | + "application/schema+json" | + "application/cbor" | + "application/cddl" + +// Format of a Metadata Field +#metadataFormat: + *"UUIDv7" | + "Document Reference" | + "Document Hash" + +// Canonical List of COSE header names +_coseHeaderNames: list.UniqueItems +_coseHeaderNames: [ + "alg", + "crit", + "content type", + "content-encoding", // Not strictly a true Cose Header, but we include it because of its relationship to `content type` + "kid", + "IV", + "Partial IV", + "counter signature", +] + +#coseHeaderFormat: + "COSE Algorithm" | + "IANA Media Type" | + "HTTP Content Encoding" + +// Canonical List of all valid metadata names +_metadataNames: list.UniqueItems +_metadataNames: [ + "id", + "ver", + "ref", + "ref_hash", + "template", + "reply", +] + +// 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] + +// A UUIDv4 formatted string regex +#uuidv4: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" + +// A uuidv7 formatted string regex +#uuidv7: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" + +// Document Type must be a valid UUIDv4 +#docType: #uuidv4 + +// Document ID or Version must be a valid UUIDv7 +#docIdOrVer: #uuidv7 + +// Definition of a metadata field. +#metadataField: { + // Format of the field. + format: #metadataFormat + // Is the field required to be present. + required: #optionalField + if format == "Document Reference" { + // If the field is Type of Document Reference, what document/s does it refer to. + "ref type": #DocumentName | [#DocumentName, #DocumentName, ...#DocumentName] + } + + // Optional markdown description of the field. + description?: string + // Optional notes about validating the field. + validation?: string + + if format == "Template" { + // What the template_ref must point to in the template for it to be valid. + template_ref: #DocumentName + } +} + +#coseField: { + coseLabel: int | string + description: "Default cryptographic algorithm to use" + required: #optionalField | *"yes" + format: #coseHeaderFormat + if format == "IANA Media Types" { + "value": "IANA" + //"value": { + // [...#contentType] | *[#contentType] + //} + } + if format == "HTTP Content Encoding" { + "value": #contentEncoding + } + +} + +// Metadata Fields that are required for every signed document +#coseHeaders: { + [_coseHeaderNames]: #coseField +} +#coseHeaders: { + // Default Signature Algorithm + alg: { + coseLabel: 1 + required: "optional" + format: "COSE Algorithm" + } + + // Documents content type + "content type": { + coseLabel: 3 + format: "IANA Media Type" + } + // Allowed content encodings + "content-encoding": { + coseLabel: "content-encoding" + format: "HTTP Content Encoding" + required: "optional" + } +} + +// Metadata fields that are optional +#metadataStruct: { + [_metadataNames]: #metadataField +} +#metadata: #metadataStruct & { + // Document ID + id: #metadataField & { + required: "yes" + } + // Document Version + ver: { + required: "yes" + } + + ref?: { + format: "Document Reference" + } + // "ref_hash"?: string`` + template?: { + format: "Document Reference" + } + +} + +#templateMetadata: { + [_metadataNames]: #metadataField +} +#templateMetadata: { + "template doc": { + format: "Document Reference" + required: "yes" + description: """ + Metadata only in Template documents. + Defines what type of document may use this template. + """ + } + + "template ref": { + format: "Document Reference" + required: "yes" + description: """ + Metadata only in Template documents. + Defines what the `ref` field of the document using the template must be. + Prevents a Document using the wrong kind of template. + """ + } + +} + +// Individual Signed Document Definition +#signedDocument: { + // The Document Type Identifier + type!: #docType + + // The description of this document. Markdown Supported. + description?: string + + // Fixed headers in every document + headers: #coseHeaders + + // The Metadata fields in this document (non cose standard) + metadata: #metadata + + //if type == "Template" { + // The Metadata fields in this document (non cose standard) + //metadata: #templateMetadata + //} +} + +// Ensure that all Document IDs are Unique. +// See: all_docs.cue for a list of all known document types. +_allTypes: list.UniqueItems +_allTypes: [...#docType] & [ + for _, v in _allDocs {v}, +] + +// List of all the document names we have defined. +_allDocNames: or([ + for k, _ in _allDocs {k}, +]) + +// We can only define known documents in the document definitions object +#DocumentDefinitions: { + [_allDocNames]: #signedDocument +} + +// Individual Valid Document Name constraint. +#DocumentName: _allDocNames + +// Default Definitions for all documents. +// Customize each document type in its own `.cue` file. +docs: #DocumentDefinitions & { + for k, v in _allDocs { + (k): { + type: v + } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/template_doc.cue b/docs/src/architecture/08_concepts/signed_doc/spec/template_doc.cue new file mode 100644 index 0000000000..79ed0a9931 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/template_doc.cue @@ -0,0 +1,20 @@ +package signed_docs + +// Proposal Document Definition + +docs: #DocumentDefinitions & { + "Template": { + headers: + "content type": { + //value: [ + // "application/schema+json", + // "application/cddl", + //] + } + + // "template": { + // required: "optional" + // "ref type": "Template" + // } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index eb3469f241..c7cd60aabe 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -14,7 +14,7 @@ | 7e8f5fa2-44ce-49c8-bfd5-02af42c179a3 | `37(h'7e8f5fa244ce49c8bfd502af42c179a3')` | Campaign Parameters Template | [Brotli] Compressed [JSON Schema] | *TBD* | | 3e4808cc-c86e-467b-9702-d60baa9d1fca | `37(h'3e4808ccc86e467b9702d60baa9d1fca')` | Brand Parameters Document | [Brotli] Compressed [JSON] | *TBD* | | fd3c1735-80b1-4eea-8d63-5f436d97ea31 | `37(h'fd3c173580b14eea8d635f436d97ea31')` | Brand Parameters Template | [Brotli] Compressed [JSON Schema] | *TBD* | -| 5e60e623-ad02-4a1b-a1ac-406db978ee48 | `37(h'5e60e623ad024a1ba1ac406db978ee48')` | Proposal Action Document | *TBD* | *TBD* | +| 5e60e623-ad02-4a1b-a1ac-406db978ee48 | `37(h'5e60e623ad024a1ba1ac406db978ee48')` | Proposal Action Document | [Brotli] Compressed [JSON] | *TBD* | | 8de5586c-e998-4b95-8742-7be3c8592803 | `37(h'8DE5586CE9984B9587427BE3C8592803')` | Public Vote Tx V2 | [Brotli] Compressed [CBOR] | [Public Vote Tx V2 Spec](./../catalyst_voting/v2.md#public-vote) | | e78ee18d-f380-44c1-a852-80aa6ecb07fe | `37(h'E78EE18DF38044C1A85280AA6ECB07FE')` | Private Vote Tx V2 | [Brotli] Compressed [CBOR] | [Private Vote Tx V2 Spec](./../catalyst_voting/v2.md#private-vote) | | d9e7e6ce-2401-4d7d-9492-f4f7c64241c3 | `37(h'D9E7E6CE24014D7D9492F4F7C64241C3')` | Immutable Ledger Block | [Brotli] Compressed [CBOR] | [Immutable Ledger Block Spec](./../immutable_ledger/ledger.md#block-structure) | diff --git a/docs/src/architecture/08_concepts/signed_doc/validation.md b/docs/src/architecture/08_concepts/signed_doc/validation.md new file mode 100644 index 0000000000..ee85160032 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/validation.md @@ -0,0 +1,23 @@ +--- +Title: Catalyst Signed Documents - Validation Summary +Category: Catalyst +Status: Proposed +Authors: + - Steven Johnson +Implementors: + - Catalyst Fund 14 +Discussions: [] +Created: 2024-12-29 +License: CC-BY-4.0 +--- + +This is a list of Metadata fields that apply to each document type, and how they are to be validated. + +| Document Type |`ref` | `ref_hash` | `template` | `reply` | `section` | `brand_id` | `campaign_id` | `category_id` | +| ------------- | ----- | ---------- | --------- | ------- | --------- | ---------- | ------------ | ----------------- | +| Proposal | None | `p` | `p` | `p` | `p` | `p` | `p` | `p` | +| Proposal Template | +| Comment | `c` | `p` | `p` | `p` | `p` | `p` | `p` | `p` | `p` | + + +[Proposal]: \ No newline at end of file From 011b6f1ba9558b0cd17d144d437c135082c5b057 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 16 Feb 2025 20:06:23 +0400 Subject: [PATCH 02/35] docs: wip --- .../08_concepts/signed_doc/spec/Justfile | 2 +- .../08_concepts/signed_doc/spec/all_docs.cue | 11 - .../signed_doc/spec/def_cose_headers.cue | 85 +++++++ .../signed_doc/spec/def_metadata.cue | 185 ++++++++++++++ .../signed_doc/spec/def_signed_doc.cue | 76 ++++++ .../08_concepts/signed_doc/spec/doc_all.cue | 30 +++ .../signed_doc/spec/doc_template.cue | 22 ++ .../signed_doc/spec/signed_doc.json | 227 ++++++++++++++--- .../signed_doc/spec/signed_doc.yaml | 85 ------- .../signed_doc/spec/signed_doc_defs.cue | 235 ------------------ .../signed_doc/temp/proposal_doc.cue | 13 + .../{spec => temp}/template_doc.cue | 0 12 files changed, 600 insertions(+), 371 deletions(-) delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/all_docs.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/doc_template.cue delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.yaml delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/signed_doc_defs.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/temp/proposal_doc.cue rename docs/src/architecture/08_concepts/signed_doc/{spec => temp}/template_doc.cue (100%) diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/Justfile b/docs/src/architecture/08_concepts/signed_doc/spec/Justfile index 15348de834..59eecf321b 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/Justfile +++ b/docs/src/architecture/08_concepts/signed_doc/spec/Justfile @@ -16,7 +16,7 @@ check: format # Fix and Check Markdown files regenerate: check - cue export -f -s -p signed_docs --out yaml --outfile signed_doc.yaml + cue export -f -s -p signed_docs --out json --outfile signed_doc.json # Pre Push Checks - intended to be run by a git pre-push hook. pre-push: regenerate diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/all_docs.cue b/docs/src/architecture/08_concepts/signed_doc/spec/all_docs.cue deleted file mode 100644 index f1ceebb6d8..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/all_docs.cue +++ /dev/null @@ -1,11 +0,0 @@ -// Master list of all document types. -package signed_docs - -// Source of truth for ALL Document Types and their matching UUID's. -// Format is : : -_allDocs: { - "Template": "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - "Proposal": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" - "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea" - "Action": "5e60e623-ad02-4a1b-a1ac-406db978ee48" -} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue b/docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue new file mode 100644 index 0000000000..508e540f72 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue @@ -0,0 +1,85 @@ +// Signed Document Definitions +// +// COSE Headers and Constraints +package signed_docs + +import "list" + +// Supported Content Types (list of values) +#contentType: + *"application/json" | + "application/schema+json" | + "application/cbor" | + "application/cddl" + +// 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: [ + "alg", + "crit", + "content type", + "content-encoding", // Not strictly a true Cose Header, but we include it because of its relationship to `content type` + "kid", + "IV", + "Partial IV", + "counter signature", +] + +_allCoseHeaderNames: or([ + for k in _coseHeaderNames {k}, +]) + +#coseHeaderFormat: + "COSE Algorithm" | + "IANA Media Type" | + "HTTP Content Encoding" + +#coseField: { + coseLabel: int | string + description: string + required: #optionalField | *"yes" + format: #coseHeaderFormat + if format == "IANA Media Type" { + "value": { + *[#contentType] | [...#contentType]} + } + + if format == "HTTP Content Encoding" { + "value": #contentEncoding + } +} + +// Metadata Fields that are required for every signed document +#coseHeaders: { + [_allCoseHeaderNames]: #coseField +} +_coseHeaders: #coseHeaders & { + // Default Signature Algorithm + alg: { + coseLabel: 1 + required: "optional" + format: "COSE Algorithm" + description: "Default cryptographic signature algorithm" + } + + // Documents content type + "content type": { + coseLabel: 3 + format: "IANA Media Type" + description: "IANA Media Type/s allowed in the Payload" + } + // Allowed content encodings + "content-encoding": { + coseLabel: "content-encoding" + format: "HTTP Content Encoding" + required: "optional" + description: "Supported HTTP Encodings of the Payload" + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue b/docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue new file mode 100644 index 0000000000..8be6c9936f --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue @@ -0,0 +1,185 @@ +// Signed Document Definitions +// +// Metadata Types and Constraints +package signed_docs + +import "list" + +// Format of a Metadata Field +#metadataFormat: + *"UUIDv7" | + "Document Reference" | + "Document Hash" | + "Section Reference" | + "Collaborators Reference List" + +// Canonical List of all valid metadata names +_metadataNames: list.UniqueItems +_metadataNames: [ + "id", + "ver", + "ref", + "ref_hash", + "ref_type", + "template", + "template_doc", + "reply", + "section", + "collaborators", + "brand_id", + "campaign_id", + "election_id", + "category_id", +] + +_allMetadataNames: or([ + for k in _metadataNames {k}, +]) +// Definition of a metadata field. +#metadataField: { + // Format of the field. + format: #metadataFormat + if format == "Document Reference" { + ref: { + type: [#DocumentName, ...#DocumentName] + if list.Contains(type, "Template") { + // What the template_ref must point to in the template for it to be valid. + template_ref?: #DocumentName + // What media type must the template be + template_media_type?: #contentType + } + } + } + + // Is the field required to be present. + required: #optionalField + + // Markdown description of the field. + description: string + // Optional notes about validating the field. + validation?: string +} + +// Metadata fields that are optional +#metadataStruct: { + [_allMetadataNames]: #metadataField +} +_metadata: #metadataStruct & { + // Document ID + id: #metadataField & { + required: "yes" + description: "Document ID, created the first time the document is created." + } + // Document Version + ver: { + required: "yes" + description: """ + ## Document Version + + The unique version of the document. + The first version of the document must set `ver` == `id` + """ + + validation: """ + The document version must always be >= the document ID. + """ + } + + ref?: { + format: "Document Reference" + } + + if ref != _|_ { + ref_hash?: { + format: "Document Hash" + } + } + + // "ref_hash"?: string`` + template?: { + format: "Document Reference" + description: "Reference to the template used to create and/or validate this document." + validation: "The document payload is not valid if it does not validate completely against the referenced template." + ref: { + type: ["Template"] + template_ref: "Template" + template_media_type: "application/schema+json" + } + } + + template_doc?: { + format: "Document Reference" + required: "yes" + description: """ + Metadata only in Template documents. + Defines what type of document may use this template. + """ + ref: { + type: _allDocNamesList + template_ref: "Template" + template_media_type: "application/schema+json" + } + } + + reply?: { + format: "Document Reference" + required: "optional" + description: """ + Reference to a Comment document type being referred to. + """ + validation: """ + The `ref` of the `reply` document must be the same as + the original comment document. + """ + } + + section?: { + format: "Section Reference" + required: "optional" + description: """ + A Reference to the original document, or the comment being replied to. + """ + validation: """ + For a non-reply this must be a valid section reference into the referenced document. + For a reply, this must be a valid section reference into the comment being replied to. + """ + } + + collaborators?: { + format: "Collaborators Reference List" + required: "optional" + description: """ + 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. + """ + 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. + """ + } + + brand_id?: { + format: "Document Reference" + required: "optional" + description: "A reference to the Brand Parameters Document this document lies under." + } + + campaign_id?: { + format: "Document Reference" + required: "optional" + description: "A reference to the Campaign Parameters Document this document lies under." + } + + election_id?: { + format: "Document Reference" + required: "optional" + description: "A reference to the Election Parameters Document this document lies under." + } + + category_id?: { + format: "Document Reference" + required: "optional" + description: "A reference to the Category Parameters Document this document lies under." + } + +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue b/docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue new file mode 100644 index 0000000000..8bfbe1a769 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue @@ -0,0 +1,76 @@ +// Signed Document Definitions +// +// Base Types and Constraints +package signed_docs + +#optionalField: + "yes" | + "optional" | + *"excluded" + +// A UUIDv4 formatted string regex +#uuidv4: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" + +// A uuidv7 formatted string regex +#uuidv7: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" + +// Document Type must be a valid UUIDv4 +#docType: #uuidv4 + +// Document ID or Version must be a valid UUIDv7 +#docIdOrVer: #uuidv7 + +#templateMetadata: { + [_metadataNames]: #metadataField +} +#templateMetadata: { + "template doc": { + format: "Document Reference" + required: "yes" + description: """ + Metadata only in Template documents. + Defines what type of document may use this template. + """ + } + + "template ref": { + format: "Document Reference" + required: "yes" + description: """ + Metadata only in Template documents. + Defines what the `ref` field of the document using the template must be. + Prevents a Document using the wrong kind of template. + """ + } + +} + +// Individual Signed Document Definition +#signedDocument: { + // The Document Type Identifier + type!: #docType + + // The description of this document. Markdown Supported. + description?: string + + // Fixed headers in every document + headers: _coseHeaders + + // The Metadata fields in this document (non cose standard) + metadata: _metadata +} + +// We can only define known documents in the document definitions object +#DocumentDefinitions: { + [_allDocNames]: #signedDocument +} + +// Default Definitions for all documents. +// Customize each document type in its own `.cue` file. +docs: #DocumentDefinitions & { + for k, v in _allDocs { + (k): { + type: v + } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue b/docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue new file mode 100644 index 0000000000..2fedd7c435 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue @@ -0,0 +1,30 @@ +// Master list of all document types. +package signed_docs + +import "list" + +// Source of truth for ALL Document Types and their matching UUID's. +// Format is : : +_allDocs: { + "Template": "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + "Proposal": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea" + "Action": "5e60e623-ad02-4a1b-a1ac-406db978ee48" +} + +// Ensure that all Document IDs are Unique. +// See: all_docs.cue for a list of all known document types. +_allTypes: list.UniqueItems +_allTypes: [...#docType] & [ + for _, v in _allDocs {v}, +] + +_allDocNamesList: [...string] & [ + for k, _ in _allDocs {k}, +] + +// List of all the document names we have defined. +_allDocNames: or(_allDocNamesList) + +// Individual Valid Document Name constraint. +#DocumentName: _allDocNames diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_template.cue b/docs/src/architecture/08_concepts/signed_doc/spec/doc_template.cue new file mode 100644 index 0000000000..5c0e8b26bd --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/doc_template.cue @@ -0,0 +1,22 @@ +package signed_docs + +// Proposal Document Definition + +docs: #DocumentDefinitions & { + "Template": { + headers: + "content type": { + value: [ + "application/schema+json", + "application/cddl", + ] + } + + metadata: { + template: { + required: "optional" + } + template_doc: {} + } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json index ae86d4c3be..de10fc5ee7 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json +++ b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json @@ -2,52 +2,201 @@ "docs": { "Template": { "type": "7808d2ba-d511-40af-84e8-c0d1625fdfdc", - "id": { - "format": "UUIDv7", - "required": "yes" + "headers": { + "alg": { + "coseLabel": 1, + "required": "optional", + "format": "COSE Algorithm", + "description": "Default cryptographic signature algorithm" + }, + "content type": { + "value": [ + "application/schema+json", + "application/cddl" + ], + "coseLabel": 3, + "format": "IANA Media Type", + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "value": [ + "br" + ], + "format": "HTTP Content Encoding", + "required": "optional", + "description": "Supported HTTP Encodings of the Payload" + } }, - "ver": { - "format": "UUIDv7", - "required": "yes" - }, - "alg": { - "format": "COSE Algorithm", - "required": "optional" - }, - "content type": [ - "application/schema+json", - "application/cddl" - ], - "ref": { - "format": "Document Reference", - "required": "optional", - "ref type": "Proposal" - }, - "content encoding": [ - "br" - ] + "metadata": { + "id": { + "format": "UUIDv7", + "required": "yes", + "description": "Document ID, created the first time the document is created." + }, + "ver": { + "format": "UUIDv7", + "required": "yes", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + }, + "template": { + "format": "Document Reference", + "required": "optional", + "description": "Reference to the template used to create and/or validate this document.", + "validation": "The document payload is not valid if it does not validate completely against the referenced template.", + "ref": { + "type": [ + "Template" + ], + "template_ref": "Template", + "template_media_type": "application/schema+json" + } + }, + "template_doc": { + "format": "Document Reference", + "required": "yes", + "description": "Metadata only in Template documents.\nDefines what type of document may use this template.", + "ref": { + "type": [ + "Template", + "Proposal", + "Comment", + "Action" + ], + "template_ref": "Template", + "template_media_type": "application/schema+json" + } + } + } }, "Proposal": { - "description": "# This is my description.\n\n* Its markdown", "type": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "id": { - "format": "UUIDv7", - "required": "yes" + "description": "# This is my description.\n\n* Its markdown", + "headers": { + "alg": { + "coseLabel": 1, + "required": "optional", + "format": "COSE Algorithm", + "description": "Default cryptographic signature algorithm" + }, + "content type": { + "coseLabel": 3, + "value": [ + "application/json" + ], + "format": "IANA Media Type", + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "value": [ + "br" + ], + "format": "HTTP Content Encoding", + "required": "optional", + "description": "Supported HTTP Encodings of the Payload" + } }, - "ver": { - "format": "UUIDv7", - "required": "yes" + "metadata": { + "id": { + "format": "UUIDv7", + "required": "yes", + "description": "Document ID, created the first time the document is created." + }, + "ver": { + "format": "UUIDv7", + "required": "yes", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + } + } + }, + "Comment": { + "type": "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "headers": { + "alg": { + "coseLabel": 1, + "required": "optional", + "format": "COSE Algorithm", + "description": "Default cryptographic signature algorithm" + }, + "content type": { + "coseLabel": 3, + "value": [ + "application/json" + ], + "format": "IANA Media Type", + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "value": [ + "br" + ], + "format": "HTTP Content Encoding", + "required": "optional", + "description": "Supported HTTP Encodings of the Payload" + } }, - "alg": { - "format": "COSE Algorithm", - "required": "optional" + "metadata": { + "id": { + "format": "UUIDv7", + "required": "yes", + "description": "Document ID, created the first time the document is created." + }, + "ver": { + "format": "UUIDv7", + "required": "yes", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + } + } + }, + "Action": { + "type": "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "headers": { + "alg": { + "coseLabel": 1, + "required": "optional", + "format": "COSE Algorithm", + "description": "Default cryptographic signature algorithm" + }, + "content type": { + "coseLabel": 3, + "value": [ + "application/json" + ], + "format": "IANA Media Type", + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "value": [ + "br" + ], + "format": "HTTP Content Encoding", + "required": "optional", + "description": "Supported HTTP Encodings of the Payload" + } }, - "content type": [ - "application/json" - ], - "content encoding": [ - "br" - ] + "metadata": { + "id": { + "format": "UUIDv7", + "required": "yes", + "description": "Document ID, created the first time the document is created." + }, + "ver": { + "format": "UUIDv7", + "required": "yes", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + } + } } } } diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.yaml b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.yaml deleted file mode 100644 index 85382ae7e8..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.yaml +++ /dev/null @@ -1,85 +0,0 @@ -docs: - Proposal: - type: 0ce8ab38-9258-4fbc-a62e-7faa6e58318f - description: |- - # This is my description. - - * Its markdown - headers: - alg: - coseLabel: 1 - required: optional - format: COSE Algorithm - content type: - coseLabel: 3 - format: IANA Media Type - content-encoding: - coseLabel: content-encoding - format: HTTP Content Encoding - required: optional - metadata: - id: - required: "yes" - ver: - required: "yes" - dogs: cats - Template: - type: 7808d2ba-d511-40af-84e8-c0d1625fdfdc - headers: - alg: - coseLabel: 1 - required: optional - format: COSE Algorithm - content type: - coseLabel: 3 - format: IANA Media Type - content-encoding: - coseLabel: content-encoding - format: HTTP Content Encoding - required: optional - metadata: - id: - required: "yes" - ver: - required: "yes" - dogs: cats - Comment: - type: b679ded3-0e7c-41ba-89f8-da62a17898ea - headers: - alg: - coseLabel: 1 - required: optional - format: COSE Algorithm - content type: - coseLabel: 3 - format: IANA Media Type - content-encoding: - coseLabel: content-encoding - format: HTTP Content Encoding - required: optional - metadata: - id: - required: "yes" - ver: - required: "yes" - dogs: cats - Action: - type: 5e60e623-ad02-4a1b-a1ac-406db978ee48 - headers: - alg: - coseLabel: 1 - required: optional - format: COSE Algorithm - content type: - coseLabel: 3 - format: IANA Media Type - content-encoding: - coseLabel: content-encoding - format: HTTP Content Encoding - required: optional - metadata: - id: - required: "yes" - ver: - required: "yes" - dogs: cats diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc_defs.cue b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc_defs.cue deleted file mode 100644 index b28015c7fc..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc_defs.cue +++ /dev/null @@ -1,235 +0,0 @@ -// Signed Document Definitions -// -// Base Types and Constraints -package signed_docs - -import "list" - -#optionalField: - "yes" | - "optional" | - *"excluded" - -// Supported Content Types (list of values) -#contentType: - *"application/json" | - "application/schema+json" | - "application/cbor" | - "application/cddl" - -// Format of a Metadata Field -#metadataFormat: - *"UUIDv7" | - "Document Reference" | - "Document Hash" - -// Canonical List of COSE header names -_coseHeaderNames: list.UniqueItems -_coseHeaderNames: [ - "alg", - "crit", - "content type", - "content-encoding", // Not strictly a true Cose Header, but we include it because of its relationship to `content type` - "kid", - "IV", - "Partial IV", - "counter signature", -] - -#coseHeaderFormat: - "COSE Algorithm" | - "IANA Media Type" | - "HTTP Content Encoding" - -// Canonical List of all valid metadata names -_metadataNames: list.UniqueItems -_metadataNames: [ - "id", - "ver", - "ref", - "ref_hash", - "template", - "reply", -] - -// 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] - -// A UUIDv4 formatted string regex -#uuidv4: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" - -// A uuidv7 formatted string regex -#uuidv7: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" - -// Document Type must be a valid UUIDv4 -#docType: #uuidv4 - -// Document ID or Version must be a valid UUIDv7 -#docIdOrVer: #uuidv7 - -// Definition of a metadata field. -#metadataField: { - // Format of the field. - format: #metadataFormat - // Is the field required to be present. - required: #optionalField - if format == "Document Reference" { - // If the field is Type of Document Reference, what document/s does it refer to. - "ref type": #DocumentName | [#DocumentName, #DocumentName, ...#DocumentName] - } - - // Optional markdown description of the field. - description?: string - // Optional notes about validating the field. - validation?: string - - if format == "Template" { - // What the template_ref must point to in the template for it to be valid. - template_ref: #DocumentName - } -} - -#coseField: { - coseLabel: int | string - description: "Default cryptographic algorithm to use" - required: #optionalField | *"yes" - format: #coseHeaderFormat - if format == "IANA Media Types" { - "value": "IANA" - //"value": { - // [...#contentType] | *[#contentType] - //} - } - if format == "HTTP Content Encoding" { - "value": #contentEncoding - } - -} - -// Metadata Fields that are required for every signed document -#coseHeaders: { - [_coseHeaderNames]: #coseField -} -#coseHeaders: { - // Default Signature Algorithm - alg: { - coseLabel: 1 - required: "optional" - format: "COSE Algorithm" - } - - // Documents content type - "content type": { - coseLabel: 3 - format: "IANA Media Type" - } - // Allowed content encodings - "content-encoding": { - coseLabel: "content-encoding" - format: "HTTP Content Encoding" - required: "optional" - } -} - -// Metadata fields that are optional -#metadataStruct: { - [_metadataNames]: #metadataField -} -#metadata: #metadataStruct & { - // Document ID - id: #metadataField & { - required: "yes" - } - // Document Version - ver: { - required: "yes" - } - - ref?: { - format: "Document Reference" - } - // "ref_hash"?: string`` - template?: { - format: "Document Reference" - } - -} - -#templateMetadata: { - [_metadataNames]: #metadataField -} -#templateMetadata: { - "template doc": { - format: "Document Reference" - required: "yes" - description: """ - Metadata only in Template documents. - Defines what type of document may use this template. - """ - } - - "template ref": { - format: "Document Reference" - required: "yes" - description: """ - Metadata only in Template documents. - Defines what the `ref` field of the document using the template must be. - Prevents a Document using the wrong kind of template. - """ - } - -} - -// Individual Signed Document Definition -#signedDocument: { - // The Document Type Identifier - type!: #docType - - // The description of this document. Markdown Supported. - description?: string - - // Fixed headers in every document - headers: #coseHeaders - - // The Metadata fields in this document (non cose standard) - metadata: #metadata - - //if type == "Template" { - // The Metadata fields in this document (non cose standard) - //metadata: #templateMetadata - //} -} - -// Ensure that all Document IDs are Unique. -// See: all_docs.cue for a list of all known document types. -_allTypes: list.UniqueItems -_allTypes: [...#docType] & [ - for _, v in _allDocs {v}, -] - -// List of all the document names we have defined. -_allDocNames: or([ - for k, _ in _allDocs {k}, -]) - -// We can only define known documents in the document definitions object -#DocumentDefinitions: { - [_allDocNames]: #signedDocument -} - -// Individual Valid Document Name constraint. -#DocumentName: _allDocNames - -// Default Definitions for all documents. -// Customize each document type in its own `.cue` file. -docs: #DocumentDefinitions & { - for k, v in _allDocs { - (k): { - type: v - } - } -} diff --git a/docs/src/architecture/08_concepts/signed_doc/temp/proposal_doc.cue b/docs/src/architecture/08_concepts/signed_doc/temp/proposal_doc.cue new file mode 100644 index 0000000000..f10c826fae --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/temp/proposal_doc.cue @@ -0,0 +1,13 @@ +package signed_docs + +// Proposal Document Definition + +docs: #DocumentDefinitions & { + "Proposal": { + description: """ + # This is my description. + + * Its markdown + """ + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/template_doc.cue b/docs/src/architecture/08_concepts/signed_doc/temp/template_doc.cue similarity index 100% rename from docs/src/architecture/08_concepts/signed_doc/spec/template_doc.cue rename to docs/src/architecture/08_concepts/signed_doc/temp/template_doc.cue From 4292ad18cc89c59d5764b205dc00fc9b28c94d26 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 27 Feb 2025 19:25:00 +0400 Subject: [PATCH 03/35] feat: wip --- .../signed_doc/spec/def_cose_headers.cue | 9 +- .../signed_doc/spec/def_metadata.cue | 76 ++-- .../signed_doc/spec/def_signed_doc.cue | 30 +- .../08_concepts/signed_doc/spec/doc_all.cue | 64 ++- .../signed_doc/spec/doc_proposal.cue | 34 ++ .../spec/doc_proposal_meta_template copy.cue | 29 ++ .../signed_doc/spec/doc_proposal_template.cue | 37 ++ .../signed_doc/spec/signed_doc.json | 363 ++++++++++++++---- .../spec/{ => temp}/doc_template.cue | 0 .../spec/{ => temp}/proposal_doc.cue | 0 .../{ => spec}/temp/template_doc.cue | 0 .../signed_doc/temp/proposal_doc.cue | 13 - 12 files changed, 493 insertions(+), 162 deletions(-) create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_meta_template copy.cue create mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_template.cue rename docs/src/architecture/08_concepts/signed_doc/spec/{ => temp}/doc_template.cue (100%) rename docs/src/architecture/08_concepts/signed_doc/spec/{ => temp}/proposal_doc.cue (100%) rename docs/src/architecture/08_concepts/signed_doc/{ => spec}/temp/template_doc.cue (100%) delete mode 100644 docs/src/architecture/08_concepts/signed_doc/temp/proposal_doc.cue diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue b/docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue index 508e540f72..925e1c7310 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue +++ b/docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue @@ -47,8 +47,7 @@ _allCoseHeaderNames: or([ required: #optionalField | *"yes" format: #coseHeaderFormat if format == "IANA Media Type" { - "value": { - *[#contentType] | [...#contentType]} + "value": #contentType } if format == "HTTP Content Encoding" { @@ -62,7 +61,7 @@ _allCoseHeaderNames: or([ } _coseHeaders: #coseHeaders & { // Default Signature Algorithm - alg: { + alg: #coseField & { coseLabel: 1 required: "optional" format: "COSE Algorithm" @@ -70,13 +69,13 @@ _coseHeaders: #coseHeaders & { } // Documents content type - "content type": { + "content type": #coseField & { coseLabel: 3 format: "IANA Media Type" description: "IANA Media Type/s allowed in the Payload" } // Allowed content encodings - "content-encoding": { + "content-encoding": #coseField & { coseLabel: "content-encoding" format: "HTTP Content Encoding" required: "optional" diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue b/docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue index 8be6c9936f..f588207ad9 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue +++ b/docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue @@ -20,9 +20,8 @@ _metadataNames: [ "ver", "ref", "ref_hash", - "ref_type", + "collation", "template", - "template_doc", "reply", "section", "collaborators", @@ -37,23 +36,15 @@ _allMetadataNames: or([ ]) // Definition of a metadata field. #metadataField: { + // Is the field required to be present. + required: #optionalField + // Format of the field. format: #metadataFormat if format == "Document Reference" { - ref: { - type: [#DocumentName, ...#DocumentName] - if list.Contains(type, "Template") { - // What the template_ref must point to in the template for it to be valid. - template_ref?: #DocumentName - // What media type must the template be - template_media_type?: #contentType - } - } + type: #DocumentName } - // Is the field required to be present. - required: #optionalField - // Markdown description of the field. description: string // Optional notes about validating the field. @@ -71,7 +62,7 @@ _metadata: #metadataStruct & { description: "Document ID, created the first time the document is created." } // Document Version - ver: { + ver: #metadataField & { required: "yes" description: """ ## Document Version @@ -85,43 +76,30 @@ _metadata: #metadataStruct & { """ } - ref?: { - format: "Document Reference" + ref?: #metadataField & { + format: "Document Reference" + description: "Reference to a Linked Document. This is the primary hierarchial reference to a related document." } + // IF we have a ref, we can optionally have a `ref_hash` if ref != _|_ { - ref_hash?: { + ref_hash?: #metadataField & { format: "Document Hash" } } - // "ref_hash"?: string`` - template?: { + collation?: #metadataField & { + format: "Document Collation Reference" + description: "Array of Collated Document References" + } + + template?: #metadataField & { format: "Document Reference" description: "Reference to the template used to create and/or validate this document." validation: "The document payload is not valid if it does not validate completely against the referenced template." - ref: { - type: ["Template"] - template_ref: "Template" - template_media_type: "application/schema+json" - } } - template_doc?: { - format: "Document Reference" - required: "yes" - description: """ - Metadata only in Template documents. - Defines what type of document may use this template. - """ - ref: { - type: _allDocNamesList - template_ref: "Template" - template_media_type: "application/schema+json" - } - } - - reply?: { + reply?: #metadataField & { format: "Document Reference" required: "optional" description: """ @@ -133,7 +111,7 @@ _metadata: #metadataStruct & { """ } - section?: { + section?: #metadataField & { format: "Section Reference" required: "optional" description: """ @@ -145,38 +123,44 @@ _metadata: #metadataStruct & { """ } - collaborators?: { + collaborators?: #metadataField & { format: "Collaborators Reference List" required: "optional" description: """ 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 new version of the document. """ 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. """ } - brand_id?: { + brand_id?: #metadataField & { format: "Document Reference" required: "optional" description: "A reference to the Brand Parameters Document this document lies under." } - campaign_id?: { + campaign_id?: #metadataField & { format: "Document Reference" required: "optional" description: "A reference to the Campaign Parameters Document this document lies under." } - election_id?: { + election_id?: #metadataField & { format: "Document Reference" required: "optional" description: "A reference to the Election Parameters Document this document lies under." } - category_id?: { + category_id?: #metadataField & { format: "Document Reference" required: "optional" description: "A reference to the Category Parameters Document this document lies under." diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue b/docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue index 8bfbe1a769..94b2204287 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue +++ b/docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue @@ -15,36 +15,11 @@ package signed_docs #uuidv7: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" // Document Type must be a valid UUIDv4 -#docType: #uuidv4 +#docType: [#uuidv4] | [#uuidv4, #uuidv4] | [#uuidv4, #uuidv4, #uuidv4] // Document ID or Version must be a valid UUIDv7 #docIdOrVer: #uuidv7 -#templateMetadata: { - [_metadataNames]: #metadataField -} -#templateMetadata: { - "template doc": { - format: "Document Reference" - required: "yes" - description: """ - Metadata only in Template documents. - Defines what type of document may use this template. - """ - } - - "template ref": { - format: "Document Reference" - required: "yes" - description: """ - Metadata only in Template documents. - Defines what the `ref` field of the document using the template must be. - Prevents a Document using the wrong kind of template. - """ - } - -} - // Individual Signed Document Definition #signedDocument: { // The Document Type Identifier @@ -53,6 +28,9 @@ package signed_docs // The description of this document. Markdown Supported. description?: string + // The description of this document. Markdown Supported. + validation?: string + // Fixed headers in every document headers: _coseHeaders diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue b/docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue index 2fedd7c435..ea993c08bf 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue +++ b/docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue @@ -3,13 +3,69 @@ package signed_docs import "list" +// 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" + "Category": "818938c3-3139-4daa-afe6-974c78488e95" +} + +// Ensure that all Document Type IDs are Unique. +// See: all_docs.cue for a list of all known document types. +_allDocTypeIDs: list.UniqueItems +_allDocTypeIDs: [...#uuidv4] & [ + for _, v in _allDocTypes {v}, +] + // Source of truth for ALL Document Types and their matching UUID's. // Format is : : _allDocs: { - "Template": "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - "Proposal": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" - "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea" - "Action": "5e60e623-ad02-4a1b-a1ac-406db978ee48" + "Proposal Meta Template": [ + _allDocTypes["Template"], // Template + _allDocTypes["Template"], // For Templates + _allDocTypes["Proposal"], // On Proposals + ] + "Proposal Template": [ + _allDocTypes["Template"], // Template + _allDocTypes["Proposal"], // For Proposals + ] + "Proposal": [ + _allDocTypes["Proposal"], + ] + "Proposal Comment Template": [ + _allDocTypes["Template"], // Template + _allDocTypes["Comment"], // For Comments + _allDocTypes["Proposal"], // On Proposals + ] + "Proposal Comment": [ + _allDocTypes["Comment"], // Comment + _allDocTypes["Proposal"], // For Proposals + ] + "Proposal Submission Action": + [ + _allDocTypes["Action"], // Action + _allDocTypes["Proposal"], // For Proposal + _allDocTypes["SubmissionAction"], // On Submission + ] + "Proposal Moderation Action": + [ + _allDocTypes["Action"], // Action + _allDocTypes["Proposal"], // For Proposal + _allDocTypes["ModerationAction"], // On Moderation + ] + "Comment Action Document": [ + _allDocTypes["Action"], // Action + _allDocTypes["Comment"], // For Comment + _allDocTypes["ModerationAction"], // On Moderation + ] + "Category Parameters": [ + _allDocTypes["Category"], + ] + } // Ensure that all Document IDs are Unique. diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal.cue b/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal.cue new file mode 100644 index 0000000000..4f254cce69 --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal.cue @@ -0,0 +1,34 @@ +package signed_docs + +// Proposal Document Definition + +docs: #DocumentDefinitions & { + "Proposal": { + description: """ + ## Proposal Document + + A Proposal is a document which describes a proposed solution or project to + address the criteria of a category within a campaign. + + The proposal itself is a draft document, it is not submitted for consideration + unless a `Proposal Submission Action` is submitted which references it. + + 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. + """ + + metadata: { + template: { + required: "yes" + type: "Proposal Template" + } + + category_id: { + required: "optional" + type: "Category Parameters" + } + } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_meta_template copy.cue b/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_meta_template copy.cue new file mode 100644 index 0000000000..f79be9df5b --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_meta_template copy.cue @@ -0,0 +1,29 @@ +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: { + category_id: { + required: "optional" + type: "Category Parameters" + } + } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_template.cue b/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_template.cue new file mode 100644 index 0000000000..92c77dad0f --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_template.cue @@ -0,0 +1,37 @@ +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" + } + + category_id: { + required: "optional" + type: "Category Parameters" + } + } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json index de10fc5ee7..f35497d005 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json +++ b/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json @@ -1,198 +1,425 @@ { "docs": { - "Template": { - "type": "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "Proposal": { + "type": [ + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ], + "description": "## Proposal Document\n\nA Proposal is a document which describes a proposed solution or project to\naddress the criteria of a category within a campaign.\n\nThe proposal itself is a draft document, it is not submitted for consideration\nunless a `Proposal Submission Action` is submitted which references it.\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.", "headers": { "alg": { "coseLabel": 1, + "description": "Default cryptographic signature algorithm", "required": "optional", - "format": "COSE Algorithm", - "description": "Default cryptographic signature algorithm" + "format": "COSE Algorithm" }, "content type": { + "coseLabel": 3, + "value": "application/json", + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes", + "format": "IANA Media Type" + }, + "content-encoding": { + "coseLabel": "content-encoding", "value": [ - "application/schema+json", - "application/cddl" + "br" ], + "description": "Supported HTTP Encodings of the Payload", + "required": "optional", + "format": "HTTP Content Encoding" + } + }, + "metadata": { + "id": { + "required": "yes", + "format": "UUIDv7", + "description": "Document ID, created the first time the document is created." + }, + "ver": { + "required": "yes", + "format": "UUIDv7", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + }, + "template": { + "required": "yes", + "format": "Document Reference", + "description": "Reference to the template used to create and/or validate this document.", + "type": "Proposal Template", + "validation": "The document payload is not valid if it does not validate completely against the referenced template." + }, + "category_id": { + "required": "optional", + "format": "Document Reference", + "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under." + } + } + }, + "Proposal Meta Template": { + "type": [ + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ], + "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.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "required": "optional", + "format": "COSE Algorithm" + }, + "content type": { + "value": "application/schema+json", "coseLabel": 3, - "format": "IANA Media Type", "description": "IANA Media Type/s allowed in the Payload", - "required": "yes" + "required": "yes", + "format": "IANA Media Type" }, "content-encoding": { "coseLabel": "content-encoding", "value": [ "br" ], - "format": "HTTP Content Encoding", + "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "description": "Supported HTTP Encodings of the Payload" + "format": "HTTP Content Encoding" } }, "metadata": { "id": { - "format": "UUIDv7", "required": "yes", + "format": "UUIDv7", "description": "Document ID, created the first time the document is created." }, "ver": { + "required": "yes", + "format": "UUIDv7", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + }, + "category_id": { + "required": "optional", + "format": "Document Reference", + "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under." + } + } + }, + "Proposal Template": { + "type": [ + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ], + "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.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "required": "optional", + "format": "COSE Algorithm" + }, + "content type": { + "value": "application/schema+json", + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes", + "format": "IANA Media Type" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "value": [ + "br" + ], + "description": "Supported HTTP Encodings of the Payload", + "required": "optional", + "format": "HTTP Content Encoding" + } + }, + "metadata": { + "id": { + "required": "yes", "format": "UUIDv7", + "description": "Document ID, created the first time the document is created." + }, + "ver": { "required": "yes", + "format": "UUIDv7", "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." }, "template": { - "format": "Document Reference", "required": "optional", + "format": "Document Reference", "description": "Reference to the template used to create and/or validate this document.", - "validation": "The document payload is not valid if it does not validate completely against the referenced template.", - "ref": { - "type": [ - "Template" - ], - "template_ref": "Template", - "template_media_type": "application/schema+json" - } - }, - "template_doc": { + "type": "Proposal Meta Template", + "validation": "The document payload is not valid if it does not validate completely against the referenced template." + }, + "category_id": { + "required": "optional", "format": "Document Reference", - "required": "yes", - "description": "Metadata only in Template documents.\nDefines what type of document may use this template.", - "ref": { - "type": [ - "Template", - "Proposal", - "Comment", - "Action" - ], - "template_ref": "Template", - "template_media_type": "application/schema+json" - } + "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under." } } }, - "Proposal": { - "type": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "description": "# This is my description.\n\n* Its markdown", + "Proposal Comment Template": { + "type": [ + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ], "headers": { "alg": { "coseLabel": 1, + "description": "Default cryptographic signature algorithm", "required": "optional", - "format": "COSE Algorithm", - "description": "Default cryptographic signature algorithm" + "format": "COSE Algorithm" }, "content type": { "coseLabel": 3, + "value": "application/json", + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes", + "format": "IANA Media Type" + }, + "content-encoding": { + "coseLabel": "content-encoding", "value": [ - "application/json" + "br" ], - "format": "IANA Media Type", + "description": "Supported HTTP Encodings of the Payload", + "required": "optional", + "format": "HTTP Content Encoding" + } + }, + "metadata": { + "id": { + "required": "yes", + "format": "UUIDv7", + "description": "Document ID, created the first time the document is created." + }, + "ver": { + "required": "yes", + "format": "UUIDv7", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + } + } + }, + "Proposal Comment": { + "type": [ + "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ], + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "required": "optional", + "format": "COSE Algorithm" + }, + "content type": { + "coseLabel": 3, + "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", - "required": "yes" + "required": "yes", + "format": "IANA Media Type" }, "content-encoding": { "coseLabel": "content-encoding", "value": [ "br" ], - "format": "HTTP Content Encoding", + "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "description": "Supported HTTP Encodings of the Payload" + "format": "HTTP Content Encoding" } }, "metadata": { "id": { - "format": "UUIDv7", "required": "yes", + "format": "UUIDv7", "description": "Document ID, created the first time the document is created." }, "ver": { - "format": "UUIDv7", "required": "yes", + "format": "UUIDv7", "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." } } }, - "Comment": { - "type": "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "Proposal Submission Action": { + "type": [ + "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "78927329-cfd9-4ea1-9c71-0e019b126a65" + ], "headers": { "alg": { "coseLabel": 1, + "description": "Default cryptographic signature algorithm", "required": "optional", - "format": "COSE Algorithm", - "description": "Default cryptographic signature algorithm" + "format": "COSE Algorithm" }, "content type": { "coseLabel": 3, + "value": "application/json", + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes", + "format": "IANA Media Type" + }, + "content-encoding": { + "coseLabel": "content-encoding", "value": [ - "application/json" + "br" ], - "format": "IANA Media Type", + "description": "Supported HTTP Encodings of the Payload", + "required": "optional", + "format": "HTTP Content Encoding" + } + }, + "metadata": { + "id": { + "required": "yes", + "format": "UUIDv7", + "description": "Document ID, created the first time the document is created." + }, + "ver": { + "required": "yes", + "format": "UUIDv7", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + } + } + }, + "Proposal Moderation Action": { + "type": [ + "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "a5d232b8-5e03-4117-9afd-be32b878fcdd" + ], + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "required": "optional", + "format": "COSE Algorithm" + }, + "content type": { + "coseLabel": 3, + "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", - "required": "yes" + "required": "yes", + "format": "IANA Media Type" }, "content-encoding": { "coseLabel": "content-encoding", "value": [ "br" ], - "format": "HTTP Content Encoding", + "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "description": "Supported HTTP Encodings of the Payload" + "format": "HTTP Content Encoding" } }, "metadata": { "id": { - "format": "UUIDv7", "required": "yes", + "format": "UUIDv7", "description": "Document ID, created the first time the document is created." }, "ver": { - "format": "UUIDv7", "required": "yes", + "format": "UUIDv7", "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." } } }, - "Action": { - "type": "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "Comment Action Document": { + "type": [ + "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "a5d232b8-5e03-4117-9afd-be32b878fcdd" + ], "headers": { "alg": { "coseLabel": 1, + "description": "Default cryptographic signature algorithm", "required": "optional", - "format": "COSE Algorithm", - "description": "Default cryptographic signature algorithm" + "format": "COSE Algorithm" }, "content type": { "coseLabel": 3, + "value": "application/json", + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes", + "format": "IANA Media Type" + }, + "content-encoding": { + "coseLabel": "content-encoding", "value": [ - "application/json" + "br" ], - "format": "IANA Media Type", + "description": "Supported HTTP Encodings of the Payload", + "required": "optional", + "format": "HTTP Content Encoding" + } + }, + "metadata": { + "id": { + "required": "yes", + "format": "UUIDv7", + "description": "Document ID, created the first time the document is created." + }, + "ver": { + "required": "yes", + "format": "UUIDv7", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + } + } + }, + "Category Parameters": { + "type": [ + "818938c3-3139-4daa-afe6-974c78488e95" + ], + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "required": "optional", + "format": "COSE Algorithm" + }, + "content type": { + "coseLabel": 3, + "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", - "required": "yes" + "required": "yes", + "format": "IANA Media Type" }, "content-encoding": { "coseLabel": "content-encoding", "value": [ "br" ], - "format": "HTTP Content Encoding", + "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "description": "Supported HTTP Encodings of the Payload" + "format": "HTTP Content Encoding" } }, "metadata": { "id": { - "format": "UUIDv7", "required": "yes", + "format": "UUIDv7", "description": "Document ID, created the first time the document is created." }, "ver": { - "format": "UUIDv7", "required": "yes", + "format": "UUIDv7", "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." } diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_template.cue b/docs/src/architecture/08_concepts/signed_doc/spec/temp/doc_template.cue similarity index 100% rename from docs/src/architecture/08_concepts/signed_doc/spec/doc_template.cue rename to docs/src/architecture/08_concepts/signed_doc/spec/temp/doc_template.cue diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/proposal_doc.cue b/docs/src/architecture/08_concepts/signed_doc/spec/temp/proposal_doc.cue similarity index 100% rename from docs/src/architecture/08_concepts/signed_doc/spec/proposal_doc.cue rename to docs/src/architecture/08_concepts/signed_doc/spec/temp/proposal_doc.cue diff --git a/docs/src/architecture/08_concepts/signed_doc/temp/template_doc.cue b/docs/src/architecture/08_concepts/signed_doc/spec/temp/template_doc.cue similarity index 100% rename from docs/src/architecture/08_concepts/signed_doc/temp/template_doc.cue rename to docs/src/architecture/08_concepts/signed_doc/spec/temp/template_doc.cue diff --git a/docs/src/architecture/08_concepts/signed_doc/temp/proposal_doc.cue b/docs/src/architecture/08_concepts/signed_doc/temp/proposal_doc.cue deleted file mode 100644 index f10c826fae..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/temp/proposal_doc.cue +++ /dev/null @@ -1,13 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Proposal": { - description: """ - # This is my description. - - * Its markdown - """ - } -} From 03edade880eff946bb0ae9651398c949b0571cdd Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 1 Mar 2025 20:51:47 +0400 Subject: [PATCH 04/35] feat: Signed Docs formal specs WIP --- .../08_concepts/signed_doc/spec/Justfile | 22 -- .../signed_doc/spec/temp/doc_template.cue | 22 -- .../signed_doc/spec/temp/proposal_doc.cue | 13 - .../signed_doc/spec/temp/template_doc.cue | 20 -- specs/Justfile | 29 ++ specs/cue.mod/module.cue | 4 + specs/generic/optional.cue | 7 + specs/generic/uuid.cue | 8 + .../signed_doc/spec => specs}/signed_doc.json | 330 +++++++++++++++++- .../signed_docs/cose_headers.cue | 8 +- .../signed_docs/docs/all.cue | 32 +- .../proposal_submission_action.schema.json | 36 ++ .../signed_docs/docs/proposal.cue | 24 ++ specs/signed_docs/docs/proposal_comment.cue | 51 +++ .../docs/proposal_comment_meta_template.cue | 52 +++ .../docs/proposal_comment_template.cue | 56 +++ .../docs/proposal_meta_template.cue | 24 ++ .../docs/proposal_submission_action.cue | 61 ++++ .../signed_docs/docs/proposal_template.cue | 20 ++ .../signed_docs/metadata.cue | 73 +++- specs/signed_docs/payload.cue | 9 + .../signed_docs/signed_doc.cue | 48 ++- specs/signed_docs/signers.cue | 76 ++++ 23 files changed, 878 insertions(+), 147 deletions(-) delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/Justfile delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/temp/doc_template.cue delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/temp/proposal_doc.cue delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/temp/template_doc.cue create mode 100644 specs/Justfile create mode 100644 specs/cue.mod/module.cue create mode 100644 specs/generic/optional.cue create mode 100644 specs/generic/uuid.cue rename {docs/src/architecture/08_concepts/signed_doc/spec => specs}/signed_doc.json (53%) rename docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue => specs/signed_docs/cose_headers.cue (93%) rename docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue => specs/signed_docs/docs/all.cue (74%) create mode 100644 specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json rename docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal.cue => specs/signed_docs/docs/proposal.cue (70%) create mode 100644 specs/signed_docs/docs/proposal_comment.cue create mode 100644 specs/signed_docs/docs/proposal_comment_meta_template.cue create mode 100644 specs/signed_docs/docs/proposal_comment_template.cue rename docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_meta_template copy.cue => specs/signed_docs/docs/proposal_meta_template.cue (50%) create mode 100644 specs/signed_docs/docs/proposal_submission_action.cue rename docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_template.cue => specs/signed_docs/docs/proposal_template.cue (68%) rename docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue => specs/signed_docs/metadata.cue (62%) create mode 100644 specs/signed_docs/payload.cue rename docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue => specs/signed_docs/signed_doc.cue (50%) create mode 100644 specs/signed_docs/signers.cue diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/Justfile b/docs/src/architecture/08_concepts/signed_doc/spec/Justfile deleted file mode 100644 index 59eecf321b..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/Justfile +++ /dev/null @@ -1,22 +0,0 @@ -# use with https://github.com/casey/just -# -# Developer convenience functions - -default: - @just --list --unsorted - -# Fiz (where possible) and format cue files -format: - cue fix signed_docs - cue fmt . - -# Check the signed document cue files are valid. -check: format - cue vet -p signed_docs -c - -# Fix and Check Markdown files -regenerate: check - cue export -f -s -p signed_docs --out json --outfile signed_doc.json - -# Pre Push Checks - intended to be run by a git pre-push hook. -pre-push: regenerate diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/temp/doc_template.cue b/docs/src/architecture/08_concepts/signed_doc/spec/temp/doc_template.cue deleted file mode 100644 index 5c0e8b26bd..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/temp/doc_template.cue +++ /dev/null @@ -1,22 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Template": { - headers: - "content type": { - value: [ - "application/schema+json", - "application/cddl", - ] - } - - metadata: { - template: { - required: "optional" - } - template_doc: {} - } - } -} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/temp/proposal_doc.cue b/docs/src/architecture/08_concepts/signed_doc/spec/temp/proposal_doc.cue deleted file mode 100644 index f10c826fae..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/temp/proposal_doc.cue +++ /dev/null @@ -1,13 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Proposal": { - description: """ - # This is my description. - - * Its markdown - """ - } -} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/temp/template_doc.cue b/docs/src/architecture/08_concepts/signed_doc/spec/temp/template_doc.cue deleted file mode 100644 index 79ed0a9931..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/temp/template_doc.cue +++ /dev/null @@ -1,20 +0,0 @@ -package signed_docs - -// Proposal Document Definition - -docs: #DocumentDefinitions & { - "Template": { - headers: - "content type": { - //value: [ - // "application/schema+json", - // "application/cddl", - //] - } - - // "template": { - // required: "optional" - // "ref type": "Template" - // } - } -} diff --git a/specs/Justfile b/specs/Justfile new file mode 100644 index 0000000000..78f7b3f27c --- /dev/null +++ b/specs/Justfile @@ -0,0 +1,29 @@ +# use with https://github.com/casey/just +# +# Developer convenience functions + +# required to get cuelang to enable file embedding +export CUE_EXPERIMENT := "embed" +default: + @just --list --unsorted + +# Fiz (where possible) and format cue files +format: + cue fix ./signed_docs/docs:signed_docs + cue fmt --files . + +# Check the signed document cue files are valid. +check: format + cue vet ./signed_docs/docs:signed_docs -c + +# Fix and Check Markdown files +regenerate: check + cue export -f -s ./signed_docs/docs:signed_docs --out json --outfile 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 + +# Pre Push Checks - intended to be run by a git pre-push hook. +pre-push: regenerate validate + \ No newline at end of file diff --git a/specs/cue.mod/module.cue b/specs/cue.mod/module.cue new file mode 100644 index 0000000000..aad96b47e7 --- /dev/null +++ b/specs/cue.mod/module.cue @@ -0,0 +1,4 @@ +module: "github.com/input-output-hk/catalyst-libs/specs" +language: { + version: "v0.11.2" +} diff --git a/specs/generic/optional.cue b/specs/generic/optional.cue new file mode 100644 index 0000000000..a6c84e4c89 --- /dev/null +++ b/specs/generic/optional.cue @@ -0,0 +1,7 @@ +package optional + +// Is a field Required, Optional or Excluded/Unused +#field: + "yes" | + "optional" | + *"excluded" diff --git a/specs/generic/uuid.cue b/specs/generic/uuid.cue new file mode 100644 index 0000000000..ac2bfa8a20 --- /dev/null +++ b/specs/generic/uuid.cue @@ -0,0 +1,8 @@ +// UUID Definitions +package uuid + +// A UUIDv4 formatted string regex +#v4: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" + +// A uuidv7 formatted string regex +#v7: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json b/specs/signed_doc.json similarity index 53% rename from docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json rename to specs/signed_doc.json index f35497d005..9c810fcb22 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/signed_doc.json +++ b/specs/signed_doc.json @@ -48,21 +48,133 @@ "type": "Proposal Template", "validation": "The document payload is not valid if it does not validate completely against the referenced template." }, + "collaborators": { + "required": "optional", + "format": "Collaborators Reference List", + "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 new version of the document.", + "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." + }, "category_id": { "required": "optional", "format": "Document Reference", + "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under." + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + } + }, + "payload": { + "description": "Proposal Document drafted for submission to a category of a campaign.\n\nMust be valid according to the schema of the referenced Template." + }, + "signers": { + "roles": { + "user": [ + "Proposer" + ] + }, + "update": { + "collaborators": true, + "author": true } } }, - "Proposal Meta Template": { + "Proposal Comment": { + "type": [ + "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ], + "description": "## Proposal Comment Document\n\nA Proposal Comment is a document which comments on a referenced Proposal document.\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.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "required": "optional", + "format": "COSE Algorithm" + }, + "content type": { + "coseLabel": 3, + "value": "application/json", + "description": "IANA Media Type/s allowed in the Payload", + "required": "yes", + "format": "IANA Media Type" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "value": [ + "br" + ], + "description": "Supported HTTP Encodings of the Payload", + "required": "optional", + "format": "HTTP Content Encoding" + } + }, + "metadata": { + "id": { + "required": "yes", + "format": "UUIDv7", + "description": "Document ID, created the first time the document is created." + }, + "ver": { + "required": "yes", + "format": "UUIDv7", + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "validation": "The document version must always be >= the document ID." + }, + "ref": { + "required": "yes", + "format": "Document Reference", + "type": "Proposal", + "description": "Reference to a Linked Document. \nThis is the primary hierarchial reference to a related document." + }, + "reply": { + "required": "optional", + "format": "Document Reference", + "description": "Reference to a Comment document type being referred to.", + "type": "Proposal Comment", + "validation": "The `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "section": { + "required": "optional", + "format": "Section Reference", + "description": "A Reference to the original document, or the comment being replied to.", + "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": { + "required": "yes", + "format": "Document Reference", + "description": "Reference to the template used to create and/or validate this document.", + "type": "Proposal Comment Template", + "validation": "The document payload is not valid if it does not validate completely against the referenced template." + }, + "category_id": { + "required": "optional", + "format": "Document Reference", + "description": "A reference to the Category Parameters Document this document lies under.", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + } + }, + "payload": { + "description": "JSON Document which must validate against the referenced template." + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] + }, + "update": { + "author": true + } + } + }, + "Proposal Comment Meta Template": { "type": [ "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "b679ded3-0e7c-41ba-89f8-da62a17898ea", "7808d2ba-d511-40af-84e8-c0d1625fdfdc" ], - "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 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.", "headers": { "alg": { "coseLabel": 1, @@ -102,17 +214,34 @@ "category_id": { "required": "optional", "format": "Document Reference", + "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under." + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + } + }, + "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." + }, + "signers": { + "roles": { + "user": [], + "admin": [ + "RootAdmin", + "BrandAdmin" + ] + }, + "update": { + "author": true } } }, - "Proposal Template": { + "Proposal Comment Template": { "type": [ "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "b679ded3-0e7c-41ba-89f8-da62a17898ea", "7808d2ba-d511-40af-84e8-c0d1625fdfdc" ], - "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.", + "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.", "headers": { "alg": { "coseLabel": 1, @@ -153,23 +282,40 @@ "required": "optional", "format": "Document Reference", "description": "Reference to the template used to create and/or validate this document.", - "type": "Proposal Meta Template", + "type": "Proposal Comment Meta Template", "validation": "The document payload is not valid if it does not validate completely against the referenced template." }, "category_id": { "required": "optional", "format": "Document Reference", + "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under." + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + } + }, + "payload": { + "description": "JSON Schema document which defines the content of the Proposal Comments." + }, + "signers": { + "roles": { + "user": [], + "admin": [ + "BrandAdmin", + "CampaignAdmin" + ] + }, + "update": { + "author": true } } }, - "Proposal Comment Template": { + "Proposal Meta Template": { "type": [ "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", "7808d2ba-d511-40af-84e8-c0d1625fdfdc" ], + "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.", "headers": { "alg": { "coseLabel": 1, @@ -178,8 +324,8 @@ "format": "COSE Algorithm" }, "content type": { + "value": "application/schema+json", "coseLabel": 3, - "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", "required": "yes", "format": "IANA Media Type" @@ -205,14 +351,38 @@ "format": "UUIDv7", "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." + }, + "category_id": { + "required": "optional", + "format": "Document Reference", + "description": "A reference to the Category Parameters Document this document lies under.", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + } + }, + "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." + }, + "signers": { + "roles": { + "user": [], + "admin": [ + "RootAdmin", + "BrandAdmin" + ] + }, + "update": { + "author": true } } }, - "Proposal Comment": { + "Proposal Submission Action": { "type": [ - "b679ded3-0e7c-41ba-89f8-da62a17898ea", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "78927329-cfd9-4ea1-9c71-0e019b126a65" ], + "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. Unless they all submit or withdraw the same version of the proposal\nthe proposal will not be seen as submitted or withdrawn.\n\nThe payload is a fixed format.", "headers": { "alg": { "coseLabel": 1, @@ -248,15 +418,78 @@ "format": "UUIDv7", "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." + }, + "collation": { + "required": "yes", + "format": "Document Collation Reference", + "description": "Array of Collated Document References\n\nThis is an Array of the format:\n `[[DocumentID, DocumentVer, DocumentHash],...]`\n\nIt is equivalent to `ref` plus `ref_hash` but allows multiple documents to be \nreferenced simultaneously. \nWhen a `collation` is used, Version and Hash are required.\n\nWhen `collation` and `ref` appear in the same document, \nthe first document in the collation list must be identical to the `ref` and `ref_hash` \nmust be present." + }, + "category_id": { + "required": "yes", + "format": "Document Reference", + "description": "A reference to the Category Parameters Document this document lies under.", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + } + }, + "payload": { + "description": "The kind of action is controlled by this payload.\nThe Payload is a JSON Document, and must conform to this schema.", + "schema": { + "$schema": "http://json-schema.org/draft-07/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", + "title": "Proposal Submission Action Payload Schema", + "description": "Structure of the payload of a Proposal Submission Action.", + "maintainers": [ + { + "name": "Catalyst Team", + "url": "https://projectcatalyst.io/" + } + ], + "x-changelog": { + "2025-03-01": [ + "First Version Created." + ] + }, + "additionalProperties": false, + "definitions": { + "action": { + "type": "string", + "description": "The action being performed on the Proposal.", + "enum": [ + "submission", + "retraction" + ] + } + }, + "properties": { + "action": { + "$ref": "#/definitions/action" + } + }, + "required": [ + "action" + ] + } + }, + "signers": { + "roles": { + "user": [ + "Proposer" + ] + }, + "referenced": true, + "update": { + "collaborators": true, + "author": true } } }, - "Proposal Submission Action": { + "Proposal Template": { "type": [ - "5e60e623-ad02-4a1b-a1ac-406db978ee48", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc", - "78927329-cfd9-4ea1-9c71-0e019b126a65" + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" ], + "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.", "headers": { "alg": { "coseLabel": 1, @@ -265,8 +498,8 @@ "format": "COSE Algorithm" }, "content type": { + "value": "application/schema+json", "coseLabel": 3, - "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", "required": "yes", "format": "IANA Media Type" @@ -292,6 +525,35 @@ "format": "UUIDv7", "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." + }, + "template": { + "required": "optional", + "format": "Document Reference", + "description": "Reference to the template used to create and/or validate this document.", + "type": "Proposal Meta Template", + "validation": "The document payload is not valid if it does not validate completely against the referenced template." + }, + "category_id": { + "required": "optional", + "format": "Document Reference", + "description": "A reference to the Category Parameters Document this document lies under.", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + } + }, + "payload": { + "description": "JSON Schema document which defines the valid contents of a proposal document." + }, + "signers": { + "roles": { + "user": [], + "admin": [ + "BrandAdmin", + "CampaignAdmin" + ] + }, + "update": { + "author": true } } }, @@ -337,6 +599,16 @@ "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." } + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] + }, + "update": { + "author": true + } } }, "Comment Action Document": { @@ -381,6 +653,16 @@ "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." } + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] + }, + "update": { + "author": true + } } }, "Category Parameters": { @@ -423,6 +705,16 @@ "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "validation": "The document version must always be >= the document ID." } + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] + }, + "update": { + "author": true + } } } } diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue b/specs/signed_docs/cose_headers.cue similarity index 93% rename from docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue rename to specs/signed_docs/cose_headers.cue index 925e1c7310..d51dfdc623 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/def_cose_headers.cue +++ b/specs/signed_docs/cose_headers.cue @@ -3,7 +3,11 @@ // COSE Headers and Constraints package signed_docs -import "list" +import ( + "list" + "github.com/input-output-hk/catalyst-libs/specs/generic:optional" + +) // Supported Content Types (list of values) #contentType: @@ -44,7 +48,7 @@ _allCoseHeaderNames: or([ #coseField: { coseLabel: int | string description: string - required: #optionalField | *"yes" + required: optional.#field | *"yes" format: #coseHeaderFormat if format == "IANA Media Type" { "value": #contentType diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue b/specs/signed_docs/docs/all.cue similarity index 74% rename from docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue rename to specs/signed_docs/docs/all.cue index ea993c08bf..4eef9c7e1b 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/doc_all.cue +++ b/specs/signed_docs/docs/all.cue @@ -1,8 +1,6 @@ // Master list of all document types. package signed_docs -import "list" - // Named Type UUIDs for easier definitions/references _allDocTypes: { "Template": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" @@ -14,13 +12,6 @@ _allDocTypes: { "Category": "818938c3-3139-4daa-afe6-974c78488e95" } -// Ensure that all Document Type IDs are Unique. -// See: all_docs.cue for a list of all known document types. -_allDocTypeIDs: list.UniqueItems -_allDocTypeIDs: [...#uuidv4] & [ - for _, v in _allDocTypes {v}, -] - // Source of truth for ALL Document Types and their matching UUID's. // Format is : : _allDocs: { @@ -36,6 +27,12 @@ _allDocs: { "Proposal": [ _allDocTypes["Proposal"], ] + "Proposal Comment Meta Template": [ + _allDocTypes["Template"], // Template + _allDocTypes["Template"], // For Templates + _allDocTypes["Comment"], // On Comment + _allDocTypes["Proposal"], // On Proposals + ] "Proposal Comment Template": [ _allDocTypes["Template"], // Template _allDocTypes["Comment"], // For Comments @@ -67,20 +64,3 @@ _allDocs: { ] } - -// Ensure that all Document IDs are Unique. -// See: all_docs.cue for a list of all known document types. -_allTypes: list.UniqueItems -_allTypes: [...#docType] & [ - for _, v in _allDocs {v}, -] - -_allDocNamesList: [...string] & [ - for k, _ in _allDocs {k}, -] - -// List of all the document names we have defined. -_allDocNames: or(_allDocNamesList) - -// Individual Valid Document Name constraint. -#DocumentName: _allDocNames diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json new file mode 100644 index 0000000000..c97bf97a4d --- /dev/null +++ b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-07/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", + "title": "Proposal Submission Action Payload Schema", + "description": "Structure of the payload of a Proposal Submission Action.", + "maintainers": [ + { + "name": "Catalyst Team", + "url": "https://projectcatalyst.io/" + } + ], + "x-changelog": { + "2025-03-01": [ + "First Version Created." + ] + }, + "additionalProperties": false, + "definitions": { + "action": { + "type": "string", + "description": "The action being performed on the Proposal.", + "enum": [ + "submission", + "retraction" + ] + } + }, + "properties": { + "action": { + "$ref": "#/definitions/action" + } + }, + "required": [ + "action" + ] +} \ No newline at end of file diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal.cue b/specs/signed_docs/docs/proposal.cue similarity index 70% rename from docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal.cue rename to specs/signed_docs/docs/proposal.cue index 4f254cce69..8ae320d3ae 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal.cue +++ b/specs/signed_docs/docs/proposal.cue @@ -25,10 +25,34 @@ docs: #DocumentDefinitions & { type: "Proposal Template" } + collaborators: { + required: "optional" + } + category_id: { required: "optional" type: "Category Parameters" } } + + payload: { + description: """ + Proposal Document drafted for submission to a category of a campaign. + + Must be valid according to the schema of the referenced Template. + """ + } + + signers: { + roles: { + user: [ + "Proposer", + ] + } + + update: { + "collaborators": true + } + } } } diff --git a/specs/signed_docs/docs/proposal_comment.cue b/specs/signed_docs/docs/proposal_comment.cue new file mode 100644 index 0000000000..7ab941fda7 --- /dev/null +++ b/specs/signed_docs/docs/proposal_comment.cue @@ -0,0 +1,51 @@ +package signed_docs + +// Proposal Document Definition + +docs: #DocumentDefinitions & { + "Proposal Comment": { + description: """ + ## Proposal Comment Document + + A Proposal Comment is a document which comments on a referenced Proposal document. + + 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. + """ + + metadata: { + ref: { + required: "yes" + type: "Proposal" + } + + reply: { + required: "optional" + type: "Proposal Comment" + } + + section: { + required: "optional" + } + + template: { + required: "yes" + type: "Proposal Comment Template" + } + + category_id: { + required: "optional" + type: "Category Parameters" + } + } + + payload: { + description: """ + JSON Document which must validate against the referenced template. + """ + } + + } +} diff --git a/specs/signed_docs/docs/proposal_comment_meta_template.cue b/specs/signed_docs/docs/proposal_comment_meta_template.cue new file mode 100644 index 0000000000..a04a591d62 --- /dev/null +++ b/specs/signed_docs/docs/proposal_comment_meta_template.cue @@ -0,0 +1,52 @@ +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: { + category_id: { + required: "optional" + type: "Category Parameters" + } + } + + 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. + """ + } + + "signers": { + roles: { + // No User Role may publish this document. + user: [] + + // Root Admin and brand Admin may publish this document. + admin: [ + "RootAdmin", + "BrandAdmin", + ] + } + } + } +} diff --git a/specs/signed_docs/docs/proposal_comment_template.cue b/specs/signed_docs/docs/proposal_comment_template.cue new file mode 100644 index 0000000000..6f3d15eaec --- /dev/null +++ b/specs/signed_docs/docs/proposal_comment_template.cue @@ -0,0 +1,56 @@ +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" + } + + category_id: { + required: "optional" + type: "Category Parameters" + } + } + + 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: [ + "BrandAdmin", + "CampaignAdmin", + ] + } + } + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_meta_template copy.cue b/specs/signed_docs/docs/proposal_meta_template.cue similarity index 50% rename from docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_meta_template copy.cue rename to specs/signed_docs/docs/proposal_meta_template.cue index f79be9df5b..615344f86a 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_meta_template copy.cue +++ b/specs/signed_docs/docs/proposal_meta_template.cue @@ -25,5 +25,29 @@ docs: #DocumentDefinitions & { type: "Category Parameters" } } + + 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. + """ + } + + "signers": { + roles: { + // No User Role may publish this document. + user: [] + + // Root Admin and brand Admin may publish this document. + admin: [ + "RootAdmin", + "BrandAdmin", + ] + } + } + } } diff --git a/specs/signed_docs/docs/proposal_submission_action.cue b/specs/signed_docs/docs/proposal_submission_action.cue new file mode 100644 index 0000000000..8a6b488eb9 --- /dev/null +++ b/specs/signed_docs/docs/proposal_submission_action.cue @@ -0,0 +1,61 @@ +@extern(embed) + +package signed_docs + +// Proposal Submission Action +docs: #DocumentDefinitions & { + "Proposal Submission Action": { + description: """ + ## 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. + + The last action on the document ts the action which takes effect at the deadline. + + For multiple collaborators, multiple submission actions can be posted independently, + but none of them will take effect until ALL collaborators have posted equivalent actions. + + For example, three collaborators Alice/Bob/Claire can each post one submission action + for the same document. Unless they all submit or withdraw the same version of the proposal + the proposal will not be seen as submitted or withdrawn. + + The payload is a fixed format. + """ + + metadata: { + collation: { + required: "yes" + } + + category_id: { + required: "yes" + type: "Category Parameters" + } + } + + payload: { + description: """ + The kind of action is controlled by this payload. + The Payload is a JSON Document, and must conform to this schema. + """ + schema: _ @embed(file="payload_schemas/proposal_submission_action.schema.json") + } + + "signers": { + roles: { + // Proposers may publish this document. + user: [ + "Proposer", + ] + } + + referenced: true + + update: { + collaborators: true + } + } + + } +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_template.cue b/specs/signed_docs/docs/proposal_template.cue similarity index 68% rename from docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_template.cue rename to specs/signed_docs/docs/proposal_template.cue index 92c77dad0f..5eeca8a0ce 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/doc_proposal_template.cue +++ b/specs/signed_docs/docs/proposal_template.cue @@ -33,5 +33,25 @@ docs: #DocumentDefinitions & { type: "Category Parameters" } } + + 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: [ + "BrandAdmin", + "CampaignAdmin", + ] + } + } + } } diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue b/specs/signed_docs/metadata.cue similarity index 62% rename from docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue rename to specs/signed_docs/metadata.cue index f588207ad9..956cea3f55 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/def_metadata.cue +++ b/specs/signed_docs/metadata.cue @@ -3,7 +3,11 @@ // Metadata Types and Constraints package signed_docs -import "list" +import ( + "list" + "github.com/input-output-hk/catalyst-libs/specs/generic:optional" + +) // Format of a Metadata Field #metadataFormat: @@ -11,7 +15,8 @@ import "list" "Document Reference" | "Document Hash" | "Section Reference" | - "Collaborators Reference List" + "Collaborators Reference List" | + "Document Collation Reference" // Canonical List of all valid metadata names _metadataNames: list.UniqueItems @@ -37,7 +42,7 @@ _allMetadataNames: or([ // Definition of a metadata field. #metadataField: { // Is the field required to be present. - required: #optionalField + required: optional.#field // Format of the field. format: #metadataFormat @@ -77,20 +82,46 @@ _metadata: #metadataStruct & { } ref?: #metadataField & { - format: "Document Reference" - description: "Reference to a Linked Document. This is the primary hierarchial reference to a related document." + format: "Document Reference" + description: """ + Reference to a Linked Document. + This is the primary hierarchial reference to a related document. + """ } // IF we have a ref, we can optionally have a `ref_hash` if ref != _|_ { ref_hash?: #metadataField & { format: "Document Hash" + description: """ + Hash of the referenced document. + This is the Blake2b-256 Hash over the entire referenced signed document. + It ensures that the intended referenced document is the one used. + + Prevents substitutions where a new document with the same Document ID and Ver might be + published over an existing one. + + This is only used when there could be security issues with substitutions of the referenced document. + """ } } collation?: #metadataField & { - format: "Document Collation Reference" - description: "Array of Collated Document References" + format: "Document Collation Reference" + description: """ + Array of Collated Document References + + This is an Array of the format: + `[[DocumentID, DocumentVer, DocumentHash],...]` + + It is equivalent to `ref` plus `ref_hash` but allows multiple documents to be + referenced simultaneously. + When a `collation` is used, Version and Hash are required. + + When `collation` and `ref` appear in the same document, + the first document in the collation list must be identical to the `ref` and `ref_hash` + must be present. + """ } template?: #metadataField & { @@ -144,26 +175,46 @@ _metadata: #metadataStruct & { brand_id?: #metadataField & { format: "Document Reference" - required: "optional" description: "A reference to the Brand Parameters Document this document lies under." + validation: """ + Any referenced document that includes a `brand_id` must match the `brand_id` + of the referencing document. + It is also valid for the referenced document to not include this field, if it is + optional for the referenced document. + """ } campaign_id?: #metadataField & { format: "Document Reference" - required: "optional" description: "A reference to the Campaign Parameters Document this document lies under." + validation: """ + Any referenced document that includes a `campaign_id` must match the `campaign_id` + of the referencing document. + It is also valid for the referenced document to not include this field, if it is + optional for the referenced document. + """ } election_id?: #metadataField & { format: "Document Reference" - required: "optional" description: "A reference to the Election Parameters Document this document lies under." + validation: """ + Any referenced document that includes a `election_id` must match the `election_id` + of the referencing document. + It is also valid for the referenced document to not include this field, if it is + optional for the referenced document. + """ } category_id?: #metadataField & { format: "Document Reference" - required: "optional" description: "A reference to the Category Parameters Document this document lies under." + validation: """ + Any referenced document that includes a `category_id` must match the `category_id` + of the referencing document. + It is also valid for the referenced document to not include this field, if it is + optional for the referenced document. + """ } } diff --git a/specs/signed_docs/payload.cue b/specs/signed_docs/payload.cue new file mode 100644 index 0000000000..e875f55304 --- /dev/null +++ b/specs/signed_docs/payload.cue @@ -0,0 +1,9 @@ +package signed_docs + +// Payload definition +_payload: { + // Description of the payload + description?: string + // Optional fixed schema for the payload. + schema?: _ +} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue b/specs/signed_docs/signed_doc.cue similarity index 50% rename from docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue rename to specs/signed_docs/signed_doc.cue index 94b2204287..774172db9f 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/def_signed_doc.cue +++ b/specs/signed_docs/signed_doc.cue @@ -3,22 +3,16 @@ // Base Types and Constraints package signed_docs -#optionalField: - "yes" | - "optional" | - *"excluded" - -// A UUIDv4 formatted string regex -#uuidv4: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" - -// A uuidv7 formatted string regex -#uuidv7: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" +import ( + "list" + "github.com/input-output-hk/catalyst-libs/specs/generic:uuid" +) // Document Type must be a valid UUIDv4 -#docType: [#uuidv4] | [#uuidv4, #uuidv4] | [#uuidv4, #uuidv4, #uuidv4] +#docType: [...uuid.#v4] // Document ID or Version must be a valid UUIDv7 -#docIdOrVer: #uuidv7 +#docIdOrVer: uuid.#v7 // Individual Signed Document Definition #signedDocument: { @@ -36,6 +30,12 @@ package signed_docs // The Metadata fields in this document (non cose standard) metadata: _metadata + + // Requirements for the document payload. + payload?: _payload + + // Required/Allowed Signers of a document + signers: _allowedSigners } // We can only define known documents in the document definitions object @@ -52,3 +52,27 @@ docs: #DocumentDefinitions & { } } } + +// Ensure that all Document Type IDs are Unique. +// See: all_docs.cue for a list of all known document types. +_allDocTypeIDs: list.UniqueItems +_allDocTypeIDs: [...uuid.#uuidv4] & [ + for _, v in _allDocTypes {v}, +] + +// Ensure that all Document IDs are Unique. +// See: all_docs.cue for a list of all known document types. +_allTypes: list.UniqueItems +_allTypes: [...#docType] & [ + for _, v in _allDocs {v}, +] + +_allDocNamesList: [...string] & [ + for k, _ in _allDocs {k}, +] + +// List of all the document names we have defined. +_allDocNames: or(_allDocNamesList) + +// Individual Valid Document Name constraint. +#DocumentName: _allDocNames diff --git a/specs/signed_docs/signers.cue b/specs/signed_docs/signers.cue new file mode 100644 index 0000000000..7f874ee682 --- /dev/null +++ b/specs/signed_docs/signers.cue @@ -0,0 +1,76 @@ +// Signed Document Definitions +// +// Metadata Types and Constraints +package signed_docs + +import "list" + +// TODO: Get Roles from RBAC definition configuration package instead. +// Named User Roles +_allUserRolesList: list.UniqueItems +_allUserRolesList: [ + "Registered", // Role 0 - A registered User / Voter - Base Role + "Proposer", // Registered for posting proposals + "Representative", // Registered as a rep for voting purposes. +] +_allUserRoles: or(_allUserRolesList) + +// Individual Valid User Role Constraint +#UserRoles: _allUserRoles +#allowedUserRoles: [...#UserRoles] + +// TODO: Get roles from RBAC definition configuration package instead +// Named Admin Roles +_allAdminRolesList: list.UniqueItems +_allAdminRolesList: [ + "RootCA", + "BrandCA", + "CampaignCA", + "CategoryCA", + "RootAdmin", + "BrandAdmin", + "CampaignAdmin", + "CategoryAdmin", + "Moderator", +] +_allAdminRoles: or(_allAdminRolesList) + +// Individual Valid Admin Role Constraint +#AdminRoles: _allAdminRoles +#allowedAdminRoles: [...#AdminRoles] + +// The roles which are allowed to publish this document +#allowedRoles: { + // User roles allowed to publish this document + user: #allowedUserRoles + + // Admin roles allowed to publish this document + admin?: #allowedAdminRoles +} + +#allowedUpdaters: { + collaborators?: bool | *false // Listed collaborators can post updated versions + author: bool | *true // The original author can post updated versions + any?: bool | *false // Anyone with the correct role can post updated versions +} + +#allowedSigners: { + // Who is allowed to sign a new document + // TODO: Import roles from a role definition configuration. + roles: #allowedRoles + + // Limited to the same signer as the document referenced + referenced?: bool | *false + + // Who is allowed to sign an update to an existing document. + update: #allowedUpdaters +} + +_allowedSigners: #allowedSigners & { + roles: #allowedRoles & { + user: #allowedUserRoles & _ | *[ + _allUserRolesList[0], + ] + } + update: #allowedUpdaters +} From 0b748b9591b9181e85c8c2e471aa684094230a6e Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sat, 1 Mar 2025 21:15:31 +0400 Subject: [PATCH 05/35] feat: Add draft7 jsonschema to meta templates schema definitions --- specs/signed_doc.json | 6 ++++-- specs/signed_docs/docs/proposal_comment_meta_template.cue | 2 ++ specs/signed_docs/docs/proposal_meta_template.cue | 2 ++ specs/signed_docs/payload.cue | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 9c810fcb22..9367836cc9 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -220,7 +220,8 @@ } }, "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." + "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" }, "signers": { "roles": { @@ -361,7 +362,8 @@ } }, "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." + "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" }, "signers": { "roles": { diff --git a/specs/signed_docs/docs/proposal_comment_meta_template.cue b/specs/signed_docs/docs/proposal_comment_meta_template.cue index a04a591d62..de81659af2 100644 --- a/specs/signed_docs/docs/proposal_comment_meta_template.cue +++ b/specs/signed_docs/docs/proposal_comment_meta_template.cue @@ -34,6 +34,8 @@ docs: #DocumentDefinitions & { 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": { diff --git a/specs/signed_docs/docs/proposal_meta_template.cue b/specs/signed_docs/docs/proposal_meta_template.cue index 615344f86a..bb6603b84a 100644 --- a/specs/signed_docs/docs/proposal_meta_template.cue +++ b/specs/signed_docs/docs/proposal_meta_template.cue @@ -34,6 +34,8 @@ docs: #DocumentDefinitions & { 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": { diff --git a/specs/signed_docs/payload.cue b/specs/signed_docs/payload.cue index e875f55304..971a538a08 100644 --- a/specs/signed_docs/payload.cue +++ b/specs/signed_docs/payload.cue @@ -5,5 +5,6 @@ _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?: _ } From d3128304ca0392b8d54c6b70eab549fff1f6156e Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 11:39:21 +0400 Subject: [PATCH 06/35] feat: Add CI actions to check generated data matches schema --- .../signed_doc/spec/obsolete/blueprint.cue | 2 - .../spec/obsolete => specs}/Earthfile | 17 +- specs/blueprint.cue | 2 + specs/signed_doc.json | 150 +++++++++--------- 4 files changed, 86 insertions(+), 85 deletions(-) delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/obsolete/blueprint.cue rename {docs/src/architecture/08_concepts/signed_doc/spec/obsolete => specs}/Earthfile (50%) create mode 100644 specs/blueprint.cue diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/blueprint.cue b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/blueprint.cue deleted file mode 100644 index e9144a9d01..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/blueprint.cue +++ /dev/null @@ -1,2 +0,0 @@ -version: "1.0.0" -project: name: "Signed-Docs-Specs" diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/Earthfile b/specs/Earthfile similarity index 50% rename from docs/src/architecture/08_concepts/signed_doc/spec/obsolete/Earthfile rename to specs/Earthfile index ca31162f8c..b028b22ddd 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/Earthfile +++ b/specs/Earthfile @@ -18,17 +18,18 @@ src: FROM +builder WORKDIR /src + COPY . . + ENV CUE_EXPERIMENT="embed" - COPY signed_doc_defs.* . check: FROM +src - RUN cue --help - RUN ls -al - RUN cue vet signed_doc_defs.schema.cue -d '#SignedDoc' signed_doc_defs.yml + RUN cue fmt --check --files . + RUN cue vet ./signed_docs/docs:signed_docs signed_doc.json -# Regenerate -regen: - FROM src +# Regenerate - using the builder +regenerate: + FROM +src - RUN ls -al \ No newline at end of file + RUN cue export -f -s ./signed_docs/docs:signed_docs --out json --outfile signed_doc.json + SAVE ARTIFACT --keep-ts signed_doc.json AS LOCAL . \ No newline at end of file diff --git a/specs/blueprint.cue b/specs/blueprint.cue new file mode 100644 index 0000000000..9723f22918 --- /dev/null +++ b/specs/blueprint.cue @@ -0,0 +1,2 @@ +version: "1.0.0" +project: name: "Catalyst Data Specifications" diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 9367836cc9..6ccb604ddf 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -14,19 +14,19 @@ }, "content type": { "coseLabel": 3, - "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { @@ -44,21 +44,21 @@ "template": { "required": "yes", "format": "Document Reference", - "description": "Reference to the template used to create and/or validate this document.", "type": "Proposal Template", + "description": "Reference to the template used to create and/or validate this document.", "validation": "The document payload is not valid if it does not validate completely against the referenced template." }, "collaborators": { - "required": "optional", "format": "Collaborators Reference List", + "required": "optional", "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 new version of the document.", "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." }, "category_id": { "required": "optional", "format": "Document Reference", - "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under.", "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." } }, @@ -92,19 +92,19 @@ }, "content type": { "coseLabel": 3, - "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { @@ -126,30 +126,30 @@ "description": "Reference to a Linked Document. \nThis is the primary hierarchial reference to a related document." }, "reply": { - "required": "optional", "format": "Document Reference", - "description": "Reference to a Comment document type being referred to.", + "required": "optional", "type": "Proposal Comment", + "description": "Reference to a Comment document type being referred to.", "validation": "The `ref` of the `reply` document must be the same as\nthe original comment document." }, "section": { - "required": "optional", "format": "Section Reference", + "required": "optional", "description": "A Reference to the original document, or the comment being replied to.", "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": { "required": "yes", "format": "Document Reference", - "description": "Reference to the template used to create and/or validate this document.", "type": "Proposal Comment Template", + "description": "Reference to the template used to create and/or validate this document.", "validation": "The document payload is not valid if it does not validate completely against the referenced template." }, "category_id": { "required": "optional", "format": "Document Reference", - "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under.", "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." } }, @@ -183,20 +183,20 @@ "format": "COSE Algorithm" }, "content type": { - "value": "application/schema+json", "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/schema+json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { @@ -214,8 +214,8 @@ "category_id": { "required": "optional", "format": "Document Reference", - "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under.", "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." } }, @@ -251,20 +251,20 @@ "format": "COSE Algorithm" }, "content type": { - "value": "application/schema+json", "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/schema+json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { @@ -282,15 +282,15 @@ "template": { "required": "optional", "format": "Document Reference", - "description": "Reference to the template used to create and/or validate this document.", "type": "Proposal Comment Meta Template", + "description": "Reference to the template used to create and/or validate this document.", "validation": "The document payload is not valid if it does not validate completely against the referenced template." }, "category_id": { "required": "optional", "format": "Document Reference", - "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under.", "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." } }, @@ -325,20 +325,20 @@ "format": "COSE Algorithm" }, "content type": { - "value": "application/schema+json", "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/schema+json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { @@ -356,8 +356,8 @@ "category_id": { "required": "optional", "format": "Document Reference", - "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under.", "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." } }, @@ -394,19 +394,19 @@ }, "content type": { "coseLabel": 3, - "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { @@ -429,8 +429,8 @@ "category_id": { "required": "yes", "format": "Document Reference", - "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under.", "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." } }, @@ -500,20 +500,20 @@ "format": "COSE Algorithm" }, "content type": { - "value": "application/schema+json", "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/schema+json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { @@ -531,15 +531,15 @@ "template": { "required": "optional", "format": "Document Reference", - "description": "Reference to the template used to create and/or validate this document.", "type": "Proposal Meta Template", + "description": "Reference to the template used to create and/or validate this document.", "validation": "The document payload is not valid if it does not validate completely against the referenced template." }, "category_id": { "required": "optional", "format": "Document Reference", - "description": "A reference to the Category Parameters Document this document lies under.", "type": "Category Parameters", + "description": "A reference to the Category Parameters Document this document lies under.", "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." } }, @@ -574,19 +574,19 @@ }, "content type": { "coseLabel": 3, - "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { @@ -628,19 +628,19 @@ }, "content type": { "coseLabel": 3, - "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { @@ -680,19 +680,19 @@ }, "content type": { "coseLabel": 3, - "value": "application/json", "description": "IANA Media Type/s allowed in the Payload", "required": "yes", - "format": "IANA Media Type" + "format": "IANA Media Type", + "value": "application/json" }, "content-encoding": { "coseLabel": "content-encoding", - "value": [ - "br" - ], "description": "Supported HTTP Encodings of the Payload", "required": "optional", - "format": "HTTP Content Encoding" + "format": "HTTP Content Encoding", + "value": [ + "br" + ] } }, "metadata": { From 532cc92f482083220aa7b29b487eac274608afd6 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 12:53:48 +0400 Subject: [PATCH 07/35] fix: try and fix project name for CI --- specs/blueprint.cue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/blueprint.cue b/specs/blueprint.cue index 9723f22918..2d96c1be9e 100644 --- a/specs/blueprint.cue +++ b/specs/blueprint.cue @@ -1,2 +1,2 @@ version: "1.0.0" -project: name: "Catalyst Data Specifications" +project: name: "catalyst-data-specifications" From f38eca8ee2695894ba8846704670cb43458e42de Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 13:11:51 +0400 Subject: [PATCH 08/35] fix: remove obsolete files --- .../spec/obsolete/signed_doc_defs.schema.cue | 75 -------- .../spec/obsolete/signed_doc_defs.schema.json | 177 ------------------ .../spec/obsolete/signed_doc_defs.yml | 115 ------------ 3 files changed, 367 deletions(-) delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.cue delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.json delete mode 100644 docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.yml diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.cue b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.cue deleted file mode 100644 index a9a4375711..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.cue +++ /dev/null @@ -1,75 +0,0 @@ -package signed_docs - -#SignedDoc: { - // Signed Document Definitions Database - // - // Source of truth for definitions of all catalyst signed - // documents. - @jsonschema(schema="http://json-schema.org/draft-07/schema#") - null | bool | number | string | [...] | close({ - @jsonschema(id="https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/docs/src/architecture/08_concepts/signed_doc/signed_doc_defs.schema.json") - default?: #docDefinitionFields - - // Document Definition - docs?: { - {[=~".*"]: #docDefinition} - "Proposal Template"!: _ - Proposal!: _ - "Proposal Action"!: _ - "Proposal Comment Template"!: _ - "Proposal Comment"!: _ - "Category Parameters"!: _ - "Campaign Parameters"!: _ - "Brand Parameters"!: _ - "Public Vote Tx V2"!: _ - "Private Vote Tx V2"!: _ - "Immutable Ledger Block"!: _ - ... - } - }) - - #contentType: "application/json" | "application/cbor" - - #contentEncoding: "br" - - #contentEncodings: [...#contentEncoding] - - #docType: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" - - #docIdOrVer: =~"^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" - - #metadataFormat: "UUIDv7" | "COSE Algorithm" | "HTTP Content Type" | "HTTP Content Encoding" | "Document Reference" | "Document Hash" - - #requiredOrOptional: "yes" | "optional" | "no" - - #metadataFieldDescription: string - - #metadataFieldSpec: close({ - format?: #metadataFormat - required?: #requiredOrOptional - "ref type"?: string - description?: #metadataFieldDescription - validation?: #metadataFieldDescription - }) - - #docDefinitionFields: null | bool | number | string | [...] | { - contentType?: #contentType - contentEncodings?: #contentEncodings - metadata?: close({ - id?: #metadataFieldSpec - ver?: #metadataFieldSpec - alg?: #metadataFieldSpec - "content type"?: #metadataFieldSpec - "content encoding"?: #metadataFieldSpec - ref?: #metadataFieldSpec - "ref hash"?: #metadataFieldSpec - template?: #metadataFieldSpec - }) - ... - } - - #docDefinition: { - @jsonschema(id="https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/docs/src/architecture/08_concepts/signed_doc/docDefinition") - ... - } -} diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.json b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.json deleted file mode 100644 index 8c42d457fb..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.schema.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://raw.githubusercontent.com/input-output-hk/catalyst-libs/refs/heads/main/docs/src/architecture/08_concepts/signed_doc/signed_doc_defs.schema.json", - "title": "Signed Document Definitions Database", - "description": "Source of truth for definitions of all catalyst signed documents.", - "maintainers": [ - { - "name": "Catalyst Team", - "url": "https://projectcatalyst.io/" - } - ], - "x-changelog": { - "2025-02-10": [ - "First Version Created." - ] - }, - "additionalProperties": false, - "definitions": { - "contentType": { - "type": "string", - "description": "The content type used for this document payload.", - "enum": [ - "application/json", - "application/cbor" - ] - }, - "contentEncoding": { - "type": "string", - "description": "The ways this content can be encoded. By default all content allows for no encoding.", - "enum": [ - "br" - ] - }, - "contentEncodings": { - "type": "array", - "description": "All content encodings allowed for this document payload.", - "items": { - "$ref": "#/definitions/contentEncoding" - } - }, - "docType": { - "type": "string", - "format": "uuid", - "pattern": "^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" - }, - "docIdOrVer": { - "description": "The ID or version of the document", - "type": "string", - "format": "uuid", - "pattern": "^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{7}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$" - }, - "metadataFormat": { - "type": "string", - "enum": [ - "UUIDv7", - "COSE Algorithm", - "HTTP Content Type", - "HTTP Content Encoding", - "Document Reference", - "Document Hash" - ] - }, - "requiredOrOptional": { - "type": "string", - "enum": [ - "yes", - "optional", - "no" - ] - }, - "metadataFieldDescription": { - "type": "string", - "format": "markdown" - }, - "metadataFieldSpec": { - "type": "object", - "additionalProperties": false, - "properties": { - "format": { - "$ref": "#/definitions/metadataFormat" - }, - "required": { - "$ref": "#/definitions/requiredOrOptional" - }, - "ref type": { - "type": "string" - }, - "description": { - "$ref": "#/definitions/metadataFieldDescription" - }, - "validation": { - "$ref": "#/definitions/metadataFieldDescription" - } - } - }, - "docDefinitionFields": { - "properties": { - "contentType": { - "$ref": "#/definitions/contentType" - }, - "contentEncodings": { - "$ref": "#/definitions/contentEncodings" - }, - "metadata": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "$ref": "#/definitions/metadataFieldSpec" - }, - "ver": { - "$ref": "#/definitions/metadataFieldSpec" - }, - "alg": { - "$ref": "#/definitions/metadataFieldSpec" - }, - "content type": { - "$ref": "#/definitions/metadataFieldSpec" - }, - "content encoding": { - "$ref": "#/definitions/metadataFieldSpec" - }, - "ref": { - "$ref": "#/definitions/metadataFieldSpec" - }, - "ref hash": { - "$ref": "#/definitions/metadataFieldSpec" - }, - "template": { - "$ref": "#/definitions/metadataFieldSpec" - } - } - } - } - }, - "docDefinition": { - "$id": "docDefinition", - "title": "Individual Document Definition", - "description": "A single document definition", - "type": "object" - } - }, - "properties": { - "default": { - "type": "object", - "title": "Default Document Definition", - "$ref": "#/definitions/docDefinitionFields", - "required": [ - "contentType", - "contentEncodings", - "metadata" - ] - }, - "docs": { - "type": "object", - "title": "Document Definition", - "patternProperties": { - ".*": { - "$ref": "#/definitions/docDefinition" - } - }, - "required": [ - "Proposal Template", - "Proposal", - "Proposal Action", - "Proposal Comment Template", - "Proposal Comment", - "Category Parameters", - "Campaign Parameters", - "Brand Parameters", - "Public Vote Tx V2", - "Private Vote Tx V2", - "Immutable Ledger Block" - ] - } - } -} \ No newline at end of file diff --git a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.yml b/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.yml deleted file mode 100644 index c4e05524bf..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/spec/obsolete/signed_doc_defs.yml +++ /dev/null @@ -1,115 +0,0 @@ -# yaml-language-server: $schema=./signed_doc_defs.schema.json - -# Default values applied to all documents unless otherwise re-defined. -default: - contentType: application/json - contentEncodings: - - br - metadata: - id: - format: UUIDv7 - required: yes - description: | - [Document ID]. - ver: - format: UUIDv7 - required: yes - description: | - [Document Version]. - alg: - format: COSE Algorithm - required: yes - description: | - [COSE Algorithm]. - content type: - format: HTTP Content Type - required: yes - description: | - [HTTP Content Type]. - content encoding: - format: HTTP Content Encoding - required: optional - description: | - [HTTP Content Encoding]. - ref: - format: Document Reference - description: | - This is a reference to another document. - The purpose of the `ref` will vary depending on the [Document Type]. - - The `ref` can be either a single [UUIDv7] or a [CBOR] Array of Two [UUIDv7]. - - If the `ref` is a single [UUID] v7, it is a reference to the document of that [Document Id]. - If the `ref` is a [CBOR] array, it has the form `[,]` where: - - * `` - the [UUIDv7] of the referenced documents [Document Id]. - * `` - the [UUIDv7] of the referenced documents [Document Ver]. - validation: | - For any document type, `ref` can refer to only 1 other document type. - The referenced document type *MUST* be different than the type of document `ref` appears in. - For example `ref` for a Proposal Comment Document, is always a Proposal type document. - - ref hash: - format: Document Hash - description: | - This is a cryptographically secured reference to another document. - - It consists of a single field: - - * `hash` - the [CBOR] tagged hash of the signed document. - All data within the signed document is hashed, excluding the signatures. - - This field is not used every time a [Document Reference] is used, - however if it is defined to be used then the [Document Reference] *MUST* also be used. - validation: | - The hash must match the hash of th document referenced by the [Document Reference]. - template: - format: Document Reference - description: | - This is a reference to another documen - validation: | - The referenced document must be a [Template Document]. - -docs: - Proposal Template: - type: 7808d2ba-d511-40af-84e8-c0d1625fdfdc - metadata: - ref: - required: no - ref hash: - required: no - template: - required: no - ref type: Proposal Template Template - - Proposal: - type: 0ce8ab38-9258-4fbc-a62e-7faa6e58318f - metadata: - template: - - template type: json schema - required: yes - ref type: Proposal Template - category: required - - Proposal Action: - type: 5e60e623-ad02-4a1b-a1ac-406db978ee48 - Proposal Comment Template: - type: 0b8424d4-ebfd-46e3-9577-1775a69d290c - Proposal Comment: - type: b679ded3-0e7c-41ba-89f8-da62a17898ea - Category Parameters: - type: 48c20109-362a-4d32-9bba-e0a9cf8b45be - Campaign Parameters: - type: 0110ea96-a555-47ce-8408-36efe6ed6f7c - Brand Parameters: - type: 3e4808cc-c86e-467b-9702-d60baa9d1fca - Public Vote Tx V2: - type: 8de5586c-e998-4b95-8742-7be3c8592803 - contentType: application/cbor - Private Vote Tx V2: - type: e78ee18d-f380-44c1-a852-80aa6ecb07fe - contentType: application/cbor - Immutable Ledger Block: - type: d9e7e6ce-2401-4d7d-9492-f4f7c64241c3 - contentType: application/cbor From 79ca3e00bba46daaceb9afa55092b4e9e774be88 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 13:12:04 +0400 Subject: [PATCH 09/35] fix: fix markdown --- .../src/architecture/08_concepts/signed_doc/validation.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/src/architecture/08_concepts/signed_doc/validation.md b/docs/src/architecture/08_concepts/signed_doc/validation.md index ee85160032..80d530965e 100644 --- a/docs/src/architecture/08_concepts/signed_doc/validation.md +++ b/docs/src/architecture/08_concepts/signed_doc/validation.md @@ -11,13 +11,11 @@ Created: 2024-12-29 License: CC-BY-4.0 --- +## Validation + This is a list of Metadata fields that apply to each document type, and how they are to be validated. | Document Type |`ref` | `ref_hash` | `template` | `reply` | `section` | `brand_id` | `campaign_id` | `category_id` | | ------------- | ----- | ---------- | --------- | ------- | --------- | ---------- | ------------ | ----------------- | | Proposal | None | `p` | `p` | `p` | `p` | `p` | `p` | `p` | -| Proposal Template | -| Comment | `c` | `p` | `p` | `p` | `p` | `p` | `p` | `p` | `p` | - - -[Proposal]: \ No newline at end of file +| Comment | `c` | `p` | `p` | `p` | `p` | `p` | `p` | `p` | From 577417ef0e29a6af1f8697daf4e898a6dad2fcfb Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 13:13:34 +0400 Subject: [PATCH 10/35] fix: spelling --- .config/dictionaries/project.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index 9bcf2c5498..4aeb2f3e10 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -51,6 +51,7 @@ crontabs crontagged csprng cstring +cuelang dalek dashmap Datelike From 018cb4e994622e8e9e4e76f34d8792c2ce65b9aa Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 13:42:08 +0400 Subject: [PATCH 11/35] fix: Make sure json version of document specifications is sorted to make change tracking easier. --- specs/Justfile | 3 +- specs/signed_doc.json | 1418 ++++++++++++++++++++--------------------- 2 files changed, 711 insertions(+), 710 deletions(-) diff --git a/specs/Justfile b/specs/Justfile index 78f7b3f27c..de3ef0c858 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -18,7 +18,8 @@ check: format # Fix and Check Markdown files regenerate: check - cue export -f -s ./signed_docs/docs:signed_docs --out json --outfile 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 # Validate the generated signed_docs.json is correct against the cue schema. validate: diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 6ccb604ddf..e2dd4deaba 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -1,723 +1,723 @@ { - "docs": { - "Proposal": { - "type": [ - "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - ], - "description": "## Proposal Document\n\nA Proposal is a document which describes a proposed solution or project to\naddress the criteria of a category within a campaign.\n\nThe proposal itself is a draft document, it is not submitted for consideration\nunless a `Proposal Submission Action` is submitted which references it.\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.", - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - }, - "template": { - "required": "yes", - "format": "Document Reference", - "type": "Proposal Template", - "description": "Reference to the template used to create and/or validate this document.", - "validation": "The document payload is not valid if it does not validate completely against the referenced template." - }, - "collaborators": { - "format": "Collaborators Reference List", - "required": "optional", - "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 new version of the document.", - "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." - }, - "category_id": { - "required": "optional", - "format": "Document Reference", - "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under.", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." - } - }, - "payload": { - "description": "Proposal Document drafted for submission to a category of a campaign.\n\nMust be valid according to the schema of the referenced Template." - }, - "signers": { - "roles": { - "user": [ - "Proposer" - ] - }, - "update": { - "collaborators": true, - "author": true - } - } + "docs": { + "Category Parameters": { + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" }, - "Proposal Comment": { - "type": [ - "b679ded3-0e7c-41ba-89f8-da62a17898ea", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - ], - "description": "## Proposal Comment Document\n\nA Proposal Comment is a document which comments on a referenced Proposal document.\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.", - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - }, - "ref": { - "required": "yes", - "format": "Document Reference", - "type": "Proposal", - "description": "Reference to a Linked Document. \nThis is the primary hierarchial reference to a related document." - }, - "reply": { - "format": "Document Reference", - "required": "optional", - "type": "Proposal Comment", - "description": "Reference to a Comment document type being referred to.", - "validation": "The `ref` of the `reply` document must be the same as\nthe original comment document." - }, - "section": { - "format": "Section Reference", - "required": "optional", - "description": "A Reference to the original document, or the comment being replied to.", - "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": { - "required": "yes", - "format": "Document Reference", - "type": "Proposal Comment Template", - "description": "Reference to the template used to create and/or validate this document.", - "validation": "The document payload is not valid if it does not validate completely against the referenced template." - }, - "category_id": { - "required": "optional", - "format": "Document Reference", - "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under.", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." - } - }, - "payload": { - "description": "JSON Document which must validate against the referenced template." - }, - "signers": { - "roles": { - "user": [ - "Registered" - ] - }, - "update": { - "author": true - } - } + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/json" }, - "Proposal Comment Meta Template": { - "type": [ - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "b679ded3-0e7c-41ba-89f8-da62a17898ea", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - ], - "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.", - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/schema+json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - }, - "category_id": { - "required": "optional", - "format": "Document Reference", - "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under.", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." - } - }, - "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" - }, - "signers": { - "roles": { - "user": [], - "admin": [ - "RootAdmin", - "BrandAdmin" - ] - }, - "update": { - "author": true - } - } + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes" }, - "Proposal Comment Template": { - "type": [ - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "b679ded3-0e7c-41ba-89f8-da62a17898ea", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - ], - "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.", - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/schema+json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - }, - "template": { - "required": "optional", - "format": "Document Reference", - "type": "Proposal Comment Meta Template", - "description": "Reference to the template used to create and/or validate this document.", - "validation": "The document payload is not valid if it does not validate completely against the referenced template." - }, - "category_id": { - "required": "optional", - "format": "Document Reference", - "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under.", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." - } - }, - "payload": { - "description": "JSON Schema document which defines the content of the Proposal Comments." - }, - "signers": { - "roles": { - "user": [], - "admin": [ - "BrandAdmin", - "CampaignAdmin" - ] - }, - "update": { - "author": true - } - } + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] }, - "Proposal Meta Template": { - "type": [ - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - ], - "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.", - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/schema+json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - }, - "category_id": { - "required": "optional", - "format": "Document Reference", - "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under.", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." - } - }, - "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" - }, - "signers": { - "roles": { - "user": [], - "admin": [ - "RootAdmin", - "BrandAdmin" - ] - }, - "update": { - "author": true - } - } + "update": { + "author": true + } + }, + "type": [ + "818938c3-3139-4daa-afe6-974c78488e95" + ] + }, + "Comment Action Document": { + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" }, - "Proposal Submission Action": { - "type": [ - "5e60e623-ad02-4a1b-a1ac-406db978ee48", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc", - "78927329-cfd9-4ea1-9c71-0e019b126a65" - ], - "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. Unless they all submit or withdraw the same version of the proposal\nthe proposal will not be seen as submitted or withdrawn.\n\nThe payload is a fixed format.", - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - }, - "collation": { - "required": "yes", - "format": "Document Collation Reference", - "description": "Array of Collated Document References\n\nThis is an Array of the format:\n `[[DocumentID, DocumentVer, DocumentHash],...]`\n\nIt is equivalent to `ref` plus `ref_hash` but allows multiple documents to be \nreferenced simultaneously. \nWhen a `collation` is used, Version and Hash are required.\n\nWhen `collation` and `ref` appear in the same document, \nthe first document in the collation list must be identical to the `ref` and `ref_hash` \nmust be present." - }, - "category_id": { - "required": "yes", - "format": "Document Reference", - "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under.", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." - } - }, - "payload": { - "description": "The kind of action is controlled by this payload.\nThe Payload is a JSON Document, and must conform to this schema.", - "schema": { - "$schema": "http://json-schema.org/draft-07/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", - "title": "Proposal Submission Action Payload Schema", - "description": "Structure of the payload of a Proposal Submission Action.", - "maintainers": [ - { - "name": "Catalyst Team", - "url": "https://projectcatalyst.io/" - } - ], - "x-changelog": { - "2025-03-01": [ - "First Version Created." - ] - }, - "additionalProperties": false, - "definitions": { - "action": { - "type": "string", - "description": "The action being performed on the Proposal.", - "enum": [ - "submission", - "retraction" - ] - } - }, - "properties": { - "action": { - "$ref": "#/definitions/action" - } - }, - "required": [ - "action" - ] - } - }, - "signers": { - "roles": { - "user": [ - "Proposer" - ] - }, - "referenced": true, - "update": { - "collaborators": true, - "author": true - } - } + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/json" }, - "Proposal Template": { - "type": [ - "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc" - ], - "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.", - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/schema+json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - }, - "template": { - "required": "optional", - "format": "Document Reference", - "type": "Proposal Meta Template", - "description": "Reference to the template used to create and/or validate this document.", - "validation": "The document payload is not valid if it does not validate completely against the referenced template." - }, - "category_id": { - "required": "optional", - "format": "Document Reference", - "type": "Category Parameters", - "description": "A reference to the Category Parameters Document this document lies under.", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." - } - }, - "payload": { - "description": "JSON Schema document which defines the valid contents of a proposal document." - }, - "signers": { - "roles": { - "user": [], - "admin": [ - "BrandAdmin", - "CampaignAdmin" - ] - }, - "update": { - "author": true - } - } + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes" }, - "Proposal Moderation Action": { - "type": [ - "5e60e623-ad02-4a1b-a1ac-406db978ee48", - "7808d2ba-d511-40af-84e8-c0d1625fdfdc", - "a5d232b8-5e03-4117-9afd-be32b878fcdd" - ], - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - } - }, - "signers": { - "roles": { - "user": [ - "Registered" - ] - }, - "update": { - "author": true - } - } + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] }, - "Comment Action Document": { - "type": [ - "5e60e623-ad02-4a1b-a1ac-406db978ee48", - "b679ded3-0e7c-41ba-89f8-da62a17898ea", - "a5d232b8-5e03-4117-9afd-be32b878fcdd" - ], - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - } - }, - "signers": { - "roles": { - "user": [ - "Registered" - ] - }, - "update": { - "author": true - } - } + "update": { + "author": true + } + }, + "type": [ + "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "a5d232b8-5e03-4117-9afd-be32b878fcdd" + ] + }, + "Proposal": { + "description": "## Proposal Document\n\nA Proposal is a document which describes a proposed solution or project to\naddress the criteria of a category within a campaign.\n\nThe proposal itself is a draft document, it is not submitted for consideration\nunless a `Proposal Submission Action` is submitted which references it.\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.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "optional", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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.", + "format": "UUIDv7", + "required": "yes" + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "required": "yes", + "type": "Proposal Template", + "validation": "The document payload is not valid if it does not validate completely against the referenced template." + }, + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "payload": { + "description": "Proposal Document drafted for submission to a category of a campaign.\n\nMust be valid according to the schema of the referenced Template." + }, + "signers": { + "roles": { + "user": [ + "Proposer" + ] + }, + "update": { + "author": true, + "collaborators": true + } + }, + "type": [ + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ] + }, + "Proposal Comment": { + "description": "## Proposal Comment Document\n\nA Proposal Comment is a document which comments on a referenced Proposal document.\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.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "optional", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes" + }, + "ref": { + "description": "Reference to a Linked Document. \nThis is the primary hierarchial reference to a related document.", + "format": "Document Reference", + "required": "yes", + "type": "Proposal" + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "optional", + "type": "Proposal Comment", + "validation": "The `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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", + "required": "yes", + "type": "Proposal Comment Template", + "validation": "The document payload is not valid if it does not validate completely against the referenced template." + }, + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "payload": { + "description": "JSON Document which must validate against the referenced template." + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] + }, + "update": { + "author": true + } + }, + "type": [ + "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ] + }, + "Proposal Comment Meta Template": { + "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.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/schema+json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "optional", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes" + }, + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "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" + }, + "signers": { + "roles": { + "admin": [ + "RootAdmin", + "BrandAdmin" + ], + "user": [] + }, + "update": { + "author": true + } + }, + "type": [ + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ] + }, + "Proposal Comment Template": { + "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.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/schema+json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "optional", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes" + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "required": "optional", + "type": "Proposal Comment Meta Template", + "validation": "The document payload is not valid if it does not validate completely against the referenced template." + }, + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "payload": { + "description": "JSON Schema document which defines the content of the Proposal Comments." + }, + "signers": { + "roles": { + "admin": [ + "BrandAdmin", + "CampaignAdmin" + ], + "user": [] + }, + "update": { + "author": true + } + }, + "type": [ + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ] + }, + "Proposal Meta Template": { + "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.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/schema+json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "optional", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes" + }, + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "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" + }, + "signers": { + "roles": { + "admin": [ + "RootAdmin", + "BrandAdmin" + ], + "user": [] + }, + "update": { + "author": true + } + }, + "type": [ + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ] + }, + "Proposal Moderation Action": { + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes" + }, + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] + }, + "update": { + "author": true + } + }, + "type": [ + "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "a5d232b8-5e03-4117-9afd-be32b878fcdd" + ] + }, + "Proposal Submission Action": { + "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. Unless they all submit or withdraw the same version of the proposal\nthe proposal will not be seen as submitted or withdrawn.\n\nThe payload is a fixed format.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "yes", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, - "Category Parameters": { - "type": [ - "818938c3-3139-4daa-afe6-974c78488e95" - ], - "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "required": "optional", - "format": "COSE Algorithm" - }, - "content type": { - "coseLabel": 3, - "description": "IANA Media Type/s allowed in the Payload", - "required": "yes", - "format": "IANA Media Type", - "value": "application/json" - }, - "content-encoding": { - "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", - "required": "optional", - "format": "HTTP Content Encoding", - "value": [ - "br" - ] - } - }, - "metadata": { - "id": { - "required": "yes", - "format": "UUIDv7", - "description": "Document ID, created the first time the document is created." - }, - "ver": { - "required": "yes", - "format": "UUIDv7", - "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", - "validation": "The document version must always be >= the document ID." - } - }, - "signers": { - "roles": { - "user": [ - "Registered" - ] - }, - "update": { - "author": true - } + "collation": { + "description": "Array of Collated Document References\n\nThis is an Array of the format:\n `[[DocumentID, DocumentVer, DocumentHash],...]`\n\nIt is equivalent to `ref` plus `ref_hash` but allows multiple documents to be \nreferenced simultaneously. \nWhen a `collation` is used, Version and Hash are required.\n\nWhen `collation` and `ref` appear in the same document, \nthe first document in the collation list must be identical to the `ref` and `ref_hash` \nmust be present.", + "format": "Document Collation Reference", + "required": "yes" + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes" + }, + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "payload": { + "description": "The kind of action is controlled by this payload.\nThe Payload is a JSON Document, and must conform to this schema.", + "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": [ + "submission", + "retraction" + ], + "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", + "x-changelog": { + "2025-03-01": [ + "First Version Created." + ] + } + } + }, + "signers": { + "referenced": true, + "roles": { + "user": [ + "Proposer" + ] + }, + "update": { + "author": true, + "collaborators": true + } + }, + "type": [ + "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "78927329-cfd9-4ea1-9c71-0e019b126a65" + ] + }, + "Proposal Template": { + "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.", + "headers": { + "alg": { + "coseLabel": 1, + "description": "Default cryptographic signature algorithm", + "format": "COSE Algorithm", + "required": "optional" + }, + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA Media Type", + "required": "yes", + "value": "application/schema+json" + }, + "content-encoding": { + "coseLabel": "content-encoding", + "description": "Supported HTTP Encodings of the Payload", + "format": "HTTP Content Encoding", + "required": "optional", + "value": [ + "br" + ] + } + }, + "metadata": { + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "optional", + "type": "Category Parameters", + "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes" + }, + "template": { + "description": "Reference to the template used to create and/or validate this document.", + "format": "Document Reference", + "required": "optional", + "type": "Proposal Meta Template", + "validation": "The document payload is not valid if it does not validate completely against the referenced template." + }, + "ver": { + "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "payload": { + "description": "JSON Schema document which defines the valid contents of a proposal document." + }, + "signers": { + "roles": { + "admin": [ + "BrandAdmin", + "CampaignAdmin" + ], + "user": [] + }, + "update": { + "author": true } + }, + "type": [ + "0ce8ab38-9258-4fbc-a62e-7faa6e58318f", + "7808d2ba-d511-40af-84e8-c0d1625fdfdc" + ] } + } } From 38798aa08217b6bf282493cc09813f0b49386618 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 13:42:56 +0400 Subject: [PATCH 12/35] feat: Add base types information to the json version of the document specifications --- specs/signed_doc.json | 9 +++++++++ specs/signed_docs/signed_doc.cue | 3 +++ 2 files changed, 12 insertions(+) diff --git a/specs/signed_doc.json b/specs/signed_doc.json index e2dd4deaba..fdd92ed3e4 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -1,4 +1,13 @@ { + "base_types": { + "Action": "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "Category": "818938c3-3139-4daa-afe6-974c78488e95", + "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "ModerationAction": "a5d232b8-5e03-4117-9afd-be32b878fcdd", + "Proposal": "7808d2ba-d511-40af-84e8-c0d1625fdfdc", + "SubmissionAction": "78927329-cfd9-4ea1-9c71-0e019b126a65", + "Template": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" + }, "docs": { "Category Parameters": { "headers": { diff --git a/specs/signed_docs/signed_doc.cue b/specs/signed_docs/signed_doc.cue index 774172db9f..c4b94cf777 100644 --- a/specs/signed_docs/signed_doc.cue +++ b/specs/signed_docs/signed_doc.cue @@ -53,6 +53,9 @@ docs: #DocumentDefinitions & { } } +// base Document Types to help with automated processing of the document schema information. +base_types: _allDocTypes + // Ensure that all Document Type IDs are Unique. // See: all_docs.cue for a list of all known document types. _allDocTypeIDs: list.UniqueItems From b3a93a2ea00351f4e6f1d684e470331c0cc64b77 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 14:45:31 +0400 Subject: [PATCH 13/35] fix: add recommended justfile extension for vscode --- .vscode/extensions.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index fdc5b1d78d..e5e1743e17 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -24,5 +24,6 @@ "dtsvet.vscode-wasm", "terrastruct.d2", "fill-labs.dependi", + "nefrob.vscode-just-syntax", ] } \ No newline at end of file From 7bed21ca1a3b6e8c355fe165ad6998baf62e1697 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 16:49:10 +0400 Subject: [PATCH 14/35] feat: Example of building docs directly from specification data --- docs/Earthfile | 4 + docs/macros/__init__.py | 20 ++++ docs/macros/signed_docs.py | 106 ++++++++++++++++++ .../catalyst_docs/category_parameters.md | 0 .../catalyst_docs/comment_action_document.md | 0 .../catalyst_docs/proposal_comment.md | 0 .../proposal_comment_meta_template.md | 0 .../proposal_comment_template.md | 0 .../catalyst_docs/proposal_meta_template.md | 0 .../proposal_moderation_action.md | 0 .../proposal_submission_action.md | 0 .../catalyst_docs/proposal_template.md | 0 .../08_concepts/signed_doc/types.md | 39 +++---- specs/Earthfile | 2 + utilities/docs-preview/.gitignore | 1 + utilities/docs-preview/Earthfile | 8 ++ utilities/docs-preview/justfile | 20 ++++ 17 files changed, 178 insertions(+), 22 deletions(-) create mode 100644 docs/macros/__init__.py create mode 100644 docs/macros/signed_docs.py create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md create mode 100644 utilities/docs-preview/.gitignore create mode 100644 utilities/docs-preview/Earthfile create mode 100644 utilities/docs-preview/justfile diff --git a/docs/Earthfile b/docs/Earthfile index 15382b4739..94b1f21790 100644 --- a/docs/Earthfile +++ b/docs/Earthfile @@ -4,6 +4,7 @@ IMPORT github.com/input-output-hk/catalyst-ci/earthly/docs:v3.3.0 AS docs-ci IMPORT .. AS repo +IMPORT ../specs AS specs # Copy all the source we need to build the docs src: @@ -13,6 +14,9 @@ src: # Now copy into that any artifacts we pull from the builds. COPY --dir repo+repo-docs/repo /docs/includes + # Copy our generated Signed Document Specification data. + COPY specs+src/signed_doc.json /docs/includes + # Build the docs here. docs: diff --git a/docs/macros/__init__.py b/docs/macros/__init__.py new file mode 100644 index 0000000000..92da0b46db --- /dev/null +++ b/docs/macros/__init__.py @@ -0,0 +1,20 @@ +from .include import inc_file +from .signed_docs import (doc_type_summary, doc_type_details) + +def define_env(env): + """ + This is the hook for defining variables, macros and filters + """ + + @env.macro + def include_file(filename, start_line=0, end_line=None, indent=None): + # Provided by the base mkdocs config. + return inc_file(env, filename, start_line, end_line, indent) + + @env.macro + def insert_doc_type_summary(): + return doc_type_summary(env) + + @env.macro + def insert_doc_type_details(): + return doc_type_details(env) diff --git a/docs/macros/signed_docs.py b/docs/macros/signed_docs.py new file mode 100644 index 0000000000..bc207613ea --- /dev/null +++ b/docs/macros/signed_docs.py @@ -0,0 +1,106 @@ +import os +import re +import textwrap +import json + +#SIGNED_DOCS_SPECS="signed_doc.json" +SIGNED_DOCS_SPECS="includes/signed_doc.json" + +def uuid_as_cbor(uuid): + return f"37(h'{uuid.replace('-', '')}')" + + +def get_signed_doc_data(env): + """ + Load the Signed Document Data from its json file. + """ + full_filename = os.path.join(env.project_dir, SIGNED_DOCS_SPECS) + + with open(full_filename, "r") as f: + return json.load(f) + +def doc_type_summary(env): + """ + Generate a Document Base Type Summary from the Document Specifications Data + """ + + try: + doc_data = get_signed_doc_data(env) + doc_types = doc_data["base_types"] + + doc_type_summary = """ +| Base Type | [UUID] | [CBOR] | +| :--- | :--- | :--- | +""" + + for k in doc_types: + doc_type_summary += f"| {k} | `{doc_types[k]}` | `{uuid_as_cbor(doc_types[k])}` |\n" + + return doc_type_summary + except Exception as exc: + return f"{exc}" + + +def name_for_uuid(doc_types, uuid): + """ + Get the name for a document base type, given its uuid + """ + for k in doc_types: + if doc_types[k] == uuid: + return k + return "Unknown" + + +def name_to_spec_link(name,ref=None): + """ + Create a link to a document type, and an optional ref inside the document. + """ + link = "./../catalyst_docs/"+name.lower().replace(' ','_') + ".md" + if ref is not None: + link += f"#{ref}" + return link + +def base_types(docs, doc_types, name): + types = docs[name]["type"] + type_names = "" + for sub_type in types: + type_names += name_for_uuid(doc_types, sub_type) + "/" + return type_names[:-1] + +def types_as_cbor(docs, name): + types = docs[name]["type"] + type_names = "[" + for sub_type in types: + type_names += uuid_as_cbor(sub_type) + ",
" + return type_names[:-6] + "]" + + +def doc_type_details(env): + """ + Generate a Document Type Detailed Summary from the Document Specifications Data + """ + + try: + doc_data = get_signed_doc_data(env) + doc_types = doc_data["base_types"] + docs = doc_data["docs"] + + doc_type_details = """ +| Document Type | Base Types | [CBOR] | Specification | +| :--- | :--- | :--- | :--- | +""" + + for k in docs: + doc_type_details += f"| {k} | {base_types(docs,doc_types,k)} | {types_as_cbor(docs,k)} | [Specification]({name_to_spec_link(k)}) | \n" + + return doc_type_details + except Exception as exc: + return f"{exc}" + +#class env: +# project_dir = "/home/steven/Development/iohk/catalyst-libs/specs" + +#if __name__ == '__main__': + +# print(doc_type_details(env)) +# print(doc_type_summary(env)) \ No newline at end of file diff --git a/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md b/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index c7cd60aabe..8c622818db 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -1,26 +1,21 @@ # Document Types Table -| [UUID] | [CBOR] | Type Description | Payload Type | Specification Link | -| ------------------------------------ | ----------------------------------------- | ---------------------------- | --------------------------------- | ------------------------------------------------------------------------------ | -| 7808d2ba-d511-40af-84e8-c0d1625fdfdc | `37(h'7808d2bad51140af84e8c0d1625fdfdc')` | Proposal Document | [Brotli] Compressed [JSON] | [Proposal Spec](./../catalyst_docs/proposal.md#proposal-document) | -| 0ce8ab38-9258-4fbc-a62e-7faa6e58318f | `37(h'0ce8ab3892584fbca62e7faa6e58318f')` | Proposal Template | [Brotli] Compressed [JSON Schema] | [Proposal Template Spec](./../catalyst_docs/proposal.md#proposal-template) | -| b679ded3-0e7c-41ba-89f8-da62a17898ea | `37(h'b679ded30e7c41ba89f8da62a17898ea')` | Comment Document | [Brotli] Compressed [JSON] | [Comment Spec](./../catalyst_docs/comment.md#comment-document) | -| 0b8424d4-ebfd-46e3-9577-1775a69d290c | `37(h'0b8424d4ebfd46e395771775a69d290c')` | Comment Template | [Brotli] Compressed [JSON Schema] | [Comment Template Spec](./../catalyst_docs/comment.md#comment-template) | -| e4caf5f0-098b-45fd-94f3-0702a4573db5 | `37(h'e4caf5f0098b45fd94f30702a4573db5')` | Review Document | [Brotli] Compressed [JSON] | [Review Spec](./../catalyst_docs/review.md#review-document) | -| ebe5d0bf-5d86-4577-af4d-008fddbe2edc | `37(h'ebe5d0bf5d864577af4d008fddbe2edc')` | Review Template | [Brotli] Compressed [JSON Schema] | [Review Template Spec](./../catalyst_docs/review.md#review-template) | -| 48c20109-362a-4d32-9bba-e0a9cf8b45be | `37(h'48c20109362a4d329bbae0a9cf8b45be')` | Category Parameters Document | [Brotli] Compressed [JSON] | *TBD* | -| 65b1e8b0-51f1-46a5-9970-72cdf26884be | `37(h'65b1e8b051f146a5997072cdf26884be')` | Category Parameters Template | [Brotli] Compressed [JSON Schema] | *TBD* | -| 0110ea96-a555-47ce-8408-36efe6ed6f7c | `37(h'0110ea96a55547ce840836efe6ed6f7c')` | Campaign Parameters Document | [Brotli] Compressed [JSON] | *TBD* | -| 7e8f5fa2-44ce-49c8-bfd5-02af42c179a3 | `37(h'7e8f5fa244ce49c8bfd502af42c179a3')` | Campaign Parameters Template | [Brotli] Compressed [JSON Schema] | *TBD* | -| 3e4808cc-c86e-467b-9702-d60baa9d1fca | `37(h'3e4808ccc86e467b9702d60baa9d1fca')` | Brand Parameters Document | [Brotli] Compressed [JSON] | *TBD* | -| fd3c1735-80b1-4eea-8d63-5f436d97ea31 | `37(h'fd3c173580b14eea8d635f436d97ea31')` | Brand Parameters Template | [Brotli] Compressed [JSON Schema] | *TBD* | -| 5e60e623-ad02-4a1b-a1ac-406db978ee48 | `37(h'5e60e623ad024a1ba1ac406db978ee48')` | Proposal Action Document | [Brotli] Compressed [JSON] | *TBD* | -| 8de5586c-e998-4b95-8742-7be3c8592803 | `37(h'8DE5586CE9984B9587427BE3C8592803')` | Public Vote Tx V2 | [Brotli] Compressed [CBOR] | [Public Vote Tx V2 Spec](./../catalyst_voting/v2.md#public-vote) | -| e78ee18d-f380-44c1-a852-80aa6ecb07fe | `37(h'E78EE18DF38044C1A85280AA6ECB07FE')` | Private Vote Tx V2 | [Brotli] Compressed [CBOR] | [Private Vote Tx V2 Spec](./../catalyst_voting/v2.md#private-vote) | -| d9e7e6ce-2401-4d7d-9492-f4f7c64241c3 | `37(h'D9E7E6CE24014D7D9492F4F7C64241C3')` | Immutable Ledger Block | [Brotli] Compressed [CBOR] | [Immutable Ledger Block Spec](./../immutable_ledger/ledger.md#block-structure) | - -[JSON Schema]: https://json-schema.org/draft-07 -[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 -[Brotli]: https://datatracker.ietf.org/doc/html/rfc7932 +## Document Base Types + +All Document Types are defined by composing these base document types: + +{{ insert_doc_type_summary() }} + +## Document Types + +All Defined Document Types + +{{ insert_doc_type_details() }} + + + + + + [CBOR]: https://datatracker.ietf.org/doc/html/rfc8610 [UUID]: https://www.rfc-editor.org/rfc/rfc9562.html diff --git a/specs/Earthfile b/specs/Earthfile index b028b22ddd..b396d9d92a 100644 --- a/specs/Earthfile +++ b/specs/Earthfile @@ -21,6 +21,8 @@ src: COPY . . ENV CUE_EXPERIMENT="embed" + SAVE ARTIFACT signed_doc.json + check: FROM +src diff --git a/utilities/docs-preview/.gitignore b/utilities/docs-preview/.gitignore new file mode 100644 index 0000000000..799bc6ef79 --- /dev/null +++ b/utilities/docs-preview/.gitignore @@ -0,0 +1 @@ +local.py \ No newline at end of file diff --git a/utilities/docs-preview/Earthfile b/utilities/docs-preview/Earthfile new file mode 100644 index 0000000000..9bbe251605 --- /dev/null +++ b/utilities/docs-preview/Earthfile @@ -0,0 +1,8 @@ +VERSION 0.8 + +IMPORT github.com/input-output-hk/catalyst-ci/earthly/docs:v3.3.0 AS docs-ci + + +# update-docs-dev-script: get the latest docs dev script from CI. +update-docs-dev-script: + DO docs-ci+SYNC_LOCAL_DOCS \ No newline at end of file diff --git a/utilities/docs-preview/justfile b/utilities/docs-preview/justfile new file mode 100644 index 0000000000..fa99575bc1 --- /dev/null +++ b/utilities/docs-preview/justfile @@ -0,0 +1,20 @@ +# use with https://github.com/casey/just +# +# Catalyst Voices Documentation Local Preview Build + +# cspell: words prereqs, commitlog + +default: + @just --list --unsorted + +# Ensure we have the latest version of the dev docs script locally. +update-docs-dev-script: + earthly +update-docs-dev-script + +# Live rebuilds and deploys the documentation locally. +# +# See root Justfile for full documentation. +preview-docs: update-docs-dev-script + echo "Requires Python Installed. Version >= 3.11" + python --version + ./local.py --target "../../docs+local" --exposed-port 8280 catalyst-libs-docs:latest From 4b9f6da3cdf783cb0c5ad57e7e3635cb1a194ef6 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 16:52:54 +0400 Subject: [PATCH 15/35] fix: spelling --- .config/dictionaries/project.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index 4aeb2f3e10..21f1fd4a95 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -124,6 +124,7 @@ jorm jormungandr Jörmungandr jsonschema +Justfile kiduri lcov Leay From 39bbe308bb3a66684853fc3dc79e0738a8704227 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Sun, 2 Mar 2025 16:58:40 +0400 Subject: [PATCH 16/35] fix: Spelling and Markdown --- .../08_concepts/catalyst_docs/category_parameters.md | 1 + .../08_concepts/catalyst_docs/comment_action_document.md | 1 + .../architecture/08_concepts/catalyst_docs/proposal_comment.md | 1 + .../08_concepts/catalyst_docs/proposal_comment_meta_template.md | 1 + .../08_concepts/catalyst_docs/proposal_comment_template.md | 1 + .../08_concepts/catalyst_docs/proposal_meta_template.md | 1 + .../08_concepts/catalyst_docs/proposal_moderation_action.md | 1 + .../08_concepts/catalyst_docs/proposal_submission_action.md | 1 + .../architecture/08_concepts/catalyst_docs/proposal_template.md | 1 + 9 files changed, 9 insertions(+) diff --git a/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md index e69de29bb2..f7cfc54b65 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md @@ -0,0 +1 @@ +# Category Parameters diff --git a/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md b/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md index e69de29bb2..9ba9b5a22b 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md @@ -0,0 +1 @@ +# Comment Action Document diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md index e69de29bb2..dc42b9e43d 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md @@ -0,0 +1 @@ +# Proposal Comment diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md index e69de29bb2..03a8bf55c2 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md @@ -0,0 +1 @@ +# Comment Action Meta Template diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md index e69de29bb2..5ff44d3d96 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md @@ -0,0 +1 @@ +# Proposal Comment Template diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md index e69de29bb2..0f15369a85 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md @@ -0,0 +1 @@ +# Proposal Meta Template diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md index e69de29bb2..d396db966f 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md @@ -0,0 +1 @@ +# Proposal Moderation Action diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md index e69de29bb2..e1aa8dfe2f 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md @@ -0,0 +1 @@ +# Proposal Submission Action diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md index e69de29bb2..dffc2cfea0 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md @@ -0,0 +1 @@ +# Proposal Template From 044878d9df01480eca9f392d370eb0bb83eed460 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 5 Mar 2025 18:08:07 +0400 Subject: [PATCH 17/35] feat: Add documentation auto generation for new signed documents --- .config/dictionaries/project.dic | 1 + .gitignore | 3 + .markdownlint-cli2.jsonc | 3 +- Justfile | 15 +- docs/macros/__init__.py | 7 +- docs/macros/signed_docs.py | 43 +++-- .../08_concepts/catalyst_docs/.pages | 4 - .../catalyst_docs/category_parameters.md | 2 +- .../catalyst_docs/comment_action_document.md | 2 +- .../{comment.md => old_comment.md} | 0 .../08_concepts/catalyst_docs/old_proposal.md | 159 +++++++++++++++++ .../{review.md => old_review.md} | 0 .../08_concepts/catalyst_docs/proposal.md | 160 +----------------- .../catalyst_docs/proposal_comment.md | 2 +- .../proposal_comment_meta_template.md | 2 +- .../proposal_comment_template.md | 2 +- .../catalyst_docs/proposal_meta_template.md | 2 +- .../proposal_moderation_action.md | 2 +- .../proposal_submission_action.md | 2 +- .../catalyst_docs/proposal_template.md | 2 +- specs/Justfile | 1 + specs/utility/gen_doc_pages.py | 48 ++++++ 22 files changed, 273 insertions(+), 189 deletions(-) rename docs/src/architecture/08_concepts/catalyst_docs/{comment.md => old_comment.md} (100%) create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/old_proposal.md rename docs/src/architecture/08_concepts/catalyst_docs/{review.md => old_review.md} (100%) create mode 100755 specs/utility/gen_doc_pages.py diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index 21f1fd4a95..f9152e1510 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -202,6 +202,7 @@ pubkey publickey pubspec pwrite +pytest qpsg quic rapidoc diff --git a/.gitignore b/.gitignore index e881c8d539..438959f5d5 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,6 @@ $RECYCLE.BIN/ # Dart stuff /pubspec.lock /.dart_tool/**/* + +# Python stuff +.pytest_cache \ No newline at end of file diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc index e3852a9805..04934f5ab7 100644 --- a/.markdownlint-cli2.jsonc +++ b/.markdownlint-cli2.jsonc @@ -10,7 +10,8 @@ "ignores": [ ".config/dictionaries/**", "**/target/**", - "**/.dart_tool/**" + "**/.dart_tool/**", + "**/.pytest_cache/**" ], // Set standard config options in `/.markdownlint.jsonc` "config": { diff --git a/Justfile b/Justfile index 33dd85054d..d632ca712e 100644 --- a/Justfile +++ b/Justfile @@ -15,6 +15,19 @@ check-spelling: earthly +check-spelling +# Fix and Check Markdown files +format-python-code: + ruff check --select I --fix . + ruff format . + +# Fix and Check Markdown files +lint-python: + ruff check . + +# generates specifications data +gen_specs: + just specs/pre-push + # Pre Push Checks - intended to be run by a git pre-push hook. -pre-push: check-markdown check-spelling +pre-push: gen_specs check-markdown check-spelling format-python-code lint-python just rust/pre-push diff --git a/docs/macros/__init__.py b/docs/macros/__init__.py index 92da0b46db..23f8a19410 100644 --- a/docs/macros/__init__.py +++ b/docs/macros/__init__.py @@ -1,5 +1,6 @@ from .include import inc_file -from .signed_docs import (doc_type_summary, doc_type_details) +from .signed_docs import doc_type_details, doc_type_summary, signed_doc_details + def define_env(env): """ @@ -18,3 +19,7 @@ def insert_doc_type_summary(): @env.macro def insert_doc_type_details(): return doc_type_details(env) + + @env.macro + def insert_signed_doc_details(name): + return signed_doc_details(env, name) diff --git a/docs/macros/signed_docs.py b/docs/macros/signed_docs.py index bc207613ea..2b84190f7f 100644 --- a/docs/macros/signed_docs.py +++ b/docs/macros/signed_docs.py @@ -1,10 +1,12 @@ -import os -import re -import textwrap import json +import os + +# import re +# import textwrap + +# SIGNED_DOCS_SPECS="signed_doc.json" +SIGNED_DOCS_SPECS = "includes/signed_doc.json" -#SIGNED_DOCS_SPECS="signed_doc.json" -SIGNED_DOCS_SPECS="includes/signed_doc.json" def uuid_as_cbor(uuid): return f"37(h'{uuid.replace('-', '')}')" @@ -19,6 +21,7 @@ def get_signed_doc_data(env): with open(full_filename, "r") as f: return json.load(f) + def doc_type_summary(env): """ Generate a Document Base Type Summary from the Document Specifications Data @@ -34,7 +37,9 @@ def doc_type_summary(env): """ for k in doc_types: - doc_type_summary += f"| {k} | `{doc_types[k]}` | `{uuid_as_cbor(doc_types[k])}` |\n" + doc_type_summary += ( + f"| {k} | `{doc_types[k]}` | `{uuid_as_cbor(doc_types[k])}` |\n" + ) return doc_type_summary except Exception as exc: @@ -50,16 +55,17 @@ def name_for_uuid(doc_types, uuid): return k return "Unknown" - -def name_to_spec_link(name,ref=None): + +def name_to_spec_link(name, ref=None): """ Create a link to a document type, and an optional ref inside the document. """ - link = "./../catalyst_docs/"+name.lower().replace(' ','_') + ".md" + link = "./../catalyst_docs/" + name.lower().replace(" ", "_") + ".md" if ref is not None: link += f"#{ref}" return link + def base_types(docs, doc_types, name): types = docs[name]["type"] type_names = "" @@ -67,6 +73,7 @@ def base_types(docs, doc_types, name): type_names += name_for_uuid(doc_types, sub_type) + "/" return type_names[:-1] + def types_as_cbor(docs, name): types = docs[name]["type"] type_names = "[" @@ -91,16 +98,24 @@ def doc_type_details(env): """ for k in docs: - doc_type_details += f"| {k} | {base_types(docs,doc_types,k)} | {types_as_cbor(docs,k)} | [Specification]({name_to_spec_link(k)}) | \n" + doc_type_details += f"| {k} | {base_types(docs, doc_types, k)} | {types_as_cbor(docs, k)} | [Specification]({name_to_spec_link(k)}) | \n" return doc_type_details except Exception as exc: return f"{exc}" -#class env: + +def signed_doc_details(env, name): + """ + Generate Signed Document Detailed Documentation Page. + """ + return name + "\n" + "test\n" + + +# class env: # project_dir = "/home/steven/Development/iohk/catalyst-libs/specs" -#if __name__ == '__main__': +# if __name__ == '__main__': -# print(doc_type_details(env)) -# print(doc_type_summary(env)) \ No newline at end of file +# print(doc_type_details(env)) +# print(doc_type_summary(env)) diff --git a/docs/src/architecture/08_concepts/catalyst_docs/.pages b/docs/src/architecture/08_concepts/catalyst_docs/.pages index 15986adb3b..8d05620e77 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/.pages +++ b/docs/src/architecture/08_concepts/catalyst_docs/.pages @@ -1,5 +1 @@ title: Catalyst Documents -arrange: -- proposal.md -- review.md -- comment.md \ No newline at end of file diff --git a/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md index f7cfc54b65..b751009bde 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md @@ -1 +1 @@ -# Category Parameters +# {{ insert_signed_doc_details( "Category Parameters" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md b/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md index 9ba9b5a22b..5b819f440f 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md @@ -1 +1 @@ -# Comment Action Document +# {{ insert_signed_doc_details( "Comment Action Document" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/comment.md b/docs/src/architecture/08_concepts/catalyst_docs/old_comment.md similarity index 100% rename from docs/src/architecture/08_concepts/catalyst_docs/comment.md rename to docs/src/architecture/08_concepts/catalyst_docs/old_comment.md diff --git a/docs/src/architecture/08_concepts/catalyst_docs/old_proposal.md b/docs/src/architecture/08_concepts/catalyst_docs/old_proposal.md new file mode 100644 index 0000000000..95390a229e --- /dev/null +++ b/docs/src/architecture/08_concepts/catalyst_docs/old_proposal.md @@ -0,0 +1,159 @@ +--- +Title: Catalyst Proposal Document +Category: Catalyst +Status: Proposed +Authors: + - Steven Johnson +Implementors: + - Catalyst Fund 14 +Discussions: [] +Created: 2024-12-29 +License: CC-BY-4.0 +--- + +## Abstract + +## Proposal Document + +This is a document, formatted against the referenced proposal template, which defines a proposal which may be submitted +for consideration under one or more brand campaign categories. + +The brand, campaign and category are not part of the document because the document can exist outside this boundary. +They are defined when a specific document is submitted for consideration. + +### Specification + +Catalyst Proposal document is a [Catalyst Signed Document], +so its fully follows the structure of the [Catalyst Signed Document] specification. + +#### Metadata Fields + +A list of used [Catalyst Signed Document protected header fields](./../signed_doc/spec.md#signed-object-fields). + +* [`type`](./../signed_doc/spec.md#type): `7808d2ba-d511-40af-84e8-c0d1625fdfdc` [UUID] value. + + ```CDDL + "type" => 37(h'7808d2bad51140af84e8c0d1625fdfdc') + ``` + +* [`content type`](./../signed_doc/spec.md#content-type): `application/json`. + [Catalyst Signed Document content] must be in [JSON] format. + + ```CDDL + 3 => 30 + ``` + +* [`content encoding`](./../signed_doc/spec.md#content-encoding-optional): + [Catalyst Signed Document content] must be [Brotli] compressed. + + ```CDDL + "content-encoding" => "br" + ``` + +* [`template`](./../signed_doc/meta.md#ref-document-reference). + A reference to the proposal template document, + which [`type`](./../signed_doc/spec.md#type) must be equal to + [proposal template `type`](#proposal-template) field value. + +* [`category_id`](./../signed_doc/meta.md#category_id) (optional). + A reference to the category document, + which [`type`](./../signed_doc/spec.md#type) must be equal to + `48c20109-362a-4d32-9bba-e0a9cf8b45be` value. + +#### Fund 14 defined category ids + +* id: `0194d490-30bf-7473-81c8-a0eaef369619` +* id: `0194d490-30bf-7043-8c5c-f0e09f8a6d8c` +* id: `0194d490-30bf-7e75-95c1-a6cf0e8086d9` +* id: `0194d490-30bf-7703-a1c0-83a916b001e7` +* id: `0194d490-30bf-79d1-9a0f-84943123ef38` +* id: `0194d490-30bf-706d-91c6-0d4707f74cdf` +* id: `0194d490-30bf-759e-b729-304306fbaa5e` +* id: `0194d490-30bf-7e27-b5fd-de3133b54bf6` +* id: `0194d490-30bf-7f9e-8a5d-91fb67c078f2` +* id: `0194d490-30bf-7676-9658-36c0b67e656e` +* id: `0194d490-30bf-7978-b031-7aa2ccc5e3fd` +* id: `0194d490-30bf-7d34-bba9-8498094bd627` + +#### Content format + +TODO + +## Proposal Template + +This document provides the template structure which a Proposal must be formatted to, and validated against. + +### Specification + +Catalyst Proposal Template document is a [Catalyst Signed Document], +so its fully follows the structure of the [Catalyst Signed Document] specification. + +#### Metadata Fields + +A list of used [Catalyst Signed Document protected header fields](./../signed_doc/spec.md#signed-object-fields). + +* [`type`](./../signed_doc/spec.md#type): `0ce8ab38-9258-4fbc-a62e-7faa6e58318f` [UUID] value. + + ```CDDL + "type" => 37(h'0ce8ab3892584fbca62e7faa6e58318f') + ``` + +* [`content type`](./../signed_doc/spec.md#content-type): `application/json`. + [Catalyst Signed Document content] must be in [JSON] format. + + ```CDDL + 3 => 30 + ``` + +* [`content encoding`](./../signed_doc/spec.md#content-encoding-optional): + [Catalyst Signed Document content] must be [Brotli] compressed. + + ```CDDL + "content-encoding" => "br" + ``` + +* [`category_id`](./../signed_doc/meta.md#category_id) (optional). + A reference to the category document, + which [`type`](./../signed_doc/spec.md#type) must be equal to + `48c20109-362a-4d32-9bba-e0a9cf8b45be` value. + +#### Fund 14 defined templates ids + +* id: `0194d492-1daa-75b5-b4a4-5cf331cd8d1a`, ver: `0194d492-1daa-75b5-b4a4-5cf331cd8d1a`, + category: `0194d490-30bf-7473-81c8-a0eaef369619` +* id: `0194d492-1daa-7371-8bd3-c15811b2b063`, ver: `0194d492-1daa-7371-8bd3-c15811b2b063`, + category: `0194d490-30bf-7043-8c5c-f0e09f8a6d8c` +* id: `0194d492-1daa-79c7-a222-2c3b581443a8`, ver: `0194d492-1daa-79c7-a222-2c3b581443a8`, + category: `0194d490-30bf-7e75-95c1-a6cf0e8086d9` +* id: `0194d492-1daa-716f-a04e-f422f08a99dc`, ver: `0194d492-1daa-716f-a04e-f422f08a99dc`, + category: `0194d490-30bf-7703-a1c0-83a916b001e7` +* id: `0194d492-1daa-78fc-818a-bf20fc3e9b87`, ver: `0194d492-1daa-78fc-818a-bf20fc3e9b87`, + category: `0194d490-30bf-79d1-9a0f-84943123ef38` +* id: `0194d492-1daa-7d98-a3aa-c57d99121f78`, ver: `0194d492-1daa-7d98-a3aa-c57d99121f78`, + category: `0194d490-30bf-706d-91c6-0d4707f74cdf` +* id: `0194d492-1daa-77be-a1a5-c238fe25fe4f`, ver: `0194d492-1daa-77be-a1a5-c238fe25fe4f`, + category: `0194d490-30bf-759e-b729-304306fbaa5e` +* id: `0194d492-1daa-7254-a512-30a4cdecfb90`, ver: `0194d492-1daa-7254-a512-30a4cdecfb90`, + category: `0194d490-30bf-7e27-b5fd-de3133b54bf6` +* id: `0194d492-1daa-7de9-b535-1a0b0474ed4e`, ver: `0194d492-1daa-7de9-b535-1a0b0474ed4e`, + category: `0194d490-30bf-7f9e-8a5d-91fb67c078f2` +* id: `0194d492-1daa-7fce-84ee-b872a4661075`, ver: `0194d492-1daa-7fce-84ee-b872a4661075`, + category: `0194d490-30bf-7676-9658-36c0b67e656e` +* id: `0194d492-1daa-7878-9bcc-2c79fef0fc13`, ver: `0194d492-1daa-7878-9bcc-2c79fef0fc13`, + category: `0194d490-30bf-7978-b031-7aa2ccc5e3fd` +* id: `0194d492-1daa-722f-94f4-687f2c068a5d`, ver: `0194d492-1daa-722f-94f4-687f2c068a5d`, + category: `0194d490-30bf-7d34-bba9-8498094bd627` + +#### Content format + +TODO + +## Copyright + +This document is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode). + +[Catalyst Signed Document]: ./../signed_doc/spec.md +[Catalyst Signed Document content]: ./../signed_doc/spec.md#signed-object-content +[Brotli]: https://datatracker.ietf.org/doc/html/rfc7932 +[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 +[UUID]: https://www.rfc-editor.org/rfc/rfc9562.html diff --git a/docs/src/architecture/08_concepts/catalyst_docs/review.md b/docs/src/architecture/08_concepts/catalyst_docs/old_review.md similarity index 100% rename from docs/src/architecture/08_concepts/catalyst_docs/review.md rename to docs/src/architecture/08_concepts/catalyst_docs/old_review.md diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal.md index 95390a229e..70b956cc20 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal.md @@ -1,159 +1 @@ ---- -Title: Catalyst Proposal Document -Category: Catalyst -Status: Proposed -Authors: - - Steven Johnson -Implementors: - - Catalyst Fund 14 -Discussions: [] -Created: 2024-12-29 -License: CC-BY-4.0 ---- - -## Abstract - -## Proposal Document - -This is a document, formatted against the referenced proposal template, which defines a proposal which may be submitted -for consideration under one or more brand campaign categories. - -The brand, campaign and category are not part of the document because the document can exist outside this boundary. -They are defined when a specific document is submitted for consideration. - -### Specification - -Catalyst Proposal document is a [Catalyst Signed Document], -so its fully follows the structure of the [Catalyst Signed Document] specification. - -#### Metadata Fields - -A list of used [Catalyst Signed Document protected header fields](./../signed_doc/spec.md#signed-object-fields). - -* [`type`](./../signed_doc/spec.md#type): `7808d2ba-d511-40af-84e8-c0d1625fdfdc` [UUID] value. - - ```CDDL - "type" => 37(h'7808d2bad51140af84e8c0d1625fdfdc') - ``` - -* [`content type`](./../signed_doc/spec.md#content-type): `application/json`. - [Catalyst Signed Document content] must be in [JSON] format. - - ```CDDL - 3 => 30 - ``` - -* [`content encoding`](./../signed_doc/spec.md#content-encoding-optional): - [Catalyst Signed Document content] must be [Brotli] compressed. - - ```CDDL - "content-encoding" => "br" - ``` - -* [`template`](./../signed_doc/meta.md#ref-document-reference). - A reference to the proposal template document, - which [`type`](./../signed_doc/spec.md#type) must be equal to - [proposal template `type`](#proposal-template) field value. - -* [`category_id`](./../signed_doc/meta.md#category_id) (optional). - A reference to the category document, - which [`type`](./../signed_doc/spec.md#type) must be equal to - `48c20109-362a-4d32-9bba-e0a9cf8b45be` value. - -#### Fund 14 defined category ids - -* id: `0194d490-30bf-7473-81c8-a0eaef369619` -* id: `0194d490-30bf-7043-8c5c-f0e09f8a6d8c` -* id: `0194d490-30bf-7e75-95c1-a6cf0e8086d9` -* id: `0194d490-30bf-7703-a1c0-83a916b001e7` -* id: `0194d490-30bf-79d1-9a0f-84943123ef38` -* id: `0194d490-30bf-706d-91c6-0d4707f74cdf` -* id: `0194d490-30bf-759e-b729-304306fbaa5e` -* id: `0194d490-30bf-7e27-b5fd-de3133b54bf6` -* id: `0194d490-30bf-7f9e-8a5d-91fb67c078f2` -* id: `0194d490-30bf-7676-9658-36c0b67e656e` -* id: `0194d490-30bf-7978-b031-7aa2ccc5e3fd` -* id: `0194d490-30bf-7d34-bba9-8498094bd627` - -#### Content format - -TODO - -## Proposal Template - -This document provides the template structure which a Proposal must be formatted to, and validated against. - -### Specification - -Catalyst Proposal Template document is a [Catalyst Signed Document], -so its fully follows the structure of the [Catalyst Signed Document] specification. - -#### Metadata Fields - -A list of used [Catalyst Signed Document protected header fields](./../signed_doc/spec.md#signed-object-fields). - -* [`type`](./../signed_doc/spec.md#type): `0ce8ab38-9258-4fbc-a62e-7faa6e58318f` [UUID] value. - - ```CDDL - "type" => 37(h'0ce8ab3892584fbca62e7faa6e58318f') - ``` - -* [`content type`](./../signed_doc/spec.md#content-type): `application/json`. - [Catalyst Signed Document content] must be in [JSON] format. - - ```CDDL - 3 => 30 - ``` - -* [`content encoding`](./../signed_doc/spec.md#content-encoding-optional): - [Catalyst Signed Document content] must be [Brotli] compressed. - - ```CDDL - "content-encoding" => "br" - ``` - -* [`category_id`](./../signed_doc/meta.md#category_id) (optional). - A reference to the category document, - which [`type`](./../signed_doc/spec.md#type) must be equal to - `48c20109-362a-4d32-9bba-e0a9cf8b45be` value. - -#### Fund 14 defined templates ids - -* id: `0194d492-1daa-75b5-b4a4-5cf331cd8d1a`, ver: `0194d492-1daa-75b5-b4a4-5cf331cd8d1a`, - category: `0194d490-30bf-7473-81c8-a0eaef369619` -* id: `0194d492-1daa-7371-8bd3-c15811b2b063`, ver: `0194d492-1daa-7371-8bd3-c15811b2b063`, - category: `0194d490-30bf-7043-8c5c-f0e09f8a6d8c` -* id: `0194d492-1daa-79c7-a222-2c3b581443a8`, ver: `0194d492-1daa-79c7-a222-2c3b581443a8`, - category: `0194d490-30bf-7e75-95c1-a6cf0e8086d9` -* id: `0194d492-1daa-716f-a04e-f422f08a99dc`, ver: `0194d492-1daa-716f-a04e-f422f08a99dc`, - category: `0194d490-30bf-7703-a1c0-83a916b001e7` -* id: `0194d492-1daa-78fc-818a-bf20fc3e9b87`, ver: `0194d492-1daa-78fc-818a-bf20fc3e9b87`, - category: `0194d490-30bf-79d1-9a0f-84943123ef38` -* id: `0194d492-1daa-7d98-a3aa-c57d99121f78`, ver: `0194d492-1daa-7d98-a3aa-c57d99121f78`, - category: `0194d490-30bf-706d-91c6-0d4707f74cdf` -* id: `0194d492-1daa-77be-a1a5-c238fe25fe4f`, ver: `0194d492-1daa-77be-a1a5-c238fe25fe4f`, - category: `0194d490-30bf-759e-b729-304306fbaa5e` -* id: `0194d492-1daa-7254-a512-30a4cdecfb90`, ver: `0194d492-1daa-7254-a512-30a4cdecfb90`, - category: `0194d490-30bf-7e27-b5fd-de3133b54bf6` -* id: `0194d492-1daa-7de9-b535-1a0b0474ed4e`, ver: `0194d492-1daa-7de9-b535-1a0b0474ed4e`, - category: `0194d490-30bf-7f9e-8a5d-91fb67c078f2` -* id: `0194d492-1daa-7fce-84ee-b872a4661075`, ver: `0194d492-1daa-7fce-84ee-b872a4661075`, - category: `0194d490-30bf-7676-9658-36c0b67e656e` -* id: `0194d492-1daa-7878-9bcc-2c79fef0fc13`, ver: `0194d492-1daa-7878-9bcc-2c79fef0fc13`, - category: `0194d490-30bf-7978-b031-7aa2ccc5e3fd` -* id: `0194d492-1daa-722f-94f4-687f2c068a5d`, ver: `0194d492-1daa-722f-94f4-687f2c068a5d`, - category: `0194d490-30bf-7d34-bba9-8498094bd627` - -#### Content format - -TODO - -## Copyright - -This document is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode). - -[Catalyst Signed Document]: ./../signed_doc/spec.md -[Catalyst Signed Document content]: ./../signed_doc/spec.md#signed-object-content -[Brotli]: https://datatracker.ietf.org/doc/html/rfc7932 -[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 -[UUID]: https://www.rfc-editor.org/rfc/rfc9562.html +# {{ insert_signed_doc_details( "Proposal" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md index dc42b9e43d..3b42dfa6eb 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md @@ -1 +1 @@ -# Proposal Comment +# {{ insert_signed_doc_details( "Proposal Comment" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md index 03a8bf55c2..e6ba1239fa 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md @@ -1 +1 @@ -# Comment Action Meta Template +# {{ insert_signed_doc_details( "Proposal Comment Meta Template" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md index 5ff44d3d96..ed0adefd44 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md @@ -1 +1 @@ -# Proposal Comment Template +# {{ insert_signed_doc_details( "Proposal Comment Template" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md index 0f15369a85..2fa7ff69a9 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md @@ -1 +1 @@ -# Proposal Meta Template +# {{ insert_signed_doc_details( "Proposal Meta Template" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md index d396db966f..6e2cd8b7a0 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md @@ -1 +1 @@ -# Proposal Moderation Action +# {{ insert_signed_doc_details( "Proposal Moderation Action" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md index e1aa8dfe2f..3368648bc8 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md @@ -1 +1 @@ -# Proposal Submission Action +# {{ insert_signed_doc_details( "Proposal Submission Action" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md index dffc2cfea0..abe2348a39 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md @@ -1 +1 @@ -# Proposal Template +# {{ insert_signed_doc_details( "Proposal Template" ) }} diff --git a/specs/Justfile b/specs/Justfile index de3ef0c858..2b030cc7ad 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -20,6 +20,7 @@ check: format regenerate: check # 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 utility; ./gen_doc_pages.py # Validate the generated signed_docs.json is correct against the cue schema. validate: diff --git a/specs/utility/gen_doc_pages.py b/specs/utility/gen_doc_pages.py new file mode 100755 index 0000000000..ea9c8f0cd7 --- /dev/null +++ b/specs/utility/gen_doc_pages.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# Autogenerate Documentation Pages for each signed document +# Will only create new pages and will not modify existing ones. + +import json +from pathlib import Path + +# import re +# import textwrap + +SIGNED_DOCS_SPECS = "../signed_doc.json" +SIGNED_DOCS_PAGES_DIR = "../../docs/src/architecture/08_concepts/catalyst_docs" + + +def get_signed_doc_data(): + """ + Load the Signed Document Data from its json file. + """ + with open(SIGNED_DOCS_SPECS, "r") as f: + return json.load(f) + + +def create_missing_doc_files(): + """ + Create basic markdown files for any document types that are missing. + """ + + docs = get_signed_doc_data() + all_docs = docs["docs"] + + for doc_name in all_docs: + file_name = doc_name.lower().replace(" ", "_") + ".md" + print(f"{doc_name} : {file_name}") + + doc_path = Path(SIGNED_DOCS_PAGES_DIR, file_name) + if doc_path.is_file(): + print("Exists") + else: + new_doc_contents = '# {{{{ insert_signed_doc_details( "{}" ) }}}}\n'.format( + doc_name + ) + doc_path.write_text(new_doc_contents) + print("Created") + + +if __name__ == "__main__": + create_missing_doc_files() From 2191d7f00f4e3ba3d77d1e7b531c74df2cded88c Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 5 Mar 2025 18:08:37 +0400 Subject: [PATCH 18/35] feat: Add status which allows a reference to define one or multiple references. --- specs/signed_docs/metadata.cue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/signed_docs/metadata.cue b/specs/signed_docs/metadata.cue index 956cea3f55..5aca455dfe 100644 --- a/specs/signed_docs/metadata.cue +++ b/specs/signed_docs/metadata.cue @@ -47,7 +47,8 @@ _allMetadataNames: or([ // Format of the field. format: #metadataFormat if format == "Document Reference" { - type: #DocumentName + type: #DocumentName + multiple?: bool | *false } // Markdown description of the field. From a10363617b7e62fc7be14321174b629a10ccdb8f Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 5 Mar 2025 18:10:46 +0400 Subject: [PATCH 19/35] feat: Add three states to document submission and change the names to more align with intent vs business logic behaviour. --- .../payload_schemas/proposal_submission_action.schema.json | 5 +++-- specs/signed_docs/docs/proposal_submission_action.cue | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json index c97bf97a4d..07b369012b 100644 --- a/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json +++ b/specs/signed_docs/docs/payload_schemas/proposal_submission_action.schema.json @@ -20,8 +20,9 @@ "type": "string", "description": "The action being performed on the Proposal.", "enum": [ - "submission", - "retraction" + "final", + "draft", + "hide" ] } }, diff --git a/specs/signed_docs/docs/proposal_submission_action.cue b/specs/signed_docs/docs/proposal_submission_action.cue index 8a6b488eb9..5167c266f0 100644 --- a/specs/signed_docs/docs/proposal_submission_action.cue +++ b/specs/signed_docs/docs/proposal_submission_action.cue @@ -38,6 +38,13 @@ docs: #DocumentDefinitions & { description: """ The kind of action is controlled by this payload. The Payload is a JSON 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. + * `hide` : Requests the proposal be hidden (not final, but a hidden draft). + `hide` is only actioned if sent by the author, for a collaborator its synonymous with `draft`. """ schema: _ @embed(file="payload_schemas/proposal_submission_action.schema.json") } From d7f7cbd1693388e5c7d9001082f6f7af9cf86cc0 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 5 Mar 2025 18:50:08 +0400 Subject: [PATCH 20/35] feat: Rationalize ref/ref_hash and collation into a single `ref` metadata field. --- specs/signed_doc.json | 21 +++++---- .../docs/proposal_submission_action.cue | 4 +- specs/signed_docs/metadata.cue | 45 ++++--------------- 3 files changed, 23 insertions(+), 47 deletions(-) diff --git a/specs/signed_doc.json b/specs/signed_doc.json index fdd92ed3e4..612f84949b 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -232,7 +232,7 @@ "required": "yes" }, "ref": { - "description": "Reference to a Linked Document. \nThis is the primary hierarchial reference to a related document.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", "required": "yes", "type": "Proposal" @@ -581,16 +581,18 @@ "type": "Category Parameters", "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, - "collation": { - "description": "Array of Collated Document References\n\nThis is an Array of the format:\n `[[DocumentID, DocumentVer, DocumentHash],...]`\n\nIt is equivalent to `ref` plus `ref_hash` but allows multiple documents to be \nreferenced simultaneously. \nWhen a `collation` is used, Version and Hash are required.\n\nWhen `collation` and `ref` appear in the same document, \nthe first document in the collation list must be identical to the `ref` and `ref_hash` \nmust be present.", - "format": "Document Collation Reference", - "required": "yes" - }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", "required": "yes" }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "multiple": true, + "required": "yes", + "type": "Proposal" + }, "ver": { "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "format": "UUIDv7", @@ -599,7 +601,7 @@ } }, "payload": { - "description": "The kind of action is controlled by this payload.\nThe Payload is a JSON Document, and must conform to this schema.", + "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. \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, for a collaborator its synonymous with `draft`.", "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#", @@ -608,8 +610,9 @@ "action": { "description": "The action being performed on the Proposal.", "enum": [ - "submission", - "retraction" + "final", + "draft", + "hide" ], "type": "string" } diff --git a/specs/signed_docs/docs/proposal_submission_action.cue b/specs/signed_docs/docs/proposal_submission_action.cue index 5167c266f0..6004066415 100644 --- a/specs/signed_docs/docs/proposal_submission_action.cue +++ b/specs/signed_docs/docs/proposal_submission_action.cue @@ -24,8 +24,10 @@ docs: #DocumentDefinitions & { """ metadata: { - collation: { + ref: { + type: "Proposal" required: "yes" + multiple: true } category_id: { diff --git a/specs/signed_docs/metadata.cue b/specs/signed_docs/metadata.cue index 5aca455dfe..ed5c4991d4 100644 --- a/specs/signed_docs/metadata.cue +++ b/specs/signed_docs/metadata.cue @@ -15,8 +15,7 @@ import ( "Document Reference" | "Document Hash" | "Section Reference" | - "Collaborators Reference List" | - "Document Collation Reference" + "Collaborators Reference List" // Canonical List of all valid metadata names _metadataNames: list.UniqueItems @@ -24,8 +23,6 @@ _metadataNames: [ "id", "ver", "ref", - "ref_hash", - "collation", "template", "reply", "section", @@ -85,43 +82,17 @@ _metadata: #metadataStruct & { ref?: #metadataField & { format: "Document Reference" description: """ - Reference to a Linked Document. + Reference to a Linked Document or Documents. This is the primary hierarchial reference to a related document. - """ - } - - // IF we have a ref, we can optionally have a `ref_hash` - if ref != _|_ { - ref_hash?: #metadataField & { - format: "Document Hash" - description: """ - Hash of the referenced document. - This is the Blake2b-256 Hash over the entire referenced signed document. - It ensures that the intended referenced document is the one used. - - Prevents substitutions where a new document with the same Document ID and Ver might be - published over an existing one. - - This is only used when there could be security issues with substitutions of the referenced document. - """ - } - } - - collation?: #metadataField & { - format: "Document Collation Reference" - description: """ - Array of Collated Document References This is an Array of the format: - `[[DocumentID, DocumentVer, DocumentHash],...]` - - It is equivalent to `ref` plus `ref_hash` but allows multiple documents to be - referenced simultaneously. - When a `collation` is used, Version and Hash are required. + `[[DocumentID, DocumentVer, DocumentHash],...]` - When `collation` and `ref` appear in the same document, - the first document in the collation list must be identical to the `ref` and `ref_hash` - must be present. + * `DocumentID` is the [UUIDv7] ID of the Document being referenced. + * `DocumentVer` is the [UUIDv7] Version of the Document being referenced. + * `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload. + It ensures that the intended referenced document is the one used, and there has been no substitution. + Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one. """ } From e95ad7db7cadb0b03bf24e7d0e03f201d855fc65 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 5 Mar 2025 21:19:41 +0400 Subject: [PATCH 21/35] feat: Fix validation issues --- specs/signed_doc.json | 40 ++++++++++++++++++++++++++++++++ specs/signed_docs/metadata.cue | 30 ++++++++++++------------ specs/signed_docs/signed_doc.cue | 5 ++-- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/specs/signed_doc.json b/specs/signed_doc.json index 612f84949b..ad3e824318 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -40,6 +40,11 @@ "format": "UUIDv7", "required": "yes" }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded" + }, "ver": { "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "format": "UUIDv7", @@ -92,6 +97,11 @@ "format": "UUIDv7", "required": "yes" }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded" + }, "ver": { "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "format": "UUIDv7", @@ -160,6 +170,11 @@ "format": "UUIDv7", "required": "yes" }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded" + }, "template": { "description": "Reference to the template used to create and/or validate this document.", "format": "Document Reference", @@ -321,6 +336,11 @@ "format": "UUIDv7", "required": "yes" }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded" + }, "ver": { "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "format": "UUIDv7", @@ -390,6 +410,11 @@ "format": "UUIDv7", "required": "yes" }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded" + }, "template": { "description": "Reference to the template used to create and/or validate this document.", "format": "Document Reference", @@ -464,6 +489,11 @@ "format": "UUIDv7", "required": "yes" }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded" + }, "ver": { "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "format": "UUIDv7", @@ -524,6 +554,11 @@ "format": "UUIDv7", "required": "yes" }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded" + }, "ver": { "description": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", "format": "UUIDv7", @@ -697,6 +732,11 @@ "format": "UUIDv7", "required": "yes" }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded" + }, "template": { "description": "Reference to the template used to create and/or validate this document.", "format": "Document Reference", diff --git a/specs/signed_docs/metadata.cue b/specs/signed_docs/metadata.cue index ed5c4991d4..3211cdca2c 100644 --- a/specs/signed_docs/metadata.cue +++ b/specs/signed_docs/metadata.cue @@ -43,15 +43,15 @@ _allMetadataNames: or([ // Format of the field. format: #metadataFormat - if format == "Document Reference" { + if format == "Document Reference" && required != "excluded" { type: #DocumentName - multiple?: bool | *false + multiple?: bool } // Markdown description of the field. - description: string + description: string | *"" // Optional notes about validating the field. - validation?: string + validation?: string | *"" } // Metadata fields that are optional @@ -60,12 +60,12 @@ _allMetadataNames: or([ } _metadata: #metadataStruct & { // Document ID - id: #metadataField & { + id: { required: "yes" description: "Document ID, created the first time the document is created." } // Document Version - ver: #metadataField & { + ver: { required: "yes" description: """ ## Document Version @@ -79,7 +79,7 @@ _metadata: #metadataStruct & { """ } - ref?: #metadataField & { + ref: { format: "Document Reference" description: """ Reference to a Linked Document or Documents. @@ -96,13 +96,13 @@ _metadata: #metadataStruct & { """ } - template?: #metadataField & { + template?: { format: "Document Reference" description: "Reference to the template used to create and/or validate this document." validation: "The document payload is not valid if it does not validate completely against the referenced template." } - reply?: #metadataField & { + reply?: { format: "Document Reference" required: "optional" description: """ @@ -114,7 +114,7 @@ _metadata: #metadataStruct & { """ } - section?: #metadataField & { + section?: { format: "Section Reference" required: "optional" description: """ @@ -126,7 +126,7 @@ _metadata: #metadataStruct & { """ } - collaborators?: #metadataField & { + collaborators?: { format: "Collaborators Reference List" required: "optional" description: """ @@ -145,7 +145,7 @@ _metadata: #metadataStruct & { """ } - brand_id?: #metadataField & { + brand_id?: { format: "Document Reference" description: "A reference to the Brand Parameters Document this document lies under." validation: """ @@ -156,7 +156,7 @@ _metadata: #metadataStruct & { """ } - campaign_id?: #metadataField & { + campaign_id?: { format: "Document Reference" description: "A reference to the Campaign Parameters Document this document lies under." validation: """ @@ -167,7 +167,7 @@ _metadata: #metadataStruct & { """ } - election_id?: #metadataField & { + election_id?: { format: "Document Reference" description: "A reference to the Election Parameters Document this document lies under." validation: """ @@ -178,7 +178,7 @@ _metadata: #metadataStruct & { """ } - category_id?: #metadataField & { + category_id?: { format: "Document Reference" description: "A reference to the Category Parameters Document this document lies under." validation: """ diff --git a/specs/signed_docs/signed_doc.cue b/specs/signed_docs/signed_doc.cue index c4b94cf777..d2af79861c 100644 --- a/specs/signed_docs/signed_doc.cue +++ b/specs/signed_docs/signed_doc.cue @@ -58,8 +58,9 @@ base_types: _allDocTypes // Ensure that all Document Type IDs are Unique. // See: all_docs.cue for a list of all known document types. -_allDocTypeIDs: list.UniqueItems -_allDocTypeIDs: [...uuid.#uuidv4] & [ +#allDocTypeIDs: list.UniqueItems + +#allDocTypeIDs: [...uuid.#v4] & [ for _, v in _allDocTypes {v}, ] From e2363f03a05de3e423e3a787f5d9720e897ec7eb Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Fri, 7 Mar 2025 13:43:46 +0400 Subject: [PATCH 22/35] feat: Signed Doc defintion improvements WIP --- docs/macros/__init__.py | 37 +- docs/macros/signed_docs.py | 201 ++- .../catalyst_docs/brand_parameters.md | 1 + .../catalyst_docs/campaign_parameters.md | 1 + .../catalyst_docs/election_parameters.md | 1 + .../08_concepts/signed_doc/meta copy.md | 126 ++ .../08_concepts/signed_doc/spec.md | 204 +-- specs/signed_doc.json | 1198 +++++++++++++++-- specs/signed_docs/cose_headers.cue | 124 +- specs/signed_docs/docs/all.cue | 12 + specs/signed_docs/documentation_links.cue | 50 + specs/signed_docs/metadata.cue | 109 +- 12 files changed, 1729 insertions(+), 335 deletions(-) create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/brand_parameters.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/campaign_parameters.md create mode 100644 docs/src/architecture/08_concepts/catalyst_docs/election_parameters.md create mode 100644 docs/src/architecture/08_concepts/signed_doc/meta copy.md create mode 100644 specs/signed_docs/documentation_links.cue diff --git a/docs/macros/__init__.py b/docs/macros/__init__.py index 23f8a19410..635fd5e3d0 100644 --- a/docs/macros/__init__.py +++ b/docs/macros/__init__.py @@ -1,5 +1,11 @@ from .include import inc_file -from .signed_docs import doc_type_details, doc_type_summary, signed_doc_details +from .signed_docs import ( + cose_header_parameters, + doc_type_details, + doc_type_summary, + external_links, + signed_doc_details, +) def define_env(env): @@ -14,12 +20,35 @@ def include_file(filename, start_line=0, end_line=None, indent=None): @env.macro def insert_doc_type_summary(): - return doc_type_summary(env) + try: + return doc_type_summary(env) + except Exception as exc: + return f"Macro Expansion Error: {exc}" @env.macro def insert_doc_type_details(): - return doc_type_details(env) + try: + return doc_type_details(env) + except Exception as exc: + return f"Macro Expansion Error: {exc}" + + @env.macro + def insert_cose_header_parameters(): + try: + return cose_header_parameters(env) + except Exception as exc: + return f"Macro Expansion Error: {exc}" @env.macro def insert_signed_doc_details(name): - return signed_doc_details(env, name) + try: + return signed_doc_details(env, name) + except Exception as exc: + return f"Macro Expansion Error: {exc}" + + @env.macro + def insert_external_links(): + try: + return external_links(env) + except Exception as exc: + return f"Macro Expansion Error: {exc}" diff --git a/docs/macros/signed_docs.py b/docs/macros/signed_docs.py index 2b84190f7f..05d4df5eac 100644 --- a/docs/macros/signed_docs.py +++ b/docs/macros/signed_docs.py @@ -4,8 +4,10 @@ # import re # import textwrap -# SIGNED_DOCS_SPECS="signed_doc.json" -SIGNED_DOCS_SPECS = "includes/signed_doc.json" +if __name__ == "__main__": + SIGNED_DOCS_SPECS = "signed_doc.json" +else: + SIGNED_DOCS_SPECS = "includes/signed_doc.json" def uuid_as_cbor(uuid): @@ -27,23 +29,20 @@ def doc_type_summary(env): Generate a Document Base Type Summary from the Document Specifications Data """ - try: - doc_data = get_signed_doc_data(env) - doc_types = doc_data["base_types"] + doc_data = get_signed_doc_data(env) + doc_types = doc_data["base_types"] - doc_type_summary = """ + doc_type_summary = """ | Base Type | [UUID] | [CBOR] | | :--- | :--- | :--- | """ - for k in doc_types: - doc_type_summary += ( - f"| {k} | `{doc_types[k]}` | `{uuid_as_cbor(doc_types[k])}` |\n" - ) + for k in doc_types: + doc_type_summary += ( + f"| {k} | `{doc_types[k]}` | `{uuid_as_cbor(doc_types[k])}` |\n" + ) - return doc_type_summary - except Exception as exc: - return f"{exc}" + return doc_type_summary def name_for_uuid(doc_types, uuid): @@ -87,24 +86,151 @@ def doc_type_details(env): Generate a Document Type Detailed Summary from the Document Specifications Data """ - try: - doc_data = get_signed_doc_data(env) - doc_types = doc_data["base_types"] - docs = doc_data["docs"] + doc_data = get_signed_doc_data(env) + doc_types = doc_data["base_types"] + docs = doc_data["docs"] - doc_type_details = """ + doc_type_details = """ | Document Type | Base Types | [CBOR] | Specification | | :--- | :--- | :--- | :--- | """ - for k in docs: - doc_type_details += f"| {k} | {base_types(docs, doc_types, k)} | {types_as_cbor(docs, k)} | [Specification]({name_to_spec_link(k)}) | \n" + for k in docs: + doc_type_details += f"| {k} | {base_types(docs, doc_types, k)} | {types_as_cbor(docs, k)} | [Specification]({name_to_spec_link(k)}) | \n" + + return doc_type_details + + +def header_parameter_doc(header, doc_data): + """ + Create documentation for a single cose header. + """ + options = doc_data["cose_headers"][header] + content_types = doc_data["contentTypes"] + encoding_types = doc_data["encodingTypes"] + label = options.get("coseLabel") + custom_header = "***Custom Header***" + if not isinstance(label, str): + custom_header = "" + header_format = options["format"] + header_value = 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:" + for value in header_value: + value_entry = f"\n * {value}" + value_data = None + if header_format == "IANA Media Type" and value in content_types: + value_data = content_types[value] + if header_format == "HTTP Content Encoding" and value in encoding_types: + value_data = encoding_types[value] + + if value_data is not None: + if value_data["linked"]: + value_entry = f"\n * [{value}]" + value_entry += ( + f" : {value_data['description'].replace('\n', '\n ')}" + ) + + header_format_display += value_entry + + return f""" +#### {header} + +{options.get("description")} + +* Required : {options["required"]} +* Cose Label : {label} {custom_header} +* Format : {header_format_display} - return doc_type_details - except Exception as exc: - return f"{exc}" +""" +def cose_header_parameters(env): + """ + Insert details about Cose header Parameters that are defined for use. + """ + doc_data = get_signed_doc_data(env) + headers = doc_data["cose_headers"] + header_order = doc_data["cose_headers_order"] + # Make sure unordered headers get included in the documentation. + for header in headers: + if header not in header_order: + header_order += header + + header_parameters_doc = "" + for header in header_order: + header_parameters_doc += header_parameter_doc(header, doc_data) + headers.pop(header) + + return header_parameters_doc + + +def external_links(env): + """ + Insert External Links we might have used in descriptions. + """ + doc_data = get_signed_doc_data(env) + links = doc_data["documentationLinks"] + + link_display = "" + for name in links: + link_display += f"[{name}]: {links[name]}\n" + + return link_display + + +def metadata_fields(env, doc_name=None): + """ + Display Metadata fields for the default set, or a specific document. + """ + doc_data = get_signed_doc_data(env) + if doc_name is not None: + fields = doc_data["docs"][doc_name]["metadata"] + field_title_level = "###" + else: + fields = doc_data["metadata"] + field_title_level = "##" + + order = doc_data["metadata_order"] + + # make sure every field is listed in the ordering + for field_name in fields: + if not field_name in order: + order += field_name + + field_display = "" + for field_name in order: + field = fields[field_name] + field_display += f""" +{field_title_level} `{field_name}` + +| Parameter | Value | +| --- | --- | +| Required | {field["required"]} | +""" + if field["required"] != "excluded": + field_display += f"| Format | {field["format"]} |\n" + if "multiple" in field: + field_display += f"| Multiple References | {field["multiple"]} |\n" + if "type" in field: + ref_heading = "Valid References" + ref_doc_names = field["type"] + if isinstance(ref_doc_names,str): + ref_doc_names = [ref_doc_names] + for ref_doc in ref_doc_names: + field_display += f"| {ref_heading} | {ref_doc} |\n" + ref_heading = "" + + field_display += f""" +{field["description"]} + +{field_title_level}# Validation + +{field["validation"]} +""" + return field_display + def signed_doc_details(env, name): """ Generate Signed Document Detailed Documentation Page. @@ -112,10 +238,29 @@ def signed_doc_details(env, name): return name + "\n" + "test\n" -# class env: -# project_dir = "/home/steven/Development/iohk/catalyst-libs/specs" +# run as a program to debug the macros +if __name__ == "__main__": + + class env: + project_dir = "/home/steven/Development/iohk/catalyst-libs/specs" + + print() + print("### DOC TYPE DETAILS ###") + print(doc_type_details(env)) + + print() + print("### DOC TYPE SUMMARY ###") + print(doc_type_summary(env)) + + print() + print("### COSE HEADER PARAMETERS ###") + print(cose_header_parameters(env)) + + print() + print("### EXTERNAL LINKS ###") + print(external_links(env)) -# if __name__ == '__main__': + print() + print("### GLOBAL METADATA ###") + print(metadata_fields(env)) -# print(doc_type_details(env)) -# print(doc_type_summary(env)) diff --git a/docs/src/architecture/08_concepts/catalyst_docs/brand_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/brand_parameters.md new file mode 100644 index 0000000000..374ff296fb --- /dev/null +++ b/docs/src/architecture/08_concepts/catalyst_docs/brand_parameters.md @@ -0,0 +1 @@ +# {{ insert_signed_doc_details( "Brand Parameters" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/campaign_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/campaign_parameters.md new file mode 100644 index 0000000000..d26f8b3a1b --- /dev/null +++ b/docs/src/architecture/08_concepts/catalyst_docs/campaign_parameters.md @@ -0,0 +1 @@ +# {{ insert_signed_doc_details( "Campaign Parameters" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/election_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/election_parameters.md new file mode 100644 index 0000000000..5749f999c4 --- /dev/null +++ b/docs/src/architecture/08_concepts/catalyst_docs/election_parameters.md @@ -0,0 +1 @@ +# {{ insert_signed_doc_details( "Election Parameters" ) }} diff --git a/docs/src/architecture/08_concepts/signed_doc/meta copy.md b/docs/src/architecture/08_concepts/signed_doc/meta copy.md new file mode 100644 index 0000000000..c40491897d --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/meta copy.md @@ -0,0 +1,126 @@ +# Metadata Fields List + + +??? note "Additional Metadata fields: `additional_meta.cddl`" + + ```CDDL + {{ include_file('src/architecture/08_concepts/signed_doc/cddl/additional_meta.cddl', indent=4) }} + ``` + + +* [Metadata Fields List](#metadata-fields-list) + * [`ref` Document Reference](#ref-document-reference) + * [Validation](#validation) + * [`ref_hash` Secured Document Reference](#ref_hash-secured-document-reference) + * [`template` Template Reference](#template-template-reference) + * [`reply` Reply Reference](#reply-reply-reference) + * [`section` Section Reference](#section-section-reference) + * [`collabs` Authorized Collaborators](#collabs-authorized-collaborators) + * [`brand_id`](#brand_id) + * [`campaign_id`](#campaign_id) + * [`election_id`](#election_id) + * [`category_id`](#category_id) + +## `ref` Document Reference + +This is a reference to another document. +The purpose of the `ref` will vary depending on the document [`type`](./spec.md#type). + +The `ref` can be either a single [UUID] or a [CBOR] Array of Two [UUID]. + +If the `ref` is a single [UUID] v7, it is a reference to the document of that [`id`](./spec.md#id). +If the `ref` is a [CBOR] array, it has the form `[,]` where: + +* `` - the [UUID] v7 of the referenced documents [`id`](./spec.md#id). +* `` - the [UUID] v7 of the referenced documents [`ver`](./spec.md#ver). + +### Validation + +For any document type, `ref` can refer to only 1 other document type which must be different than +the type of document `ref` appears in. +For example `ref` for a Proposal Comment Document, is always a Proposal type document. + +## `ref_hash` Secured Document Reference + +This is a cryptographically secured reference to another document. + +It consists of two fields: + +* [`ref`](#ref-document-reference) - simple reference to the document. +* `hash` - hash of the referenced document [CBOR] bytes. + +## `template` Template Reference + +If the document was formed from a template, this is a reference to that template document. +The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). + +It is invalid not to reference the template that formed a document. +If this is missing from such documents, the document will itself be considered invalid. + +Template references must explicitly reference both the Template Document ID, and Version. + +## `reply` Reply Reference + +This is a reply to another document. +The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). + +`reply` is always referencing a document of the same type, and that document must `ref` reference the same document `id`. +However, depending on the document type, it may reference a different `ver` of that `id`. + +## `section` Section Reference + +This is a reference to a section of a document. +It is a CBOR String, and contains a [JSON Path] identifying the section in question. + +Because this metadata field uses [JSON Path], it can only be used to reference a document whose payload is [JSON]. + +## `collabs` Authorized Collaborators + +This is a list of entities other than the original author that may also publish versions of this document. +This may be updated by the original author, or any collaborator that is given "author" privileges. + +The latest `collabs` list in the latest version, published by an authorized author is the definitive +list of allowed collaborators after that point. + +The `collabs` list is a [CBOR] Array. +The contents of the array are TBD. + +However, they will contain enough information such that each collaborator can be uniquely identified and validated. + +*Note: An Author can unilaterally set the `collabs` list to any list of collaborators. +It does NOT mean that the listed collaborators have agreed to collaborate, only that the Author +gives them permission to.* + +This list can impact actions that can be performed by the `Proposal Action Document`. + +## `brand_id` + +This is a reply to another document. +The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). + +`brand_id` represents a "brand" who is running the voting, e.g. Catalyst, Midnight. + +## `campaign_id` + +This is a reply to another document. +The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). + +`campaign_id` defines a "campaign" of voting, e.g. "treasury campaign". + +## `election_id` + +Unique identifier [UUID] v4, which defines an election, +e.g. "Catalyst Fund 1", "Catalyst Fund 2". + +## `category_id` + +This is a reply to another document. +The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). + +`campaign_id` defines a voting category as a collection of proposals, +e.g. "Development & Infrastructure", "Products & Integrations". + +[UUID]: https://www.rfc-editor.org/rfc/rfc9562.html +[CBOR]: https://datatracker.ietf.org/doc/rfc8949/ +[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 +[JSON Path]: https://datatracker.ietf.org/doc/html/rfc9535 diff --git a/docs/src/architecture/08_concepts/signed_doc/spec.md b/docs/src/architecture/08_concepts/signed_doc/spec.md index 8537962b0e..f47dbb9213 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec.md +++ b/docs/src/architecture/08_concepts/signed_doc/spec.md @@ -1,176 +1,78 @@ ---- -Title: Catalyst Signed Document -Category: Catalyst -Status: Proposed -Authors: - - Steven Johnson - - Alex Pozhylenkov -Implementors: - - Catalyst Fund 14 -Discussions: [] -Created: 2024-12-27 -License: CC-BY-4.0 ---- - -* [Abstract](#abstract) -* [Motivation: why is this CIP necessary?](#motivation-why-is-this-cip-necessary) -* [Specification](#specification) - * [Catalyst Signed Document metadata fields](#catalyst-signed-document-metadata-fields) - * [`type`](#type) - * [`id`](#id) - * [`ver`](#ver) - * [`alg`](#alg) - * [`content type`](#content-type) - * [`content encoding` (optional)](#content-encoding-optional) - * [Catalyst Signed Document content](#catalyst-signed-document-content) - * [COSE signature protected header](#cose-signature-protected-header) -* [Copyright](#copyright) +# Specification -## Abstract - -Project Catalyst both produces and consumes a lot of different data objects, -in different places of the system. -To ensure the data object is authoritative, it must be signed. -In addition to the data object content and the signature, metadata is also included -to describe different kind of Catalyst Signed Document properties. - -## Motivation: why is this CIP necessary? - -As we decentralize project catalyst, it will be required to unambiguously identify who produced some -data object, and the purpose of it. - -## Specification - -Catalyst Signed Document is [COSE] based structure, particularly `COSE Signed Data Object` [COSE] type. -It fully inherits an original [COSE] design and specifies the details of different [COSE] header's fields. - -### Catalyst Signed Document metadata fields - -To uniquely specify a Catalyst Signed Document `id`, `type`, `version` etc., -a list of different metadata fields is specified. - -Also as you can see from the specification, -it is allowed to add any number of additional metadata fields, which could be specified for each `type` of document. - -[A full list of considered additional metadata fields](./meta.md). - -All these fields will be encoded as the [COSE] `protected` header - - -??? note "Catalyst Signed Document metadata fields: `signed_doc_meta.cddl`" - - ```CDDL - {{ include_file('src/architecture/08_concepts/signed_doc/cddl/signed_doc_meta.cddl', indent=4) }} - ``` - - -#### `type` - -Each Catalyst Signed Document will have a type identifier called `type`. + + -The `type` is a [UUID] v4. - -[A full list of Catalyst supported document types](./types.md) - -#### `id` - -Every Catalyst Signed Document will have a unique ID. -All Catalyst Signed Document with the same `id` are considered different versions of the same Catalyst Signed Document -(read about [`ver`](#ver)). -However, `id` uniqueness is only guaranteed on first use. - -If the same `id` is used, by unauthorized publishers, the Catalyst Signed Document is invalid. - -The `id` is a [UUID] v7. - -The first time a Catalyst Signed Document is created, it will be assigned by the creator a new `id` which must -be well constructed. - -* The time must be the time the Catalyst Signed Document was first created. -* The random value must be truly random. - -Creating `id` this way ensures there are no collisions, and they can be independently created without central co-ordination. - -*Note: All Catalyst Signed Documents are signed, -the first creation of an `id` assigns that `id` to the creator and any assigned collaborators. -A Catalyst Signed Document that is not signed by the creator, or an assigned collaborator, is invalid. -There is no reasonable way an `id` can collide accidentally. -Therefore, detection of invalid `id`s published by unauthorized publishers, could result in anti-spam -or system integrity mitigations being triggered. -This could result in all actions in the system being blocked by the offending publisher, -including all otherwise legitimate publications by the same author being marked as fraudulent.* - -#### `ver` - -Every Catalyst Signed Document in the system will be versioned. -There can, and probably will, exist multiple versions of the same document. +## Abstract -The `ver` is a [UUID] v7. +Project Catalyst requires a verifiable data format for the publication and validation of +large volumes of off chain information. -The initial `ver` assigned the first time a Catalyst Signed Document is published **MUST** be identical to the [`id`](#id). -Subsequent versions will retain the same [`id`](#id) and will create a new `ver`, -following best practice for creating a new [UUID] v7. +The Catalyst Signed Documents Specification is based on [COSE][RFC9052] +and provides the basis of this document specification. -#### `alg` +## Motivation -This is an original [COSE] header field, -which indicates the cryptography algorithm used for the security processing. +As Project Catalyst decentralizes via both on-chain and off-chain mechanisms, a reliable, +standardized process for authenticating documents and their relationships is required. - -!!! warning "" +## Specification - It must be equal to `EdDSA` value - +Project Catalyst generates a large volume of off chain information. +This information requires similar guarantees as on-chain data. +It needs to be verifiably published and also immutable. +However, we also require the ability to publish new versions of documents, +and for documents to be able to securely reference one another. -Only `ed25119` considered at this moment as the only option to be supported for signed objects. +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. -#### [`content type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) +### Cose Header Parameters -This is an original [COSE] header field, -which indicates the [`content type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) -of the [content](#catalyst-signed-document-content) ([COSE] `payload`) data. +Cose documents define a set of standard [header parameters][RFC9052-HeaderParameters]. +All Headers Parameters are protected and *MUST* appear in the protected headers section of the document. +The header parameters defined and used by Catalyst Signed Documents are as follows: -#### [`content encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) (optional) +{{ insert_cose_header_parameters() }} -This field is used to indicate the [`content encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) -algorithm of the [content](#catalyst-signed-document-content) data. +### Metadata -Supported encodings: +Catalyst Signed Documents extend the Header Parameters with a series of Metadata fields. +These fields are defined [here](./meta.md). -* `br` - [Brotli] compressed data. +### Signing Catalyst Signed Documents -### Catalyst Signed Document content +Catalyst Signed Documents are based on the [COSE Sign][RFC9052-CoseSign] format. +This allows one or more signatures to be attached to the same document. +A catalyst signed document *MUST* have at least one valid signature attached. +Multiple signatures may also be attached to the same document, where that is required. -The Catalyst Signed Document content data is encoded (and could be additionally compressed, -read [`content encoding`](#content-encoding-optional)) as [COSE] `payload`. +Each signature is contained in an array of signatures attached to the document. +The signatures contain protected headers, and the signature itself. +The headers currently defined for the signatures are: -### [COSE] signature protected header +#### `kid` -As it mentioned earlier, Catalyst Signed Document utilizes `COSE Signed Data Object` format, -which allows to provide multi-signature functionality. -In that regard, -each Catalyst Signed Document [COSE] signature **must** include the following `protected` header field: +The kid is a [UTF-8][RFC3629] encoded [Catalyst ID]. +Any `kid` format which conforms to the [Catalyst ID] specification may be used. +The [Catalyst ID] unambiguously defines both the signing keys and signing algorithm used to sign the protected portion of the document. - -```CDDL -; All encoders/decoders of this specification must follow deterministic cbor encoding rules -; https://datatracker.ietf.org/doc/html/draft-ietf-cbor-cde-06 +* Required: yes +* Cose Label: 4 +* Format: [UTF-8][RFC3629] encoded [Catalyst ID] -signature_protected_header = { - 4 => bytes ; "kid", UTF-8 encoded URI string -} -``` - +## Copyright -* `kid`: A unique identifier of the signer. - A [UTF-8] encoded [URI] string. -## Copyright +| Copyright | :copyright: 2024, IOG Singapore, All Rights Reserved | +| --- | --- | +| License | This document is licensed under [CC-BY-4.0]. | +| Created | 2024-12-27 | +| Authors | Steven Johnson | +| | Alex Pozhylenkov | -This document is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode). +{{ insert_external_links() }} -[Brotli]: https://datatracker.ietf.org/doc/html/rfc7932 -[UTF-8]: https://datatracker.ietf.org/doc/html/rfc3629 -[URI]: https://datatracker.ietf.org/doc/html/rfc3986 -[COSE]: https://datatracker.ietf.org/doc/html/rfc9052 -[UUID]: https://www.rfc-editor.org/rfc/rfc9562.html + +[Catalyst ID]: ../rbac_id_uri/catalyst-id-uri.md \ No newline at end of file diff --git a/specs/signed_doc.json b/specs/signed_doc.json index ad3e824318..b5d7c01899 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -1,22 +1,278 @@ { "base_types": { "Action": "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "Brand": "ebcabeeb-5bc5-4f95-91e8-cab8ca724172", + "Campaign": "5ef32d5d-f240-462c-a7a4-ba4af221fa23", "Category": "818938c3-3139-4daa-afe6-974c78488e95", "Comment": "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "Election": "788ff4c6-d65a-451f-bb33-575fe056b411", "ModerationAction": "a5d232b8-5e03-4117-9afd-be32b878fcdd", "Proposal": "7808d2ba-d511-40af-84e8-c0d1625fdfdc", "SubmissionAction": "78927329-cfd9-4ea1-9c71-0e019b126a65", "Template": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" }, + "contentTypes": { + "application/cbor": { + "description": "[RFC8949] Binary CBOR Encoded Document", + "linked": true + }, + "application/cddl": { + "description": "[RFC8610] CBOR Document. Note: \n\t* This is an unofficial media type\n\t* [RFC9165] Additional Control Operators for CDDL are supported. \n\t* Must not have Modules, schema must be self contained.", + "linked": false + }, + "application/json": { + "description": "[RFC8259] JSON Document", + "linked": true + }, + "application/schema+json": { + "description": "[JSON Schema] Draft 7 Document. Note: \n\t* This is currently an unofficial media type.\n\t* Draft 7 is used because of its wide support by tooling.", + "linked": true + } + }, + "cose_headers": { + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA 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" + ] + } + }, + "cose_headers_order": [ + "content type", + "content-encoding" + ], "docs": { - "Category Parameters": { + "Brand Parameters": { + "headers": { + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA 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": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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 `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] + }, + "update": { + "author": true + } + }, + "type": [ + "ebcabeeb-5bc5-4f95-91e8-cab8ca724172" + ] + }, + "Campaign Parameters": { "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA 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": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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 `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] }, + "update": { + "author": true + } + }, + "type": [ + "5ef32d5d-f240-462c-a7a4-ba4af221fa23" + ] + }, + "Category Parameters": { + "headers": { "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -26,7 +282,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -35,15 +291,71 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", - "required": "excluded" + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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 `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -66,14 +378,117 @@ "818938c3-3139-4daa-afe6-974c78488e95" ] }, - "Comment Action Document": { + "Comment Action Document": { + "headers": { + "content type": { + "coseLabel": 3, + "description": "IANA Media Type/s allowed in the Payload", + "format": "IANA 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": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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 `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "signers": { + "roles": { + "user": [ + "Registered" + ] + }, + "update": { + "author": true + } + }, + "type": [ + "5e60e623-ad02-4a1b-a1ac-406db978ee48", + "b679ded3-0e7c-41ba-89f8-da62a17898ea", + "a5d232b8-5e03-4117-9afd-be32b878fcdd" + ] + }, + "Election Parameters": { "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" - }, "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -83,7 +498,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -92,15 +507,71 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", - "required": "excluded" + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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 `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -120,20 +591,12 @@ } }, "type": [ - "5e60e623-ad02-4a1b-a1ac-406db978ee48", - "b679ded3-0e7c-41ba-89f8-da62a17898ea", - "a5d232b8-5e03-4117-9afd-be32b878fcdd" + "788ff4c6-d65a-451f-bb33-575fe056b411" ] }, "Proposal": { "description": "## Proposal Document\n\nA Proposal is a document which describes a proposed solution or project to\naddress the criteria of a category within a campaign.\n\nThe proposal itself is a draft document, it is not submitted for consideration\nunless a `Proposal Submission Action` is submitted which references it.\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.", "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" - }, "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -143,7 +606,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -152,12 +615,25 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", "format": "Document Reference", + "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", @@ -165,22 +641,49 @@ "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." }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", - "required": "excluded" + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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", + "multiple": false, "required": "yes", "type": "Proposal Template", - "validation": "The document payload is not valid if it does not validate completely against the referenced template." + "validation": "In addition to the validation performed for `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -210,12 +713,6 @@ "Proposal Comment": { "description": "## Proposal Comment Document\n\nA Proposal Comment is a document which comments on a referenced Proposal document.\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.", "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" - }, "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -225,7 +722,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -234,30 +731,59 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", "format": "Document Reference", + "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", + "multiple": false, "required": "yes", - "type": "Proposal" + "type": "Proposal", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "reply": { "description": "Reference to a Comment document type being referred to.", "format": "Document Reference", + "multiple": false, "required": "optional", "type": "Proposal Comment", - "validation": "The `ref` of the `reply` document must be the same as\nthe original comment document." + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "section": { "description": "A Reference to the original document, or the comment being replied to.", @@ -268,9 +794,16 @@ "template": { "description": "Reference to the template used to create and/or validate this document.", "format": "Document Reference", + "multiple": false, "required": "yes", "type": "Proposal Comment Template", - "validation": "The document payload is not valid if it does not validate completely against the referenced template." + "validation": "In addition to the validation performed for `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -300,12 +833,6 @@ "Proposal Comment Meta Template": { "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.", "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" - }, "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -315,7 +842,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -324,22 +851,73 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", "format": "Document Reference", + "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", - "required": "excluded" + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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 `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -374,12 +952,6 @@ "Proposal Comment Template": { "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.", "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" - }, "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -389,7 +961,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -398,29 +970,75 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", "format": "Document Reference", + "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", - "required": "excluded" + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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", + "multiple": false, "required": "optional", "type": "Proposal Comment Meta Template", - "validation": "The document payload is not valid if it does not validate completely against the referenced template." + "validation": "In addition to the validation performed for `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -453,12 +1071,6 @@ "Proposal Meta Template": { "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.", "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" - }, "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -468,7 +1080,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -477,22 +1089,73 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", "format": "Document Reference", + "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", - "required": "excluded" + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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 `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -525,12 +1188,6 @@ }, "Proposal Moderation Action": { "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" - }, "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -540,7 +1197,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -549,15 +1206,71 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", - "required": "excluded" + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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 `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -585,12 +1298,6 @@ "Proposal Submission Action": { "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. Unless they all submit or withdraw the same version of the proposal\nthe proposal will not be seen as submitted or withdrawn.\n\nThe payload is a fixed format.", "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" - }, "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -600,7 +1307,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -609,24 +1316,75 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", "format": "Document Reference", + "multiple": false, "required": "yes", "type": "Category Parameters", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", "multiple": true, "required": "yes", - "type": "Proposal" + "type": "Proposal", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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 `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -696,12 +1454,6 @@ "Proposal Template": { "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.", "headers": { - "alg": { - "coseLabel": 1, - "description": "Default cryptographic signature algorithm", - "format": "COSE Algorithm", - "required": "optional" - }, "content type": { "coseLabel": 3, "description": "IANA Media Type/s allowed in the Payload", @@ -711,7 +1463,7 @@ }, "content-encoding": { "coseLabel": "content-encoding", - "description": "Supported HTTP Encodings of the Payload", + "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": [ @@ -720,29 +1472,75 @@ } }, "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", "format": "Document Reference", + "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "Any referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { "description": "Document ID, created the first time the document is created.", "format": "UUIDv7", - "required": "yes" + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." }, "ref": { "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", "format": "Document Reference", - "required": "excluded" + "required": "excluded", + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "required": "excluded", + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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", + "multiple": false, "required": "optional", "type": "Proposal Meta Template", - "validation": "The document payload is not valid if it does not validate completely against the referenced template." + "validation": "In addition to the validation performed for `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", @@ -771,5 +1569,191 @@ "7808d2ba-d511-40af-84e8-c0d1625fdfdc" ] } - } + }, + "documentationLinks": { + "CC-BY-4.0": "https://creativecommons.org/licenses/by/4.0/legalcode", + "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" + }, + "encodingTypes": { + "br": { + "description": "[BROTLI](RFC7932) Compression", + "linked": true + } + }, + "linkAKA": { + "BROTLI": "RFC7932", + "CBOR": "RFC8949", + "CDDL": "RFC8610", + "COSE": "RFC9052", + "COSE Header Parameters": "RFC9052-HeaderParameters", + "COSE Sign": "RFC9052-CoseSign", + "JSON": "RFC8259", + "RFC9165 - CDDL Additional Controls": "RFC9165", + "URI": "RFC3986", + "UTF-8": "RFC3629", + "UUID": "RFC9562", + "UUIDv4": "RFC9562-V7", + "UUIDv7": "RFC9562-V7" + }, + "metadata": { + "brand_id": { + "description": "A reference to the Brand Parameters Document this document lies under.", + "format": "Document Reference", + "multiple": false, + "required": "optional", + "type": "Brand Parameters", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "campaign_id": { + "description": "A reference to the Campaign Parameters Document this document lies under.", + "format": "Document Reference", + "multiple": false, + "required": "optional", + "type": "Campaign Parameters", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "category_id": { + "description": "A reference to the Category Parameters Document this document lies under.", + "format": "Document Reference", + "multiple": false, + "required": "optional", + "type": "Category Parameters", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 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." + }, + "election_id": { + "description": "A reference to the Election Parameters Document this document lies under.", + "format": "Document Reference", + "multiple": false, + "required": "optional", + "type": "Election Parameters", + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + }, + "id": { + "description": "Document ID, created the first time the document is created.", + "format": "UUIDv7", + "required": "yes", + "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + }, + "ref": { + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "format": "Document Reference", + "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 Action Document", + "Brand Parameters", + "Campaign Parameters", + "Category Parameters", + "Election Parameters" + ], + "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " + }, + "reply": { + "description": "Reference to a Comment document type being referred to.", + "format": "Document Reference", + "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 Action Document", + "Brand Parameters", + "Campaign Parameters", + "Category Parameters", + "Election Parameters" + ], + "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." + }, + "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", + "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 Action Document", + "Brand Parameters", + "Campaign Parameters", + "Category Parameters", + "Election Parameters" + ], + "validation": "In addition to the validation performed for `ref`, \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": "## Document Version\n\nThe unique version of the document.\nThe first version of the document must set `ver` == `id`", + "format": "UUIDv7", + "required": "yes", + "validation": "The document version must always be >= the document ID." + } + }, + "metadata_order": [ + "type", + "id", + "ver", + "ref", + "template", + "reply", + "section", + "collaborators", + "brand_id", + "campaign_id", + "category_id", + "election_id" + ] } diff --git a/specs/signed_docs/cose_headers.cue b/specs/signed_docs/cose_headers.cue index d51dfdc623..b6bae15879 100644 --- a/specs/signed_docs/cose_headers.cue +++ b/specs/signed_docs/cose_headers.cue @@ -9,12 +9,92 @@ import ( ) +// Content Type name : Description +_contentTypes: { + [string]: { + linked: bool | *true // content type has a link + description: string // description of the content type + } +} +_contentTypes: { + "application/json": { + description: "[RFC8259] JSON Document" + } + "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" + } + "application/cddl": { + linked: false + description: """ + [RFC8610] CBOR 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]: { + linked: bool | *true // content type has a link + description: string // description of the content type + } +} +_encodingTypes: { + "br": { + description: "[BROTLI](RFC7932) 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}, +] + +#contentTypesConstraint: or(#allContentTypes) + // Supported Content Types (list of values) -#contentType: - *"application/json" | - "application/schema+json" | - "application/cbor" | - "application/cddl" +//#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. @@ -51,7 +131,7 @@ _allCoseHeaderNames: or([ required: optional.#field | *"yes" format: #coseHeaderFormat if format == "IANA Media Type" { - "value": #contentType + "value": #contentType | [...#contentType] } if format == "HTTP Content Encoding" { @@ -64,14 +144,6 @@ _allCoseHeaderNames: or([ [_allCoseHeaderNames]: #coseField } _coseHeaders: #coseHeaders & { - // Default Signature Algorithm - alg: #coseField & { - coseLabel: 1 - required: "optional" - format: "COSE Algorithm" - description: "Default cryptographic signature algorithm" - } - // Documents content type "content type": #coseField & { coseLabel: 3 @@ -80,9 +152,25 @@ _coseHeaders: #coseHeaders & { } // Allowed content encodings "content-encoding": #coseField & { - coseLabel: "content-encoding" - format: "HTTP Content Encoding" - required: "optional" - description: "Supported HTTP Encodings of the Payload" + coseLabel: "content-encoding" + format: "HTTP Content Encoding" + required: "optional" + description: """ + Supported HTTP Encodings of the Payload. + If no compression or encoding is used, then this field must not be present. + """ } } + +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: [ + "content type", + "content-encoding", +] diff --git a/specs/signed_docs/docs/all.cue b/specs/signed_docs/docs/all.cue index 4eef9c7e1b..9b68904981 100644 --- a/specs/signed_docs/docs/all.cue +++ b/specs/signed_docs/docs/all.cue @@ -9,7 +9,10 @@ _allDocTypes: { "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" + "Election": "788ff4c6-d65a-451f-bb33-575fe056b411" } // Source of truth for ALL Document Types and their matching UUID's. @@ -59,8 +62,17 @@ _allDocs: { _allDocTypes["Comment"], // For Comment _allDocTypes["ModerationAction"], // On Moderation ] + "Brand Parameters": [ + _allDocTypes["Brand"], + ] + "Campaign Parameters": [ + _allDocTypes["Campaign"], + ] "Category Parameters": [ _allDocTypes["Category"], ] + "Election Parameters": [ + _allDocTypes["Election"], + ] } diff --git a/specs/signed_docs/documentation_links.cue b/specs/signed_docs/documentation_links.cue new file mode 100644 index 0000000000..7568d9e4fb --- /dev/null +++ b/specs/signed_docs/documentation_links.cue @@ -0,0 +1,50 @@ +// 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 +} + +#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-V7" + "UUID": "RFC9562" + "URI": "RFC3986" + "UTF-8": "RFC3629" +} diff --git a/specs/signed_docs/metadata.cue b/specs/signed_docs/metadata.cue index 3211cdca2c..52c63c015b 100644 --- a/specs/signed_docs/metadata.cue +++ b/specs/signed_docs/metadata.cue @@ -11,15 +11,16 @@ import ( // Format of a Metadata Field #metadataFormat: - *"UUIDv7" | - "Document Reference" | - "Document Hash" | + "UUIDv7" | + "Document Type" | + *"Document Reference" | "Section Reference" | "Collaborators Reference List" // Canonical List of all valid metadata names _metadataNames: list.UniqueItems _metadataNames: [ + "type", "id", "ver", "ref", @@ -44,14 +45,14 @@ _allMetadataNames: or([ // Format of the field. format: #metadataFormat if format == "Document Reference" && required != "excluded" { - type: #DocumentName - multiple?: bool + type: #DocumentName | [...#DocumentName] + multiple: bool | *false } // Markdown description of the field. description: string | *"" // Optional notes about validating the field. - validation?: string | *"" + validation: string | *null } // Metadata fields that are optional @@ -59,14 +60,28 @@ _allMetadataNames: or([ [_allMetadataNames]: #metadataField } _metadata: #metadataStruct & { + // Document Type + type: { + required: "yes" + format: "Document Type" + description: "The document TYPE." + validation: """ + **MUST** be a known document type. + """ + } // Document ID id: { required: "yes" + format: "UUIDv7" description: "Document ID, created the first time the document is created." + validation: """ + IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist. + """ } // Document Version ver: { required: "yes" + format: "UUIDv7" description: """ ## Document Version @@ -80,7 +95,6 @@ _metadata: #metadataStruct & { } ref: { - format: "Document Reference" description: """ Reference to a Linked Document or Documents. This is the primary hierarchial reference to a related document. @@ -94,29 +108,33 @@ _metadata: #metadataStruct & { It ensures that the intended referenced document is the one used, and there has been no substitution. Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one. """ + validation: """ + Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document. + The calculated Hash of the Referenced Document **MUST** match the Hash in the reference. + """ } - template?: { - format: "Document Reference" + template: { description: "Reference to the template used to create and/or validate this document." - validation: "The document payload is not valid if it does not validate completely against the referenced template." + validation: """ + In addition to the validation performed for `ref`, + The document payload is not valid if it does not validate completely against the referenced template. + """ } - reply?: { - format: "Document Reference" - required: "optional" + reply: { description: """ Reference to a Comment document type being referred to. """ validation: """ + In addition to the validation performed for `ref`, The `ref` of the `reply` document must be the same as the original comment document. """ } - section?: { - format: "Section Reference" - required: "optional" + section: { + format: "Section Reference" description: """ A Reference to the original document, or the comment being replied to. """ @@ -126,9 +144,8 @@ _metadata: #metadataStruct & { """ } - collaborators?: { - format: "Collaborators Reference List" - required: "optional" + collaborators: { + format: "Collaborators Reference List" description: """ 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. @@ -145,10 +162,10 @@ _metadata: #metadataStruct & { """ } - brand_id?: { - format: "Document Reference" + brand_id: { description: "A reference to the Brand Parameters Document this document lies under." validation: """ + In addition to the validation performed for `ref`, Any referenced document that includes a `brand_id` must match the `brand_id` of the referencing document. It is also valid for the referenced document to not include this field, if it is @@ -156,10 +173,10 @@ _metadata: #metadataStruct & { """ } - campaign_id?: { - format: "Document Reference" + campaign_id: { description: "A reference to the Campaign Parameters Document this document lies under." validation: """ + In addition to the validation performed for `ref`, Any referenced document that includes a `campaign_id` must match the `campaign_id` of the referencing document. It is also valid for the referenced document to not include this field, if it is @@ -167,10 +184,10 @@ _metadata: #metadataStruct & { """ } - election_id?: { - format: "Document Reference" + election_id: { description: "A reference to the Election Parameters Document this document lies under." validation: """ + In addition to the validation performed for `ref`, Any referenced document that includes a `election_id` must match the `election_id` of the referencing document. It is also valid for the referenced document to not include this field, if it is @@ -178,15 +195,53 @@ _metadata: #metadataStruct & { """ } - category_id?: { - format: "Document Reference" + category_id: { description: "A reference to the Category Parameters Document this document lies under." validation: """ + In addition to the validation performed for `ref`, Any referenced document that includes a `category_id` must match the `category_id` of the referencing document. It is also valid for the referenced document to not include this field, if it is optional for the referenced document. """ } +} +// Note: we make all normally excluded fields optional at the global level, because they are globally optional +metadata: _metadata +metadata: { + ref: required: "optional" + ref: type: _allDocNamesList + template: required: "optional" + template: type: _allDocNamesList // TODO: Filter down to only Template Type Docs + reply: required: "optional" + reply: type: _allDocNamesList // TODO: Filter down to only Comment Type Docs + section: required: "optional" + collaborators: required: "optional" + brand_id: required: "optional" + brand_id: type: "Brand Parameters" + campaign_id: required: "optional" + campaign_id: type: "Campaign Parameters" + election_id: required: "optional" + election_id: type: "Election Parameters" + category_id: required: "optional" + category_id: type: "Category Parameters" } + +// 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", + "brand_id", + "campaign_id", + "category_id", + "election_id", +] From 0167244fae9d4e5532d730e90c5b10c76630a48c Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Fri, 7 Mar 2025 18:32:58 +0400 Subject: [PATCH 23/35] feat: Signed docs Docs generation WIP --- .gitignore | 3 +- .../08_concepts/signed_doc/meta.md | 23 +--- specs/Justfile | 2 +- specs/gen_docs/__init__.py | 1 + specs/gen_docs/gen_doc_pages.py | 100 ++++++++++++++++++ specs/gen_docs/gen_spec_md.py | 7 ++ specs/gen_docs/test/spec.md | 1 + specs/utility/gen_doc_pages.py | 48 --------- 8 files changed, 113 insertions(+), 72 deletions(-) create mode 100644 specs/gen_docs/__init__.py create mode 100755 specs/gen_docs/gen_doc_pages.py create mode 100644 specs/gen_docs/gen_spec_md.py create mode 100644 specs/gen_docs/test/spec.md delete mode 100755 specs/utility/gen_doc_pages.py diff --git a/.gitignore b/.gitignore index 438959f5d5..9f75a0f579 100644 --- a/.gitignore +++ b/.gitignore @@ -86,4 +86,5 @@ $RECYCLE.BIN/ /.dart_tool/**/* # Python stuff -.pytest_cache \ No newline at end of file +.pytest_cache +__pycache__ \ No newline at end of file diff --git a/docs/src/architecture/08_concepts/signed_doc/meta.md b/docs/src/architecture/08_concepts/signed_doc/meta.md index c40491897d..2b5148cb00 100644 --- a/docs/src/architecture/08_concepts/signed_doc/meta.md +++ b/docs/src/architecture/08_concepts/signed_doc/meta.md @@ -1,25 +1,4 @@ -# Metadata Fields List - - -??? note "Additional Metadata fields: `additional_meta.cddl`" - - ```CDDL - {{ include_file('src/architecture/08_concepts/signed_doc/cddl/additional_meta.cddl', indent=4) }} - ``` - - -* [Metadata Fields List](#metadata-fields-list) - * [`ref` Document Reference](#ref-document-reference) - * [Validation](#validation) - * [`ref_hash` Secured Document Reference](#ref_hash-secured-document-reference) - * [`template` Template Reference](#template-template-reference) - * [`reply` Reply Reference](#reply-reply-reference) - * [`section` Section Reference](#section-section-reference) - * [`collabs` Authorized Collaborators](#collabs-authorized-collaborators) - * [`brand_id`](#brand_id) - * [`campaign_id`](#campaign_id) - * [`election_id`](#election_id) - * [`category_id`](#category_id) +# Metadata Fields ## `ref` Document Reference diff --git a/specs/Justfile b/specs/Justfile index 2b030cc7ad..3ec0823c4f 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -20,7 +20,7 @@ check: format regenerate: check # 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 utility; ./gen_doc_pages.py + cd gen_docs; ./gen_doc_pages.py # Validate the generated signed_docs.json is correct against the cue schema. validate: diff --git a/specs/gen_docs/__init__.py b/specs/gen_docs/__init__.py new file mode 100644 index 0000000000..9313b4dcc6 --- /dev/null +++ b/specs/gen_docs/__init__.py @@ -0,0 +1 @@ +# Intentionally Empty \ No newline at end of file diff --git a/specs/gen_docs/gen_doc_pages.py b/specs/gen_docs/gen_doc_pages.py new file mode 100755 index 0000000000..c2c20d3c4c --- /dev/null +++ b/specs/gen_docs/gen_doc_pages.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python + +# Autogenerate Documentation Pages from the formal specification + +import argparse + +import json +from pathlib import Path +from gen_spec_md import gen_spec_md + +# import re +# import textwrap + +SIGNED_DOCS_SPECS = "../signed_doc.json" +SIGNED_DOCS_PAGES_DIR = "../../docs/src/architecture/08_concepts/catalyst_docs" + + +def get_signed_doc_data(spec_file): + """ + Load the Signed Document Data from its json file. + """ + with open(spec_file, "r") as f: + return json.load(f) + + +def create_missing_doc_files(): + """ + Create basic markdown files for any document types that are missing. + """ + + docs = get_signed_doc_data() + all_docs = docs["docs"] + + for doc_name in all_docs: + file_name = doc_name.lower().replace(" ", "_") + ".md" + print(f"{doc_name} : {file_name}") + + doc_path = Path(SIGNED_DOCS_PAGES_DIR, file_name) + if doc_path.is_file(): + print("Exists") + else: + new_doc_contents = '# {{{{ insert_signed_doc_details( "{}" ) }}}}\n'.format( + doc_name + ) + doc_path.write_text(new_doc_contents) + print("Created") + +def save_or_validate(file_name, file_data, args): + """Save a file or Validate it, depending on whats required.""" + md_file = Path(args.output).joinpath("spec.md") + if args.generate: + print(f"Generating {file_name}") + md_file.write_text(file_data) + else: + print(f"Validating {file_name}") + if not md_file.exists(): + print(f"Documentation file missing: {file_name}.") + return False + + current_file = md_file.read_text() + if current_file != file_data: + print(f"Documentation not generated correctly: {file_name}.") + return False + return True + + +if __name__ == "__main__": + # Initialize parser + parser = argparse.ArgumentParser(description = "Markdown Documentation Generator for the Signed Documentation Specifications") + parser.add_argument("spec", help = "Path to JSON Specification file") + parser.add_argument("-o", "--output", help = "Where the docs are generated/located (directory)", required=True) + parser.add_argument("-g", "--generate", action="store_true", help="Set to cause docs to be generated, otherwise they are validated") + + args = parser.parse_args() + + # Check the base path exists and is a directory. + base_path = Path(args.output) + if not base_path.exists(): + base_path.mkdir(parents=True) + else: + if not base_path.is_dir(): + print("Base path is not a Directory") + exit(1) + + docs = get_signed_doc_data(args.spec) + + good = True + # Generate each of the files. + spec_md = Path(args.output).joinpath("spec.md") + + good |= save_or_validate("specs.md",gen_spec_md(docs),args) + + if not good: + print("File Comparisons Failed, Documentation is not current.") + exit(1) + + if args.generate: + print("Documentation Generated Successfully.") + else: + print("Documentation Validated Successfully.") diff --git a/specs/gen_docs/gen_spec_md.py b/specs/gen_docs/gen_spec_md.py new file mode 100644 index 0000000000..7d515ddc64 --- /dev/null +++ b/specs/gen_docs/gen_spec_md.py @@ -0,0 +1,7 @@ +# Generate the spec.md file + +def gen_spec_md(doc_defs): + """ + Generate a `spec.md` file from the definitions. + """ + return "spec.md" \ No newline at end of file diff --git a/specs/gen_docs/test/spec.md b/specs/gen_docs/test/spec.md new file mode 100644 index 0000000000..8e63671323 --- /dev/null +++ b/specs/gen_docs/test/spec.md @@ -0,0 +1 @@ +spec.md \ No newline at end of file diff --git a/specs/utility/gen_doc_pages.py b/specs/utility/gen_doc_pages.py deleted file mode 100755 index ea9c8f0cd7..0000000000 --- a/specs/utility/gen_doc_pages.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python - -# Autogenerate Documentation Pages for each signed document -# Will only create new pages and will not modify existing ones. - -import json -from pathlib import Path - -# import re -# import textwrap - -SIGNED_DOCS_SPECS = "../signed_doc.json" -SIGNED_DOCS_PAGES_DIR = "../../docs/src/architecture/08_concepts/catalyst_docs" - - -def get_signed_doc_data(): - """ - Load the Signed Document Data from its json file. - """ - with open(SIGNED_DOCS_SPECS, "r") as f: - return json.load(f) - - -def create_missing_doc_files(): - """ - Create basic markdown files for any document types that are missing. - """ - - docs = get_signed_doc_data() - all_docs = docs["docs"] - - for doc_name in all_docs: - file_name = doc_name.lower().replace(" ", "_") + ".md" - print(f"{doc_name} : {file_name}") - - doc_path = Path(SIGNED_DOCS_PAGES_DIR, file_name) - if doc_path.is_file(): - print("Exists") - else: - new_doc_contents = '# {{{{ insert_signed_doc_details( "{}" ) }}}}\n'.format( - doc_name - ) - doc_path.write_text(new_doc_contents) - print("Created") - - -if __name__ == "__main__": - create_missing_doc_files() From 3820bad4103a777b4b50d5618f3b13851c88661c Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 12 Mar 2025 18:26:37 +0700 Subject: [PATCH 24/35] feat(docs): Formal signed doc specs auto markdown generation WIP --- .vscode/extensions.json | 2 + docs/macros/signed_docs.py | 77 +-- specs/Justfile | 18 +- specs/gen_docs/__init__.py | 2 +- specs/gen_docs/common.py | 140 +++++ specs/gen_docs/gen_doc_pages.py | 234 ++++++-- specs/gen_docs/gen_metadata_md.py | 68 +++ specs/gen_docs/gen_spec_index.py | 14 + specs/gen_docs/gen_spec_md.py | 130 +++- specs/gen_docs/gen_types_md.py | 106 ++++ specs/gen_docs/test/.pages | 5 + specs/gen_docs/test/metadata.md | 319 ++++++++++ specs/gen_docs/test/spec.md | 116 +++- specs/gen_docs/test/types.md | 54 ++ specs/signed_doc.json | 689 +++++++++++++++++----- specs/signed_docs/authors_copyright.cue | 25 + specs/signed_docs/cddl_defs.cue | 64 ++ specs/signed_docs/cose_headers.cue | 27 +- specs/signed_docs/documentation_links.cue | 2 +- specs/signed_docs/metadata.cue | 118 +++- specs/signed_docs/signed_doc.cue | 16 + 21 files changed, 1910 insertions(+), 316 deletions(-) create mode 100644 specs/gen_docs/common.py create mode 100644 specs/gen_docs/gen_metadata_md.py create mode 100644 specs/gen_docs/gen_spec_index.py create mode 100644 specs/gen_docs/gen_types_md.py create mode 100644 specs/gen_docs/test/.pages create mode 100644 specs/gen_docs/test/metadata.md create mode 100644 specs/gen_docs/test/types.md create mode 100644 specs/signed_docs/authors_copyright.cue create mode 100644 specs/signed_docs/cddl_defs.cue diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e5e1743e17..b6cfac50c0 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -25,5 +25,7 @@ "terrastruct.d2", "fill-labs.dependi", "nefrob.vscode-just-syntax", + "charliermarsh.ruff", + "ms-python.python", ] } \ No newline at end of file diff --git a/docs/macros/signed_docs.py b/docs/macros/signed_docs.py index 05d4df5eac..b2266c9a9a 100644 --- a/docs/macros/signed_docs.py +++ b/docs/macros/signed_docs.py @@ -101,71 +101,6 @@ def doc_type_details(env): return doc_type_details -def header_parameter_doc(header, doc_data): - """ - Create documentation for a single cose header. - """ - options = doc_data["cose_headers"][header] - content_types = doc_data["contentTypes"] - encoding_types = doc_data["encodingTypes"] - label = options.get("coseLabel") - custom_header = "***Custom Header***" - if not isinstance(label, str): - custom_header = "" - header_format = options["format"] - header_value = 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:" - for value in header_value: - value_entry = f"\n * {value}" - value_data = None - if header_format == "IANA Media Type" and value in content_types: - value_data = content_types[value] - if header_format == "HTTP Content Encoding" and value in encoding_types: - value_data = encoding_types[value] - - if value_data is not None: - if value_data["linked"]: - value_entry = f"\n * [{value}]" - value_entry += ( - f" : {value_data['description'].replace('\n', '\n ')}" - ) - - header_format_display += value_entry - - return f""" -#### {header} - -{options.get("description")} - -* Required : {options["required"]} -* Cose Label : {label} {custom_header} -* Format : {header_format_display} - -""" - - -def cose_header_parameters(env): - """ - Insert details about Cose header Parameters that are defined for use. - """ - doc_data = get_signed_doc_data(env) - headers = doc_data["cose_headers"] - header_order = doc_data["cose_headers_order"] - # Make sure unordered headers get included in the documentation. - for header in headers: - if header not in header_order: - header_order += header - - header_parameters_doc = "" - for header in header_order: - header_parameters_doc += header_parameter_doc(header, doc_data) - headers.pop(header) - - return header_parameters_doc - - def external_links(env): """ Insert External Links we might have used in descriptions. @@ -186,7 +121,7 @@ def metadata_fields(env, doc_name=None): """ doc_data = get_signed_doc_data(env) if doc_name is not None: - fields = doc_data["docs"][doc_name]["metadata"] + fields = doc_data["docs"][doc_name]["metadata"] field_title_level = "###" else: fields = doc_data["metadata"] @@ -196,7 +131,7 @@ def metadata_fields(env, doc_name=None): # make sure every field is listed in the ordering for field_name in fields: - if not field_name in order: + if field_name not in order: order += field_name field_display = "" @@ -210,13 +145,13 @@ def metadata_fields(env, doc_name=None): | Required | {field["required"]} | """ if field["required"] != "excluded": - field_display += f"| Format | {field["format"]} |\n" + field_display += f"| Format | {field['format']} |\n" if "multiple" in field: - field_display += f"| Multiple References | {field["multiple"]} |\n" + field_display += f"| Multiple References | {field['multiple']} |\n" if "type" in field: ref_heading = "Valid References" ref_doc_names = field["type"] - if isinstance(ref_doc_names,str): + if isinstance(ref_doc_names, str): ref_doc_names = [ref_doc_names] for ref_doc in ref_doc_names: field_display += f"| {ref_heading} | {ref_doc} |\n" @@ -231,6 +166,7 @@ def metadata_fields(env, doc_name=None): """ return field_display + def signed_doc_details(env, name): """ Generate Signed Document Detailed Documentation Page. @@ -263,4 +199,3 @@ class env: print() print("### GLOBAL METADATA ###") print(metadata_fields(env)) - diff --git a/specs/Justfile b/specs/Justfile index 3ec0823c4f..d56566b44d 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -20,12 +20,24 @@ check: format regenerate: check # 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 gen_docs; ./gen_doc_pages.py + # Generate the markdown docs from the specification. + cd gen_docs; ./gen_doc_pages.py -g -o test ../signed_doc.json + # Check our validation code actually works properly + cd gen_docs; ./gen_doc_pages.py -o test ../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 # Pre Push Checks - intended to be run by a git pre-push hook. -pre-push: regenerate validate - \ No newline at end of file +pre-push: format-python-code lint-python regenerate validate + +# Fix and Check Markdown files +format-python-code: + ruff check --select I --fix . + ruff format . + +# Fix and Check Markdown files +lint-python: + ruff check . \ No newline at end of file diff --git a/specs/gen_docs/__init__.py b/specs/gen_docs/__init__.py index 9313b4dcc6..52e577c30a 100644 --- a/specs/gen_docs/__init__.py +++ b/specs/gen_docs/__init__.py @@ -1 +1 @@ -# Intentionally Empty \ No newline at end of file +# Intentionally Empty diff --git a/specs/gen_docs/common.py b/specs/gen_docs/common.py new file mode 100644 index 0000000000..d0a024bb34 --- /dev/null +++ b/specs/gen_docs/common.py @@ -0,0 +1,140 @@ +# Common documentation generation functions +import glob +import os +from datetime import datetime + + +def get_latest_file_change(directory): + # Use glob to find all files ending with .cue in the directory + cue_files = glob.glob(os.path.join(directory, "*.cue")) + + if not cue_files: + return "????-??-??" + + latest_file = max(cue_files, key=os.path.getmtime) + file_mod_time = os.path.getmtime(latest_file) + mod_date = datetime.fromtimestamp(file_mod_time).strftime("%Y-%m-%d") + + return mod_date + + +def insert_copyright(doc_data, document_name=None): + """ + Generate a copyright notice into the given document data. + + document_name: Name of the signed document we also get copyright info from. + """ + authors = doc_data["authors"] + copyright = doc_data["copyright"] + global_last_modified = get_latest_file_change("../signed_docs") + + copyright_year = copyright["created"][:4] + last_modified_year = global_last_modified[:4] + if last_modified_year != copyright_year: + copyright_year = f"{copyright_year}-{last_modified_year}" + + copyright_notice = ( + f""" +## Copyright + +| Copyright | :copyright: {copyright_year} {copyright["copyright"]} | +| --- | --- | +| License | This document is licensed under {copyright["license"]} | +| Created | {copyright["created"]} | +| Modified | {global_last_modified} | +""".strip() + + "\n" + ) + + author_title = " Authors " + for author in authors: + copyright_notice += f"|{author_title}| {author} <{authors[author]}> |\n" + author_title = " " + + return copyright_notice + + +def metadata_format_link(name: str, depth: int = 0): + """ + Metadata Format link. + """ + link = f"metadata.md#{name.lower().replace(' ', '-')}" + + while depth > 0: + link = f"../{link}" + link -= 1 + + return f"[{name}]({link})" + + +def metadata_field_link(name: str, depth: int = 0): + """ + Metadata Field link. + """ + link = f"metadata.md#{name.lower().replace('`', '')}" + + while depth > 0: + link = f"../{link}" + link -= 1 + + return f"[`{name}`]({link})" + + +def metadata_fields(doc_data: dict, doc_name: str = None, depth: int = 0): + """ + Display Metadata fields for the default set, or a specific document. + """ + field_title_level = "###" + if doc_name is not None: + fields = doc_data["docs"][doc_name]["metadata"] + else: + fields = doc_data["metadata"] + + order = doc_data["metadata_order"] + + # make sure every field is listed in the ordering + for field_name in fields: + if field_name not in order: + order += field_name + + field_display = "" + for field_name in order: + field = fields[field_name] + field_display += f""" +{field_title_level} `{field_name}` + +| Parameter | Value | +| --- | --- | +| Required | {field["required"]} | +""" + if field["required"] == "excluded": + continue + + field_display += ( + f"| Format | {metadata_format_link(field['format'], depth)} |\n" + ) + if field.get("multiple", False): + field_display += f"| Multiple References | {field['multiple']} |\n" + if "type" in field: + ref_heading = "Valid References" + ref_doc_names = field["type"] + if isinstance(ref_doc_names, str): + ref_doc_names = [ref_doc_names] + for ref_doc in ref_doc_names: + field_display += f"| {ref_heading} | {ref_doc} |\n" + ref_heading = "" + exclusive = field.get("exclusive", None) + if exclusive is not None: + exclusive_title = "Exclusive" + for ref in exclusive: + field_display += f"| {exclusive_title} | {ref} |\n" + exclusive_title = "" + + field_display += f""" +{field["description"]} + +{field_title_level}# Validation + +{field["validation"]} +""" + return field_display.strip() diff --git a/specs/gen_docs/gen_doc_pages.py b/specs/gen_docs/gen_doc_pages.py index c2c20d3c4c..3f144f0b20 100755 --- a/specs/gen_docs/gen_doc_pages.py +++ b/specs/gen_docs/gen_doc_pages.py @@ -3,19 +3,21 @@ # Autogenerate Documentation Pages from the formal specification import argparse - import json +import re from pathlib import Path -from gen_spec_md import gen_spec_md -# import re -# import textwrap +from common import metadata_field_link +from gen_metadata_md import gen_metadata_md +from gen_spec_index import gen_spec_index +from gen_spec_md import gen_spec_md +from gen_types_md import gen_types_md SIGNED_DOCS_SPECS = "../signed_doc.json" SIGNED_DOCS_PAGES_DIR = "../../docs/src/architecture/08_concepts/catalyst_docs" -def get_signed_doc_data(spec_file): +def get_signed_doc_data(spec_file: str) -> dict: """ Load the Signed Document Data from its json file. """ @@ -23,40 +25,143 @@ def get_signed_doc_data(spec_file): return json.load(f) -def create_missing_doc_files(): +def remove_tabs(text: str, tabstop: int = 4) -> str: """ - Create basic markdown files for any document types that are missing. + Replace tabs in the input text with spaces so that the text aligns on tab stops. + + Args: + text (str): The input text containing tabs. + tabstop (int): The number of characters per tab stop. Default is 8. + + Returns: + str: Text with tabs replaced by spaces, aligned at each tab stop. """ + # Create a regex pattern to match any tab character + pattern = "\t" - docs = get_signed_doc_data() - all_docs = docs["docs"] + def replace_tab(match): + # Calculate the number of spaces needed to reach the next tab stop + position = match.start() + return " " * (tabstop - (position % tabstop)) - for doc_name in all_docs: - file_name = doc_name.lower().replace(" ", "_") + ".md" - print(f"{doc_name} : {file_name}") + # Substitute tabs with spaces, using a custom replacement function + no_tabs_text = re.sub(pattern, replace_tab, text) - doc_path = Path(SIGNED_DOCS_PAGES_DIR, file_name) - if doc_path.is_file(): - print("Exists") + return no_tabs_text + + +def strip_end_whitespace(s: str) -> str: + """ + Strip all whitespace from the end of any lines. + """ + lines = s.splitlines() + stripped_lines = [line.rstrip() for line in lines] + return "\n".join(stripped_lines).strip() + "\n" + + +def add_metadata_links(file_data: str, doc_data: dict, depth: int = 0) -> str: + """ + Add metadata field documentation cross reference links to the document. + All metadata fields in text must be as `` or they will not be linked. + """ + lines = file_data.splitlines() + file_data = "" + for line in lines: + if not line.startswith("#"): + for field_name in doc_data["metadata"]: + fieldNameRegex = f"(^|\\s)`{field_name}`(\\.|\\s|$)" + replacement = f"\\1{metadata_field_link(field_name, depth)}\\2" + line = re.sub( + fieldNameRegex, + replacement, + line, + flags=re.IGNORECASE | re.MULTILINE, + ) + file_data += f"{line}\n" + + return file_data + + +def add_reference_links(file_data, doc_data) -> str: + """ + Add Markdown reference links to the document. + Only Reference links found to be used by the document will be added. + """ + links = doc_data["documentationLinks"] + linkAka = doc_data["linkAKA"] + + file_data = strip_end_whitespace(file_data) + + allLinkNames = sorted( + list(linkAka.keys()) + list(links.keys()), key=lambda x: -len(x) + ) + + actualLinksUsed = {} + for linkName in allLinkNames: + escLinkName = re.escape(linkName) + linkNameRegex = f"(^|\\s)({escLinkName})(\\.|\\s|$)" + if linkName in linkAka: + replacement = f"\\1[\\2][{linkAka[linkName]}]\\3" + (file_data, cnt) = re.subn( + linkNameRegex, + replacement, + file_data, + flags=re.IGNORECASE | re.MULTILINE, + ) + if cnt > 0: + actualLinksUsed[linkAka[linkName]] = links[linkAka[linkName]] else: - new_doc_contents = '# {{{{ insert_signed_doc_details( "{}" ) }}}}\n'.format( - doc_name + replacement = r"\1[\2]\3" + (file_data, cnt) = re.subn( + linkNameRegex, + replacement, + file_data, + flags=re.IGNORECASE | re.MULTILINE, ) - doc_path.write_text(new_doc_contents) - print("Created") + if cnt > 0: + actualLinksUsed[linkName] = links[linkName] + + for link in actualLinksUsed: + file_data += f"\n[{link}]: {actualLinksUsed[link]}" -def save_or_validate(file_name, file_data, args): + return file_data + + +def save_or_validate( + file_name: str, + gen_func: callable, + args: argparse.Namespace, + doc_data: dict, + depth=0, +) -> bool: """Save a file or Validate it, depending on whats required.""" - md_file = Path(args.output).joinpath("spec.md") + # Generate the document. + file_data = gen_func(doc_data) + # Remove any tabs from the file data. + file_data = remove_tabs(file_data) + # Add any links we find in the document. + if file_name.endswith(".md"): + file_data = add_reference_links(file_data, doc_data) + file_data = add_metadata_links(file_data, doc_data, depth) + + # Remove any leading or trailing newlines and add a single newline at the end/ + # Helps make clean markdown files. + file_data = strip_end_whitespace(file_data) + md_file = Path(args.output).joinpath(file_name) if args.generate: print(f"Generating {file_name}") - md_file.write_text(file_data) + if md_file.exists(): + old_contents = md_file.read_text() + if old_contents == file_data: + print(f"{file_name} is already up-to-date.") + else: + md_file.write_text(file_data) else: print(f"Validating {file_name}") if not md_file.exists(): print(f"Documentation file missing: {file_name}.") return False - + current_file = md_file.read_text() if current_file != file_data: print(f"Documentation not generated correctly: {file_name}.") @@ -64,31 +169,90 @@ def save_or_validate(file_name, file_data, args): return True -if __name__ == "__main__": - # Initialize parser - parser = argparse.ArgumentParser(description = "Markdown Documentation Generator for the Signed Documentation Specifications") - parser.add_argument("spec", help = "Path to JSON Specification file") - parser.add_argument("-o", "--output", help = "Where the docs are generated/located (directory)", required=True) - parser.add_argument("-g", "--generate", action="store_true", help="Set to cause docs to be generated, otherwise they are validated") +def create_individual_doc_files(docs: dict, args: argparse.Namespace) -> bool: + """ + Create Individual markdown files for all document types. + """ + + docs = get_signed_doc_data() + all_docs = docs["docs"] + + for doc_name in all_docs: + file_name = doc_name.lower().replace(" ", "_") + ".md" + print(f"{doc_name} : {file_name}") + + doc_path = Path("docs", file_name) + if doc_path.is_file(): + print("Exists") + else: + new_doc_contents = '# {{{{ insert_signed_doc_details( "{}" ) }}}}\n'.format( + doc_name + ) + doc_path.write_text(new_doc_contents) + print("Created") - args = parser.parse_args() +def check_is_dir(base_path: Path) -> bool: + """ + Check if the path exists, and is a directory. + Otherwise try and make it. + Fails if it exists and is NOT a directory. + """ # Check the base path exists and is a directory. - base_path = Path(args.output) if not base_path.exists(): base_path.mkdir(parents=True) else: if not base_path.is_dir(): print("Base path is not a Directory") - exit(1) + return False + return True + +def init_parser() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Markdown Documentation Generator for the Signed Documentation Specifications" + ) + parser.add_argument("spec", help="Path to JSON Specification file") + parser.add_argument( + "-o", + "--output", + help="Where the docs are generated/located (directory)", + required=True, + ) + parser.add_argument( + "-g", + "--generate", + action="store_true", + help="Set to cause docs to be generated, otherwise they are validated", + ) + + args = parser.parse_args() + + # Check the base path exists and is a directory. + if not check_is_dir(Path(args.output)): + exit(1) + if not check_is_dir(Path(args.output, "docs")): + exit(1) + + return args + + +if __name__ == "__main__": + # Initialize parser + args = init_parser() + + # Get the compiled documentation json file docs = get_signed_doc_data(args.spec) + # We start out hoping everything is OK. good = True - # Generate each of the files. - spec_md = Path(args.output).joinpath("spec.md") - good |= save_or_validate("specs.md",gen_spec_md(docs),args) + # Generate each of the files. + good &= save_or_validate(".pages", gen_spec_index, args, docs) + good &= save_or_validate("spec.md", gen_spec_md, args, docs) + good &= save_or_validate("types.md", gen_types_md, args, docs) + good &= save_or_validate("metadata.md", gen_metadata_md, args, docs) + # good &= create_individual_doc_files(docs, args) if not good: print("File Comparisons Failed, Documentation is not current.") diff --git a/specs/gen_docs/gen_metadata_md.py b/specs/gen_docs/gen_metadata_md.py new file mode 100644 index 0000000000..98cc1aa0aa --- /dev/null +++ b/specs/gen_docs/gen_metadata_md.py @@ -0,0 +1,68 @@ +# Generate the spec.md file +from common import insert_copyright, metadata_fields + + +def get_cddl(name, defs, found=[]): + """ + Get the CDDL for a metadatum. + """ + this_cddl = "" + # Add required definitions to this one (recursive) + for requires in defs[name]["requires"]: + if requires not in found: + next_cddl, found = get_cddl(requires, defs, found) + found.append(requires) + this_cddl += next_cddl + this_cddl += f"{name} = {defs[name]['def']}\n" + + return this_cddl, found + + +def metadata_types(doc_defs): + """ + Generate the metadata types documentation. + """ + metadata = doc_defs["metadataFormats"] + cddl = doc_defs["cddlDefinitions"] + + metadata_types = "" + + for metadatum in metadata: + cddl_def, _ = get_cddl(metadata[metadatum]["cddl"], cddl) + cddl_def = cddl_def.strip() + # TODO: We could check if the `cddl_def` is actually valid CDDL here. + metadata_types += f""" +### {metadatum} + +{metadata[metadatum]["description"]} + +#### CDDL Specification + +```cddl +{cddl_def} +``` +""" + + return metadata_types.strip() + + +def gen_metadata_md(doc_defs): + """ + Generate a `metadata.md` file from the definitions. + """ + return f""" +# Metadata Fields + +## Metadata Types + +The following types of metadata have been defined. +All Metadata fields use one of these types. + +{metadata_types(doc_defs)} + +## Individual Metadata field definitions + +{metadata_fields(doc_defs)} + +{insert_copyright(doc_defs)} +""" diff --git a/specs/gen_docs/gen_spec_index.py b/specs/gen_docs/gen_spec_index.py new file mode 100644 index 0000000000..6ecd4a27ee --- /dev/null +++ b/specs/gen_docs/gen_spec_index.py @@ -0,0 +1,14 @@ +# Generate the spec.md file + + +def gen_spec_index(doc_defs): + """ + Generate a `.pages` file for the base specification files. + """ + return """ +title: Catalyst Signed Document +nav: + - Specification: spec.md + - Metadata Fields: metadata.md + - Document Types: types.md +""" diff --git a/specs/gen_docs/gen_spec_md.py b/specs/gen_docs/gen_spec_md.py index 7d515ddc64..9bc7a6101a 100644 --- a/specs/gen_docs/gen_spec_md.py +++ b/specs/gen_docs/gen_spec_md.py @@ -1,7 +1,135 @@ # Generate the spec.md file +from common import insert_copyright + + +def header_parameter_doc(header, doc_data): + """ + Create documentation for a single cose header. + """ + options = doc_data["cose_headers"][header] + content_types = doc_data["contentTypes"] + encoding_types = doc_data["encodingTypes"] + label = options.get("coseLabel") + custom_header = "***Custom Header***" + if not isinstance(label, str): + custom_header = "" + header_format = options["format"] + header_value = 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:" + for value in header_value: + value_entry = f"\n * {value}" + value_data = None + if header_format == "IANA Media Type" and value in content_types: + value_data = content_types[value] + if header_format == "HTTP Content Encoding" and value in encoding_types: + value_data = encoding_types[value] + + if value_data is not None: + value_entry += ( + f" : {value_data['description'].replace('\n', '\n ')}" + ) + + header_format_display += value_entry + + return f""" +#### {header} + +{options.get("description")} + +* Required : {options["required"]} +* Cose Label : {label} {custom_header} +* Format : {header_format_display} +""" + + +def cose_header_parameters(doc_data): + """ + Insert details about Cose header Parameters that are defined for use. + """ + headers = doc_data["cose_headers"] + header_order = doc_data["cose_headers_order"] + # Make sure unordered headers get included in the documentation. + for header in headers: + if header not in header_order: + header_order += header + + header_parameters_doc = "" + for header in header_order: + header_parameters_doc += header_parameter_doc(header, doc_data) + headers.pop(header) + + return header_parameters_doc.strip() + def gen_spec_md(doc_defs): """ Generate a `spec.md` file from the definitions. """ - return "spec.md" \ No newline at end of file + return f""" +# Catalyst Signed Document Specification + +## Abstract + +Project Catalyst requires a verifiable data format for the publication and validation of +large volumes of off chain information. + +The Catalyst Signed Documents Specification is based on COSE +and provides the basis of this document specification. + +## Motivation + +As Project Catalyst decentralizes via both on-chain and off-chain mechanisms, a reliable, +standardized process for authenticating documents and their relationships is required. + +## Specification + +Project Catalyst generates a large volume of off chain information. +This information requires similar guarantees as on-chain data. +It needs to be verifiably published and also immutable. +However, we also require the ability to publish new versions of documents, +and for documents to be able to securely reference one another. + +Catalyst Signed Documents are based on COSE. +Specifically, the COSE Sign format is used. +This allows one or more signatures to be attached to the same document. + +### COSE Header Parameters + +COSE documents define a set of standard COSE header parameters. +All COSE Header Parameters are protected and +*MUST* appear in the protected headers section of the document. +The COSE header parameters defined and used by Catalyst Signed Documents are as follows: + +{cose_header_parameters(doc_defs)} + +### Metadata + +Catalyst Signed Documents extend the Header Parameters with a series of Metadata fields. +These fields are defined [here](./meta.md). + +### Signing Catalyst Signed Documents + +Catalyst Signed Documents are based on the COSE Sign format. +This allows one or more signatures to be attached to the same document. +A catalyst signed document *MUST* have at least one valid signature attached. +Multiple signatures may also be attached to the same document, where that is required. + +Each signature is contained in an array of signatures attached to the document. +The signatures contain protected headers, and the signature itself. +The headers currently defined for the signatures are: + +#### `kid` + +The kid is a UTF-8 encoded Catalyst ID. +Any `kid` format which conforms to the Catalyst ID specification may be used. +The Catalyst ID unambiguously defines both the signing keys and signing algorithm +used to sign the protected portion of the document. + +* Required: yes +* Cose Label: 4 +* Format: UTF-8 encoded Catalyst ID + +{insert_copyright(doc_defs)} +""" diff --git a/specs/gen_docs/gen_types_md.py b/specs/gen_docs/gen_types_md.py new file mode 100644 index 0000000000..8ffe826e87 --- /dev/null +++ b/specs/gen_docs/gen_types_md.py @@ -0,0 +1,106 @@ +# Generate the spec.md file +from common import insert_copyright + + +def uuid_as_cbor(uuid): + return f"37(h'{uuid.replace('-', '')}')" + + +def name_to_spec_link(name, ref=None): + """ + Create a link to a document type, and an optional ref inside the document. + """ + link = "./../catalyst_docs/" + name.lower().replace(" ", "_") + ".md" + if ref is not None: + link += f"#{ref}" + return link + + +def name_for_uuid(doc_types, uuid): + """ + Get the name for a document base type, given its uuid + """ + for k in doc_types: + if doc_types[k] == uuid: + return k + return "Unknown" + + +def base_types(docs, doc_types, name): + types = docs[name]["type"] + type_names = "" + for sub_type in types: + type_names += name_for_uuid(doc_types, sub_type) + "/" + return type_names[:-1] + + +def types_as_cbor(docs, name): + types = docs[name]["type"] + type_names = "[" + for sub_type in types: + type_names += uuid_as_cbor(sub_type) + ",
" + return type_names[:-6] + "]" + + +def doc_type_details(doc_data): + """ + Generate a Document Type Detailed Summary from the Document Specifications Data + """ + + doc_types = doc_data["base_types"] + docs = doc_data["docs"] + + doc_type_details = """ + +| Document Type | Base Types | CBOR | +| :--- | :--- | :--- | +""" + + for k in docs: + doc_type_details += f"| [{k}]({name_to_spec_link(k)}) | {base_types(docs, doc_types, k)} | {types_as_cbor(docs, k)} |\n" + + doc_type_details += "" + + return doc_type_details.strip() + + +def doc_type_summary(doc_data): + """ + Generate a Document Base Type Summary from the Document Specifications Data + """ + doc_types = doc_data["base_types"] + + doc_type_summary = """ +| Base Type | UUID | CBOR | +| :--- | :--- | :--- | +""" + + for k in doc_types: + doc_type_summary += ( + f"| {k} | `{doc_types[k]}` | `{uuid_as_cbor(doc_types[k])}` |\n" + ) + + return doc_type_summary.strip() + + +def gen_types_md(doc_defs): + """ + Generate a `types.md` file from the definitions. + """ + return f""" +# Document Types Table + +## Document Base Types + +All Document Types are defined by composing these base document types: + +{doc_type_summary(doc_defs)} + +## Document Types + +All Defined Document Types + +{doc_type_details(doc_defs)} + +{insert_copyright(doc_defs)} +""" diff --git a/specs/gen_docs/test/.pages b/specs/gen_docs/test/.pages new file mode 100644 index 0000000000..883e563a83 --- /dev/null +++ b/specs/gen_docs/test/.pages @@ -0,0 +1,5 @@ +title: Catalyst Signed Document +nav: + - Specification: spec.md + - Metadata Fields: metadata.md + - Document Types: types.md diff --git a/specs/gen_docs/test/metadata.md b/specs/gen_docs/test/metadata.md new file mode 100644 index 0000000000..c1c571b163 --- /dev/null +++ b/specs/gen_docs/test/metadata.md @@ -0,0 +1,319 @@ +# Metadata Fields + +## Metadata Types + +The following types of metadata have been defined. +All Metadata fields use one of these types. + +### Collaborators Reference List + +A list of collaborators who can participate in drafting and submitting a document + +#### [CDDL][RFC8610] Specification + +```cddl +catalyst_id = text +collaborators = [ * catalyst_id ] +``` + +### Document Reference + +A document reference identifier + +#### [CDDL][RFC8610] Specification + +```cddl +uuid_v7 = 6.37(bytes .size 16) +document_id = uuid_v7 +document_ver = uuid_v7 +blake2b_256 = bytes .size 32 +document_hash = blake2b_256 +document_ref = [ 1* [ document_id, document_ver, document_hash ] ] +``` + +### Document Type + +A document type identifier + +#### [CDDL][RFC8610] Specification + +```cddl +uuid_v4 = 6.37(bytes .size 16) +document_type = [ 1* uuid_v4 ] +``` + +### Section Reference + +A document section reference identifier + +#### [CDDL][RFC8610] Specification + +```cddl +json_pointer = text +section_ref = json_pointer +``` + +### [UUIDv4][RFC9562-V4] + +Version 4 formatted [UUID][RFC9562] + +#### [CDDL][RFC8610] Specification + +```cddl +uuid_v4 = 6.37(bytes .size 16) +``` + +### [UUIDv7][RFC9562-V7] + +Version 7 formatted [UUID][RFC9562] + +#### [CDDL][RFC8610] Specification + +```cddl +uuid_v7 = 6.37(bytes .size 16) +``` + +## Individual Metadata field definitions + +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](metadata.md#document-type) | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](metadata.md#ver) == [`id`](metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + +### `ref` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](metadata.md#document-reference) | +| Valid References | Proposal Meta Template | +| | Proposal Template | +| | Proposal | +| | Proposal Comment Meta Template | +| | Proposal Comment Template | +| | Proposal Comment | +| | Proposal Submission Action | +| | Proposal Moderation Action | +| | Comment Action Document | +| | Brand Parameters | +| | Campaign Parameters | +| | Category Parameters | +| | Election Parameters | + +Reference to a Linked Document or Documents. +This is the primary hierarchical reference to a related document. + +This is an Array of the format: + `[[DocumentID, DocumentVer, DocumentHash],...]` + +* `DocumentID` is the [UUIDv7][RFC9562-V7] ID of the Document being referenced. +* `DocumentVer` is the [UUIDv7][RFC9562-V7] Version of the Document being referenced. +* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload. + It ensures that the intended referenced document is the one used, and there has been no substitution. + Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one. + +#### Validation + +Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document. +The calculated Hash of the Referenced Document **MUST** match the Hash in the reference. + +### `template` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](metadata.md#document-reference) | +| Valid References | Proposal Meta Template | +| | Proposal Template | +| | Proposal Comment Meta Template | +| | Proposal Comment Template | + +Reference to the template used to create and/or validate this document. + +#### Validation + +In addition to the validation performed for `ref`, +The document payload is not valid if it does not validate completely against the referenced template. + +### `reply` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](metadata.md#document-reference) | +| Valid References | Proposal Comment | + +Reference to a Comment document type being referred to. + +#### Validation + +In addition to the validation performed for `ref`, +The [`ref`](metadata.md#ref) of the [`reply`](metadata.md#reply) document must be the same as +the original comment document. + +### `section` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Section Reference](metadata.md#section-reference) | + +A Reference to the original document, or the comment being replied to. + +#### Validation + +For a non-reply this must be a valid section reference into the referenced document. +For a reply, this must be a valid section reference into the comment being replied to. + +### `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. + +#### 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. + +### `brand_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](metadata.md#document-reference) | +| Valid References | Brand Parameters | +| Exclusive | campaign_id | +| | category_id | + +A reference to the Brand Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`brand_id`](metadata.md#brand_id) must match the [`brand_id`](metadata.md#brand_id) +of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + +### `campaign_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](metadata.md#document-reference) | +| Valid References | Campaign Parameters | +| Exclusive | brand_id | +| | category_id | + +A reference to the Campaign Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`campaign_id`](metadata.md#campaign_id) must match the +[`campaign_id`](metadata.md#campaign_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + +### `category_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](metadata.md#document-reference) | +| Valid References | Category Parameters | +| Exclusive | brand_id | +| | campaign_id | + +A reference to the Category Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`category_id`](metadata.md#category_id) must match the +[`category_id`](metadata.md#category_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + +### `election_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](metadata.md#document-reference) | +| Valid References | Election Parameters | + +A reference to the Election Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`election_id`](metadata.md#election_id) must match the +[`election_id`](metadata.md#election_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[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 +[RFC8610]: https://www.rfc-editor.org/rfc/rfc8610 +[RFC9562]: https://www.rfc-editor.org/rfc/rfc9562.html diff --git a/specs/gen_docs/test/spec.md b/specs/gen_docs/test/spec.md index 8e63671323..07dba08a45 100644 --- a/specs/gen_docs/test/spec.md +++ b/specs/gen_docs/test/spec.md @@ -1 +1,115 @@ -spec.md \ No newline at end of file +# Catalyst Signed Document Specification + +## Abstract + +Project Catalyst requires a verifiable data format for the publication and validation of +large volumes of off chain information. + +The Catalyst Signed Documents Specification is based on [COSE][RFC9052] +and provides the basis of this document specification. + +## Motivation + +As Project Catalyst decentralizes via both on-chain and off-chain mechanisms, a reliable, +standardized process for authenticating documents and their relationships is required. + +## Specification + +Project Catalyst generates a large volume of off chain information. +This information requires similar guarantees as on-chain data. +It needs to be verifiably published and also immutable. +However, we also require the ability to publish new versions of documents, +and for documents to be able to securely reference one another. + +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. + +### [COSE Header Parameters][RFC9052-HeaderParameters] + +[COSE][RFC9052] documents define a set of standard [COSE header parameters][RFC9052-HeaderParameters]. +All [COSE Header Parameters][RFC9052-HeaderParameters] are protected and +*MUST* appear in the protected headers section of the document. +The [COSE header parameters][RFC9052-HeaderParameters] defined and used by Catalyst Signed Documents are as follows: + +#### content type + +IANA Media Type/s allowed in the Payload + +* Required : yes +* [Cose][RFC9052] Label : 3 +* Format : IANA 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: + * This is an unofficial media type + * [RFC9165] Additional Control Operators for [CDDL][RFC8610] are supported. + * Must not have Modules, schema must be self-contained. + +#### content-encoding + +Supported HTTP Encodings of the Payload. +If no compression or encoding is used, then this field must not be present. + +* Required : optional +* [Cose][RFC9052] Label : content-encoding ***Custom Header*** +* Format : HTTP Content Encoding + * Supported Values: + * [br] : [BROTLI][RFC7932] Compression + +### Metadata + +Catalyst Signed Documents extend the Header Parameters with a series of Metadata fields. +These fields are defined [here](./meta.md). + +### Signing Catalyst Signed Documents + +Catalyst Signed Documents are based on the [COSE Sign][RFC9052-CoseSign] format. +This allows one or more signatures to be attached to the same document. +A catalyst signed document *MUST* have at least one valid signature attached. +Multiple signatures may also be attached to the same document, where that is required. + +Each signature is contained in an array of signatures attached to the document. +The signatures contain protected headers, and the signature itself. +The headers currently defined for the signatures are: + +#### `kid` + +The kid is a [UTF-8][RFC3629] encoded Catalyst ID. +Any `kid` format which conforms to the Catalyst ID specification may be used. +The Catalyst ID unambiguously defines both the signing keys and signing algorithm +used to sign the protected portion of the document. + +* Required: yes +* [Cose][RFC9052] Label: 4 +* Format: [UTF-8][RFC3629] encoded Catalyst ID + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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 +[application/json]: https://www.iana.org/assignments/media-types/application/json +[JSON Schema]: https://json-schema.org/draft-07 +[RFC9052-CoseSign]: https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si +[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 +[br]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br diff --git a/specs/gen_docs/test/types.md b/specs/gen_docs/test/types.md new file mode 100644 index 0000000000..0135585b53 --- /dev/null +++ b/specs/gen_docs/test/types.md @@ -0,0 +1,54 @@ +# Document Types Table + +## Document Base Types + +All Document Types are defined by composing these base document types: + +| Base Type | [UUID][RFC9562] | [CBOR][RFC8949] | +| :--- | :--- | :--- | +| Action | `5e60e623-ad02-4a1b-a1ac-406db978ee48` | `37(h'5e60e623ad024a1ba1ac406db978ee48')` | +| Brand | `ebcabeeb-5bc5-4f95-91e8-cab8ca724172` | `37(h'ebcabeeb5bc54f9591e8cab8ca724172')` | +| 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')` | +| Election | `788ff4c6-d65a-451f-bb33-575fe056b411` | `37(h'788ff4c6d65a451fbb33575fe056b411')` | +| ModerationAction | `a5d232b8-5e03-4117-9afd-be32b878fcdd` | `37(h'a5d232b85e0341179afdbe32b878fcdd')` | +| 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 + +All Defined Document Types + + +| Document Type | Base Types | [CBOR][RFC8949] | +| :--- | :--- | :--- | +| [Brand Parameters](./../catalyst_docs/brand_parameters.md) | Brand | [37(h'ebcabeeb5bc54f9591e8cab8ca724172')] | +| [Campaign Parameters](./../catalyst_docs/campaign_parameters.md) | Campaign | [37(h'5ef32d5df240462ca7a4ba4af221fa23')] | +| [Category Parameters](./../catalyst_docs/category_parameters.md) | Category | [37(h'818938c331394daaafe6974c78488e95')] | +| [Comment Action Document](./../catalyst_docs/comment_action_document.md) | Action/Comment/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | +| [Election Parameters](./../catalyst_docs/election_parameters.md) | Election | [37(h'788ff4c6d65a451fbb33575fe056b411')] | +| [Proposal](./../catalyst_docs/proposal.md) | Proposal | [37(h'7808d2bad51140af84e8c0d1625fdfdc')] | +| [Proposal Comment](./../catalyst_docs/proposal_comment.md) | Comment/Proposal | [37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | +| [Proposal Comment Meta Template](./../catalyst_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](./../catalyst_docs/proposal_comment_template.md) | Template/Comment/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | +| [Proposal Meta Template](./../catalyst_docs/proposal_meta_template.md) | Template/Template/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | +| [Proposal Moderation Action](./../catalyst_docs/proposal_moderation_action.md) | Action/Proposal/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | +| [Proposal Submission Action](./../catalyst_docs/proposal_submission_action.md) | Action/Proposal/SubmissionAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'78927329cfd94ea19c710e019b126a65')] | +| [Proposal Template](./../catalyst_docs/proposal_template.md) | Template/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | + + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC8949]: https://www.rfc-editor.org/rfc/rfc8949.html +[RFC9562]: https://www.rfc-editor.org/rfc/rfc9562.html diff --git a/specs/signed_doc.json b/specs/signed_doc.json index b5d7c01899..4280b4d744 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -1,4 +1,8 @@ { + "authors": { + "Alex Pozhylenkov": "alex.pozhylenkov@iohk.io", + "Steven Johnson": "steven.johnson@iohk.io" + }, "base_types": { "Action": "5e60e623-ad02-4a1b-a1ac-406db978ee48", "Brand": "ebcabeeb-5bc5-4f95-91e8-cab8ca724172", @@ -11,24 +15,91 @@ "SubmissionAction": "78927329-cfd9-4ea1-9c71-0e019b126a65", "Template": "0ce8ab38-9258-4fbc-a62e-7faa6e58318f" }, + "cddlDefinitions": { + "blake2b_256": { + "def": "bytes .size 32", + "requires": [] + }, + "catalyst_id": { + "def": "text", + "requires": [] + }, + "collaborators": { + "def": "[ * catalyst_id ]", + "requires": [ + "catalyst_id" + ] + }, + "document_hash": { + "def": "blake2b_256", + "requires": [ + "blake2b_256" + ] + }, + "document_id": { + "def": "uuid_v7", + "requires": [ + "uuid_v7" + ] + }, + "document_ref": { + "def": "[ 1* [ document_id, document_ver, document_hash ] ]", + "requires": [ + "document_id", + "document_ver", + "document_hash" + ] + }, + "document_type": { + "def": "[ 1* uuid_v4 ]", + "requires": [ + "uuid_v4" + ] + }, + "document_ver": { + "def": "uuid_v7", + "requires": [ + "uuid_v7" + ] + }, + "json_pointer": { + "def": "text", + "requires": [] + }, + "section_ref": { + "def": "json_pointer", + "requires": [ + "json_pointer" + ] + }, + "uuid_v4": { + "def": "6.37(bytes .size 16)", + "requires": [] + }, + "uuid_v7": { + "def": "6.37(bytes .size 16)", + "requires": [] + } + }, "contentTypes": { "application/cbor": { - "description": "[RFC8949] Binary CBOR Encoded Document", - "linked": true + "description": "RFC8949 Binary CBOR Encoded Document" }, "application/cddl": { - "description": "[RFC8610] CBOR Document. Note: \n\t* This is an unofficial media type\n\t* [RFC9165] Additional Control Operators for CDDL are supported. \n\t* Must not have Modules, schema must be self contained.", - "linked": false + "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." }, "application/json": { - "description": "[RFC8259] JSON Document", - "linked": true + "description": "JSON Document" }, "application/schema+json": { - "description": "[JSON Schema] Draft 7 Document. Note: \n\t* This is currently an unofficial media type.\n\t* Draft 7 is used because of its wide support by tooling.", - "linked": true + "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." } }, + "copyright": { + "copyright": "IOG Singapore, All Rights Reserved", + "created": "2024-12-27", + "license": "CC-BY-4.0" + }, "cose_headers": { "content type": { "coseLabel": 3, @@ -79,72 +150,93 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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 `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -186,72 +278,93 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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 `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -293,72 +406,93 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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 `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -400,72 +534,93 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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 `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -509,72 +664,93 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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 `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -617,62 +793,81 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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", "multiple": false, "required": "yes", @@ -681,12 +876,14 @@ }, "type": { "description": "The document TYPE.", + "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { - "description": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -733,44 +930,60 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "multiple": false, "required": "yes", @@ -779,6 +992,7 @@ }, "reply": { "description": "Reference to a Comment document type being referred to.", + "exclusive": null, "format": "Document Reference", "multiple": false, "required": "optional", @@ -787,12 +1001,14 @@ }, "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", "multiple": false, "required": "yes", @@ -801,12 +1017,14 @@ }, "type": { "description": "The document TYPE.", + "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { - "description": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -853,74 +1071,95 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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 `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -972,62 +1211,81 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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", "multiple": false, "required": "optional", @@ -1036,12 +1294,14 @@ }, "type": { "description": "The document TYPE.", + "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { - "description": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1091,74 +1351,95 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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 `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1208,72 +1489,93 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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 `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1318,44 +1620,60 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "multiple": false, "required": "yes", "type": "Category Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "multiple": true, "required": "yes", @@ -1364,30 +1682,35 @@ }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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 `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1474,62 +1797,81 @@ "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `brand_id` must match the `brand_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "required": "excluded", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "required": "excluded", "validation": "Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document.\nThe calculated Hash of the Referenced Document **MUST** match the Hash in the reference. " }, "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 `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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", "multiple": false, "required": "optional", @@ -1538,12 +1880,14 @@ }, "type": { "description": "The document TYPE.", + "exclusive": null, "format": "Document Type", "required": "yes", "validation": "**MUST** be a known document type." }, "ver": { - "description": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "required": "yes", "validation": "The document version must always be >= the document ID." @@ -1593,8 +1937,7 @@ }, "encodingTypes": { "br": { - "description": "[BROTLI](RFC7932) Compression", - "linked": true + "description": "BROTLI Compression" } }, "linkAKA": { @@ -1609,12 +1952,16 @@ "URI": "RFC3986", "UTF-8": "RFC3629", "UUID": "RFC9562", - "UUIDv4": "RFC9562-V7", + "UUIDv4": "RFC9562-V4", "UUIDv7": "RFC9562-V7" }, "metadata": { "brand_id": { "description": "A reference to the Brand Parameters Document this document lies under.", + "exclusive": [ + "campaign_id", + "category_id" + ], "format": "Document Reference", "multiple": false, "required": "optional", @@ -1623,42 +1970,54 @@ }, "campaign_id": { "description": "A reference to the Campaign Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "category_id" + ], "format": "Document Reference", "multiple": false, "required": "optional", "type": "Campaign Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the `campaign_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `campaign_id` must match the \n`campaign_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "category_id": { "description": "A reference to the Category Parameters Document this document lies under.", + "exclusive": [ + "brand_id", + "campaign_id" + ], "format": "Document Reference", "multiple": false, "required": "optional", "type": "Category Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the `category_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `category_id` must match the \n`category_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced 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 new version of the document.", + "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." + "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." }, "election_id": { "description": "A reference to the Election Parameters Document this document lies under.", + "exclusive": null, "format": "Document Reference", "multiple": false, "required": "optional", "type": "Election Parameters", - "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the `election_id` \nof the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." + "validation": "In addition to the validation performed for `ref`, \nAny referenced document that includes a `election_id` must match the \n`election_id` of the referencing document.\nIt is also valid for the referenced document to not include this field, if it is \noptional for the referenced document." }, "id": { - "description": "Document ID, created the first time the document is created.", + "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": "UUIDv7", "required": "yes", - "validation": "IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist." + "validation": "IF `ver` does not == `id` then a document with \n`id` and `ver` being equal *MUST* exist." }, "ref": { - "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchial reference to a related document.\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the [UUIDv7] ID of the Document being referenced.\n* `DocumentVer` is the [UUIDv7] Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n\tIt ensures that the intended referenced document is the one used, and there has been no substitution.\n\tPrevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "description": "Reference to a Linked Document or Documents. \nThis is the primary hierarchical reference to a related document.\t\t\t\n\nThis is an Array of the format:\n\t`[[DocumentID, DocumentVer, DocumentHash],...]`\n\n* `DocumentID` is the UUIDv7 ID of the Document being referenced.\n* `DocumentVer` is the UUIDv7 Version of the Document being referenced.\n* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload.\n It ensures that the intended referenced document is the one used, and there has been no substitution.\n Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one.", + "exclusive": null, "format": "Document Reference", "multiple": false, "required": "optional", @@ -1681,67 +2040,77 @@ }, "reply": { "description": "Reference to a Comment document type being referred to.", + "exclusive": null, "format": "Document Reference", "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 Action Document", - "Brand Parameters", - "Campaign Parameters", - "Category Parameters", - "Election Parameters" + "Proposal Comment" ], "validation": "In addition to the validation performed for `ref`, \nThe `ref` of the `reply` document must be the same as\nthe original comment document." }, "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", "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 Action Document", - "Brand Parameters", - "Campaign Parameters", - "Category Parameters", - "Election Parameters" + "Proposal Comment Template" ], "validation": "In addition to the validation performed for `ref`, \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": "## Document Version\n\nThe 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`", + "exclusive": null, "format": "UUIDv7", "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 Reference": { + "cddl": "document_ref", + "description": "A document reference identifier" + }, + "Document Type": { + "cddl": "document_type", + "description": "A document type identifier" + }, + "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" + } + }, "metadata_order": [ "type", "id", diff --git a/specs/signed_docs/authors_copyright.cue b/specs/signed_docs/authors_copyright.cue new file mode 100644 index 0000000000..374fa251d6 --- /dev/null +++ b/specs/signed_docs/authors_copyright.cue @@ -0,0 +1,25 @@ +// Signed Document Definitions +// +// COSE Headers and Constraints +package signed_docs + +// List of authors, name: email +#authorList: { + [string]: string +} + +// General Authors List +authors: #authorList & { + "Steven Johnson": "steven.johnson@iohk.io" + "Alex Pozhylenkov": "alex.pozhylenkov@iohk.io" +} + +#copyrightNotice: { + created: string // YYYY-MM-DD + license: "CC-BY-4.0" + copyright: "IOG Singapore, All Rights Reserved" +} + +copyright: #copyrightNotice & { + created: "2024-12-27" +} diff --git a/specs/signed_docs/cddl_defs.cue b/specs/signed_docs/cddl_defs.cue new file mode 100644 index 0000000000..4a98360152 --- /dev/null +++ b/specs/signed_docs/cddl_defs.cue @@ -0,0 +1,64 @@ +// Signed Document Definitions +// +// CDDL Definitions +package signed_docs + +// List of cddl definitions, cddl_type_name: cddl_definition +#cddlDefinitions: { + [string]: { + def: string + requires: [...#cddlTypesConstraint] | *[] + } +} + +cddlDefinitions: #cddlDefinitions & { + "uuid_v7": { + def: "6.37(bytes .size 16)" + } + "uuid_v4": { + def: "6.37(bytes .size 16)" + } + "document_type": { + def: "[ 1* uuid_v4 ]" + requires: ["uuid_v4"] + } + "blake2b_256": { + def: "bytes .size 32" + } + "document_id": { + def: "uuid_v7" + requires: ["uuid_v7"] + } + "document_ver": { + def: "uuid_v7" + requires: ["uuid_v7"] + } + "document_hash": { + def: "blake2b_256" + requires: ["blake2b_256"] + } + "document_ref": { + def: "[ 1* [ document_id, document_ver, document_hash ] ]" + requires: ["document_id", "document_ver", "document_hash"] + } + "json_pointer": { + def: "text" + } + "section_ref": { + def: "json_pointer" + requires: ["json_pointer"] + } + "catalyst_id": { + def: "text" + } + "collaborators": { + def: "[ * catalyst_id ]" + requires: ["catalyst_id"] + } +} + +#cddlTypes: [ + for k, _ in cddlDefinitions {k}, +] + +#cddlTypesConstraint: or(#cddlTypes) diff --git a/specs/signed_docs/cose_headers.cue b/specs/signed_docs/cose_headers.cue index b6bae15879..5c0f32f43f 100644 --- a/specs/signed_docs/cose_headers.cue +++ b/specs/signed_docs/cose_headers.cue @@ -12,31 +12,29 @@ import ( // Content Type name : Description _contentTypes: { [string]: { - linked: bool | *true // content type has a link - description: string // description of the content type + description: string // description of the content type } } _contentTypes: { "application/json": { - description: "[RFC8259] JSON Document" + description: "JSON Document" } "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. + 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" + description: "RFC8949 Binary CBOR Encoded Document" } "application/cddl": { - linked: false description: """ - [RFC8610] CBOR 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. + 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. """ } } @@ -46,13 +44,12 @@ contentTypes: _contentTypes // Content Encoding Type name : Description _encodingTypes: { [string]: { - linked: bool | *true // content type has a link - description: string // description of the content type + description: string // description of the content type } } _encodingTypes: { "br": { - description: "[BROTLI](RFC7932) Compression" + description: "BROTLI Compression" } } diff --git a/specs/signed_docs/documentation_links.cue b/specs/signed_docs/documentation_links.cue index 7568d9e4fb..18c4469a4c 100644 --- a/specs/signed_docs/documentation_links.cue +++ b/specs/signed_docs/documentation_links.cue @@ -43,7 +43,7 @@ linkAKA: { // Known aliases for links. Lets us automatically create [Named Link][Reference Link] linkAKA: { "UUIDv7": "RFC9562-V7" - "UUIDv4": "RFC9562-V7" + "UUIDv4": "RFC9562-V4" "UUID": "RFC9562" "URI": "RFC3986" "UTF-8": "RFC3629" diff --git a/specs/signed_docs/metadata.cue b/specs/signed_docs/metadata.cue index 52c63c015b..e37c29cfd8 100644 --- a/specs/signed_docs/metadata.cue +++ b/specs/signed_docs/metadata.cue @@ -9,13 +9,57 @@ import ( ) +// Metadata Formats. +// format_name : cddl definition +#metadataFormats: { + [string]: { + description: string + cddl: #cddlTypesConstraint + } +} + +metadataFormats: #metadataFormats & { + "Document Reference": { + description: "A document reference identifier" + cddl: "document_ref" + } + "UUIDv7": { + description: "Version 7 formatted UUID" + cddl: "uuid_v7" + } + "UUIDv4": { + description: "Version 4 formatted UUID" + cddl: "uuid_v4" + } + "Document Type": { + description: "A document type identifier" + cddl: "document_type" + } + "Section Reference": { + description: "A document section reference identifier" + cddl: "section_ref" + } + "Collaborators Reference List": { + description: "A list of collaborators who can participate in drafting and submitting a document" + cddl: "collaborators" + } +} + +// Types of a Metadata Fields +#metadataTypes: [ + for k, _ in metadataFormats {k}, +] + +// Constraint of Types of Metadata Fields +#metadataTypesConstraint: or(#metadataTypes) + // Format of a Metadata Field -#metadataFormat: - "UUIDv7" | - "Document Type" | - *"Document Reference" | - "Section Reference" | - "Collaborators Reference List" +//#metadataFormat: +// "UUIDv7" | +// "Document Type" | +// *"Document Reference" | +// "Section Reference" | +// "Collaborators Reference List" // Canonical List of all valid metadata names _metadataNames: list.UniqueItems @@ -43,7 +87,7 @@ _allMetadataNames: or([ required: optional.#field // Format of the field. - format: #metadataFormat + format: #metadataTypesConstraint | *#metadataTypes[0] if format == "Document Reference" && required != "excluded" { type: #DocumentName | [...#DocumentName] multiple: bool | *false @@ -53,6 +97,9 @@ _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 @@ -71,11 +118,16 @@ _metadata: #metadataStruct & { } // Document ID id: { - required: "yes" - format: "UUIDv7" - description: "Document ID, created the first time the document is created." + required: "yes" + format: "UUIDv7" + description: """ + Document ID, created the first time the document is created. + This must be a properly created UUIDv7 which contains the + timestamp of when the document was created. + """ validation: """ - IF `ver` does not == `id` then a document with `id` and `ver` being equal *MUST* exist. + IF `ver` does not == `id` then a document with + `id` and `ver` being equal *MUST* exist. """ } // Document Version @@ -83,8 +135,6 @@ _metadata: #metadataStruct & { required: "yes" format: "UUIDv7" description: """ - ## Document Version - The unique version of the document. The first version of the document must set `ver` == `id` """ @@ -97,16 +147,16 @@ _metadata: #metadataStruct & { ref: { description: """ Reference to a Linked Document or Documents. - This is the primary hierarchial reference to a related document. + This is the primary hierarchical reference to a related document. This is an Array of the format: `[[DocumentID, DocumentVer, DocumentHash],...]` - * `DocumentID` is the [UUIDv7] ID of the Document being referenced. - * `DocumentVer` is the [UUIDv7] Version of the Document being referenced. + * `DocumentID` is the UUIDv7 ID of the Document being referenced. + * `DocumentVer` is the UUIDv7 Version of the Document being referenced. * `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload. - It ensures that the intended referenced document is the one used, and there has been no substitution. - Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one. + It ensures that the intended referenced document is the one used, and there has been no substitution. + Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one. """ validation: """ Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document. @@ -152,12 +202,12 @@ _metadata: #metadataStruct & { Every subsequent version can amend the collaborators list. However, the initial Author can never be removed from being able to - publish new version of the document. + publish a new version of the document. """ 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 + However, any document submission referencing a proposal MUST be signed by all collaborators in addition to the author. """ } @@ -171,25 +221,33 @@ _metadata: #metadataStruct & { It is also valid for the referenced document to not include this field, if it is optional for the referenced document. """ + exclusive: [ + "campaign_id", + "category_id", + ] } campaign_id: { description: "A reference to the Campaign Parameters Document this document lies under." validation: """ In addition to the validation performed for `ref`, - Any referenced document that includes a `campaign_id` must match the `campaign_id` - of the referencing document. + Any referenced document that includes a `campaign_id` must match the + `campaign_id` of the referencing document. It is also valid for the referenced document to not include this field, if it is optional for the referenced document. """ + exclusive: [ + "brand_id", + "category_id", + ] } election_id: { description: "A reference to the Election Parameters Document this document lies under." validation: """ In addition to the validation performed for `ref`, - Any referenced document that includes a `election_id` must match the `election_id` - of the referencing document. + Any referenced document that includes a `election_id` must match the + `election_id` of the referencing document. It is also valid for the referenced document to not include this field, if it is optional for the referenced document. """ @@ -199,11 +257,15 @@ _metadata: #metadataStruct & { description: "A reference to the Category Parameters Document this document lies under." validation: """ In addition to the validation performed for `ref`, - Any referenced document that includes a `category_id` must match the `category_id` - of the referencing document. + Any referenced document that includes a `category_id` must match the + `category_id` of the referencing document. It is also valid for the referenced document to not include this field, if it is optional for the referenced document. """ + exclusive: [ + "brand_id", + "campaign_id", + ] } } @@ -213,9 +275,9 @@ metadata: { ref: required: "optional" ref: type: _allDocNamesList template: required: "optional" - template: type: _allDocNamesList // TODO: Filter down to only Template Type Docs + template: type: #templateDocNamesList reply: required: "optional" - reply: type: _allDocNamesList // TODO: Filter down to only Comment Type Docs + reply: type: #commentDocNamesList section: required: "optional" collaborators: required: "optional" brand_id: required: "optional" diff --git a/specs/signed_docs/signed_doc.cue b/specs/signed_docs/signed_doc.cue index d2af79861c..c00731fe66 100644 --- a/specs/signed_docs/signed_doc.cue +++ b/specs/signed_docs/signed_doc.cue @@ -5,6 +5,7 @@ package signed_docs import ( "list" + "strings" "github.com/input-output-hk/catalyst-libs/specs/generic:uuid" ) @@ -75,6 +76,21 @@ _allDocNamesList: [...string] & [ for k, _ in _allDocs {k}, ] +// List of all Comment Docs (not templates or actions) +#commentDocNamesList: [...string] & [ + for k, _ in _allDocs + if strings.Contains(k, "Comment") && + !strings.Contains(k, "Template") && + !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) From 52cf095f7f5771d4c92c77c657e3a21b2aaf6af2 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Tue, 18 Mar 2025 11:06:39 +0700 Subject: [PATCH 25/35] feat(docs): Add start of individual documentation pages for each signed document defined --- specs/Justfile | 4 +- specs/gen_docs/gen_docs_page_md.py | 39 ++++++++++++++ .../{gen_doc_pages.py => generate_docs.py} | 30 +++++------ specs/gen_docs/test/docs/brand_parameters.md | 40 ++++++++++++++ .../gen_docs/test/docs/campaign_parameters.md | 40 ++++++++++++++ .../gen_docs/test/docs/category_parameters.md | 40 ++++++++++++++ .../test/docs/comment_action_document.md | 40 ++++++++++++++ .../gen_docs/test/docs/election_parameters.md | 40 ++++++++++++++ specs/gen_docs/test/docs/proposal.md | 49 +++++++++++++++++ specs/gen_docs/test/docs/proposal_comment.md | 47 ++++++++++++++++ .../docs/proposal_comment_meta_template.md | 45 ++++++++++++++++ .../test/docs/proposal_comment_template.md | 48 +++++++++++++++++ .../test/docs/proposal_meta_template.md | 45 ++++++++++++++++ .../test/docs/proposal_moderation_action.md | 40 ++++++++++++++ .../test/docs/proposal_submission_action.md | 54 +++++++++++++++++++ specs/gen_docs/test/docs/proposal_template.md | 48 +++++++++++++++++ specs/signed_doc.json | 17 +++++- specs/signed_docs/authors_copyright.cue | 5 ++ specs/signed_docs/docs/proposal.cue | 6 ++- specs/signed_docs/signed_doc.cue | 8 +++ 20 files changed, 664 insertions(+), 21 deletions(-) create mode 100644 specs/gen_docs/gen_docs_page_md.py rename specs/gen_docs/{gen_doc_pages.py => generate_docs.py} (92%) create mode 100644 specs/gen_docs/test/docs/brand_parameters.md create mode 100644 specs/gen_docs/test/docs/campaign_parameters.md create mode 100644 specs/gen_docs/test/docs/category_parameters.md create mode 100644 specs/gen_docs/test/docs/comment_action_document.md create mode 100644 specs/gen_docs/test/docs/election_parameters.md create mode 100644 specs/gen_docs/test/docs/proposal.md create mode 100644 specs/gen_docs/test/docs/proposal_comment.md create mode 100644 specs/gen_docs/test/docs/proposal_comment_meta_template.md create mode 100644 specs/gen_docs/test/docs/proposal_comment_template.md create mode 100644 specs/gen_docs/test/docs/proposal_meta_template.md create mode 100644 specs/gen_docs/test/docs/proposal_moderation_action.md create mode 100644 specs/gen_docs/test/docs/proposal_submission_action.md create mode 100644 specs/gen_docs/test/docs/proposal_template.md diff --git a/specs/Justfile b/specs/Justfile index d56566b44d..e693b0e2f9 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -21,9 +21,9 @@ regenerate: check # 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 # Generate the markdown docs from the specification. - cd gen_docs; ./gen_doc_pages.py -g -o test ../signed_doc.json + cd gen_docs; ./generate_docs.py -g -o test ../signed_doc.json # Check our validation code actually works properly - cd gen_docs; ./gen_doc_pages.py -o test ../signed_doc.json + cd gen_docs; ./generate_docs.py -o test ../signed_doc.json # Validate the generated signed_docs.json is correct against the cue schema. diff --git a/specs/gen_docs/gen_docs_page_md.py b/specs/gen_docs/gen_docs_page_md.py new file mode 100644 index 0000000000..09c077c0ce --- /dev/null +++ b/specs/gen_docs/gen_docs_page_md.py @@ -0,0 +1,39 @@ +# Generate the spec.md file +from common import insert_copyright + + +def gen_docs_page_md(name: str, doc_defs: dict) -> str: + """ + Generate an individual Documents Specification Page file from the definitions. + """ + return f""" +# {name} + +## Description + +{doc_defs["docs"][name].get("description", "TODO")} + +### Validation + +{doc_defs["docs"][name].get("validation", "TODO")} + +### Business Logic + +#### Front End + +{doc_defs["docs"][name].get("business_logic", {}).get("front_end", "TODO")} + +#### Back End + +{doc_defs["docs"][name].get("business_logic", {}).get("back_end", "TODO")} + +## COSE Header Parameters + +## Metadata + +## Payload + +## Signers + +{insert_copyright(doc_defs)} +""" diff --git a/specs/gen_docs/gen_doc_pages.py b/specs/gen_docs/generate_docs.py similarity index 92% rename from specs/gen_docs/gen_doc_pages.py rename to specs/gen_docs/generate_docs.py index 3f144f0b20..44564e639d 100755 --- a/specs/gen_docs/gen_doc_pages.py +++ b/specs/gen_docs/generate_docs.py @@ -8,6 +8,7 @@ from pathlib import Path from common import metadata_field_link +from gen_docs_page_md import gen_docs_page_md from gen_metadata_md import gen_metadata_md from gen_spec_index import gen_spec_index from gen_spec_md import gen_spec_md @@ -154,8 +155,8 @@ def save_or_validate( old_contents = md_file.read_text() if old_contents == file_data: print(f"{file_name} is already up-to-date.") - else: - md_file.write_text(file_data) + return True + md_file.write_text(file_data) else: print(f"Validating {file_name}") if not md_file.exists(): @@ -173,23 +174,20 @@ def create_individual_doc_files(docs: dict, args: argparse.Namespace) -> bool: """ Create Individual markdown files for all document types. """ - - docs = get_signed_doc_data() all_docs = docs["docs"] + good = True + for doc_name in all_docs: - file_name = doc_name.lower().replace(" ", "_") + ".md" - print(f"{doc_name} : {file_name}") + file_name = "docs/" + doc_name.lower().replace(" ", "_") + ".md" + good &= save_or_validate( + file_name, + lambda docs: gen_docs_page_md(doc_name, docs), + args, + docs, + ) - doc_path = Path("docs", file_name) - if doc_path.is_file(): - print("Exists") - else: - new_doc_contents = '# {{{{ insert_signed_doc_details( "{}" ) }}}}\n'.format( - doc_name - ) - doc_path.write_text(new_doc_contents) - print("Created") + return good def check_is_dir(base_path: Path) -> bool: @@ -252,7 +250,7 @@ def init_parser() -> argparse.Namespace: good &= save_or_validate("spec.md", gen_spec_md, args, docs) good &= save_or_validate("types.md", gen_types_md, args, docs) good &= save_or_validate("metadata.md", gen_metadata_md, args, docs) - # good &= create_individual_doc_files(docs, args) + good &= create_individual_doc_files(docs, args) if not good: print("File Comparisons Failed, Documentation is not current.") diff --git a/specs/gen_docs/test/docs/brand_parameters.md b/specs/gen_docs/test/docs/brand_parameters.md new file mode 100644 index 0000000000..9066fcab16 --- /dev/null +++ b/specs/gen_docs/test/docs/brand_parameters.md @@ -0,0 +1,40 @@ +# Brand Parameters + +## Description + +TODO + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/campaign_parameters.md b/specs/gen_docs/test/docs/campaign_parameters.md new file mode 100644 index 0000000000..7c039c2e2b --- /dev/null +++ b/specs/gen_docs/test/docs/campaign_parameters.md @@ -0,0 +1,40 @@ +# Campaign Parameters + +## Description + +TODO + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/category_parameters.md b/specs/gen_docs/test/docs/category_parameters.md new file mode 100644 index 0000000000..5a4aba221b --- /dev/null +++ b/specs/gen_docs/test/docs/category_parameters.md @@ -0,0 +1,40 @@ +# Category Parameters + +## Description + +TODO + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/comment_action_document.md b/specs/gen_docs/test/docs/comment_action_document.md new file mode 100644 index 0000000000..d5604e8a5e --- /dev/null +++ b/specs/gen_docs/test/docs/comment_action_document.md @@ -0,0 +1,40 @@ +# Comment Action Document + +## Description + +TODO + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/election_parameters.md b/specs/gen_docs/test/docs/election_parameters.md new file mode 100644 index 0000000000..d6cfcda76c --- /dev/null +++ b/specs/gen_docs/test/docs/election_parameters.md @@ -0,0 +1,40 @@ +# Election Parameters + +## Description + +TODO + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/proposal.md b/specs/gen_docs/test/docs/proposal.md new file mode 100644 index 0000000000..b35efaed0f --- /dev/null +++ b/specs/gen_docs/test/docs/proposal.md @@ -0,0 +1,49 @@ +# Proposal + +## Description + +A Proposal is a document which describes a proposed solution or project to +address the criteria of a category within a campaign. + +The proposal itself is a draft document, it is not submitted for consideration +unless a `Proposal Submission Action` is submitted which references it. + +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. + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/proposal_comment.md b/specs/gen_docs/test/docs/proposal_comment.md new file mode 100644 index 0000000000..8ae10a262c --- /dev/null +++ b/specs/gen_docs/test/docs/proposal_comment.md @@ -0,0 +1,47 @@ +# Proposal Comment + +## Description + +## Proposal Comment Document + +A Proposal Comment is a document which comments on a referenced Proposal document. + +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. + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/proposal_comment_meta_template.md b/specs/gen_docs/test/docs/proposal_comment_meta_template.md new file mode 100644 index 0000000000..12249717fd --- /dev/null +++ b/specs/gen_docs/test/docs/proposal_comment_meta_template.md @@ -0,0 +1,45 @@ +# 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. + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/proposal_comment_template.md b/specs/gen_docs/test/docs/proposal_comment_template.md new file mode 100644 index 0000000000..f32adbe56b --- /dev/null +++ b/specs/gen_docs/test/docs/proposal_comment_template.md @@ -0,0 +1,48 @@ +# 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. + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/proposal_meta_template.md b/specs/gen_docs/test/docs/proposal_meta_template.md new file mode 100644 index 0000000000..c23c5978d0 --- /dev/null +++ b/specs/gen_docs/test/docs/proposal_meta_template.md @@ -0,0 +1,45 @@ +# 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. + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/proposal_moderation_action.md b/specs/gen_docs/test/docs/proposal_moderation_action.md new file mode 100644 index 0000000000..8c76a729e2 --- /dev/null +++ b/specs/gen_docs/test/docs/proposal_moderation_action.md @@ -0,0 +1,40 @@ +# Proposal Moderation Action + +## Description + +TODO + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/proposal_submission_action.md b/specs/gen_docs/test/docs/proposal_submission_action.md new file mode 100644 index 0000000000..3acf24c143 --- /dev/null +++ b/specs/gen_docs/test/docs/proposal_submission_action.md @@ -0,0 +1,54 @@ +# Proposal Submission Action + +## Description + +## 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. + +The last action on the document ts the action which takes effect at the deadline. + +For multiple collaborators, multiple submission actions can be posted independently, +but none of them will take effect until ALL collaborators have posted equivalent actions. + +For example, three collaborators Alice/Bob/Claire can each post one submission action +for the same document. Unless they all submit or withdraw the same version of the proposal +the proposal will not be seen as submitted or withdrawn. + +The payload is a fixed format. + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/gen_docs/test/docs/proposal_template.md b/specs/gen_docs/test/docs/proposal_template.md new file mode 100644 index 0000000000..9b4d4d6aa2 --- /dev/null +++ b/specs/gen_docs/test/docs/proposal_template.md @@ -0,0 +1,48 @@ +# 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. + +### Validation + +TODO + +### Business Logic + +#### Front End + +TODO + +#### Back End + +TODO + +## [COSE Header Parameters][RFC9052-HeaderParameters] + +## Metadata + +## Payload + +## Signers + +## 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-03-12 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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/specs/signed_doc.json b/specs/signed_doc.json index 4280b4d744..c6e097e458 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -129,6 +129,7 @@ ], "docs": { "Brand Parameters": { + "authors": {}, "headers": { "content type": { "coseLabel": 3, @@ -257,6 +258,7 @@ ] }, "Campaign Parameters": { + "authors": {}, "headers": { "content type": { "coseLabel": 3, @@ -385,6 +387,7 @@ ] }, "Category Parameters": { + "authors": {}, "headers": { "content type": { "coseLabel": 3, @@ -513,6 +516,7 @@ ] }, "Comment Action Document": { + "authors": {}, "headers": { "content type": { "coseLabel": 3, @@ -643,6 +647,7 @@ ] }, "Election Parameters": { + "authors": {}, "headers": { "content type": { "coseLabel": 3, @@ -771,7 +776,10 @@ ] }, "Proposal": { - "description": "## Proposal Document\n\nA Proposal is a document which describes a proposed solution or project to\naddress the criteria of a category within a campaign.\n\nThe proposal itself is a draft document, it is not submitted for consideration\nunless a `Proposal Submission Action` is submitted which references it.\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.", + "authors": { + "Steven Johnson": "steven.johnson@iohk.io" + }, + "description": "A Proposal is a document which describes a proposed solution or project to\naddress the criteria of a category within a campaign.\n\nThe proposal itself is a draft document, it is not submitted for consideration\nunless a `Proposal Submission Action` is submitted which references it.\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.", "headers": { "content type": { "coseLabel": 3, @@ -908,6 +916,7 @@ ] }, "Proposal Comment": { + "authors": {}, "description": "## Proposal Comment Document\n\nA Proposal Comment is a document which comments on a referenced Proposal document.\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.", "headers": { "content type": { @@ -1049,6 +1058,7 @@ ] }, "Proposal Comment Meta 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.", "headers": { "content type": { @@ -1189,6 +1199,7 @@ ] }, "Proposal Comment 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.", "headers": { "content type": { @@ -1329,6 +1340,7 @@ ] }, "Proposal Meta 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.", "headers": { "content type": { @@ -1468,6 +1480,7 @@ ] }, "Proposal Moderation Action": { + "authors": {}, "headers": { "content type": { "coseLabel": 3, @@ -1598,6 +1611,7 @@ ] }, "Proposal Submission Action": { + "authors": {}, "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. Unless they all submit or withdraw the same version of the proposal\nthe proposal will not be seen as submitted or withdrawn.\n\nThe payload is a fixed format.", "headers": { "content type": { @@ -1775,6 +1789,7 @@ ] }, "Proposal Template": { + "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.", "headers": { "content type": { diff --git a/specs/signed_docs/authors_copyright.cue b/specs/signed_docs/authors_copyright.cue index 374fa251d6..4ebf92369c 100644 --- a/specs/signed_docs/authors_copyright.cue +++ b/specs/signed_docs/authors_copyright.cue @@ -8,6 +8,11 @@ package signed_docs [string]: string } +// +#authorMinConstraint: { + +} + // General Authors List authors: #authorList & { "Steven Johnson": "steven.johnson@iohk.io" diff --git a/specs/signed_docs/docs/proposal.cue b/specs/signed_docs/docs/proposal.cue index 8ae320d3ae..7531260e15 100644 --- a/specs/signed_docs/docs/proposal.cue +++ b/specs/signed_docs/docs/proposal.cue @@ -5,8 +5,6 @@ package signed_docs docs: #DocumentDefinitions & { "Proposal": { description: """ - ## Proposal Document - A Proposal is a document which describes a proposed solution or project to address the criteria of a category within a campaign. @@ -54,5 +52,9 @@ docs: #DocumentDefinitions & { "collaborators": true } } + + authors: { + "Steven Johnson": "steven.johnson@iohk.io" + } } } diff --git a/specs/signed_docs/signed_doc.cue b/specs/signed_docs/signed_doc.cue index c00731fe66..f6465e1eff 100644 --- a/specs/signed_docs/signed_doc.cue +++ b/specs/signed_docs/signed_doc.cue @@ -26,6 +26,12 @@ import ( // The description of this document. Markdown Supported. validation?: string + // The business logic related to this document. Markdown Supported. + business_logic?: { + front_end?: string + back_end?: string + } + // Fixed headers in every document headers: _coseHeaders @@ -37,6 +43,8 @@ import ( // Required/Allowed Signers of a document signers: _allowedSigners + + authors: #authorList } // We can only define known documents in the document definitions object From 4d1e132cce83ba3cfbdf839aa070f765c8e970e8 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Tue, 1 Apr 2025 23:51:57 +0700 Subject: [PATCH 26/35] feat: individual document specifications now generated --- specs/gen_docs/common.py | 42 ++++- specs/gen_docs/gen_docs_page_md.py | 92 +++++++++- specs/gen_docs/gen_types_md.py | 2 +- specs/gen_docs/generate_docs.py | 1 + specs/gen_docs/test/docs/brand_parameters.md | 60 ++++++- .../gen_docs/test/docs/campaign_parameters.md | 60 ++++++- .../gen_docs/test/docs/category_parameters.md | 60 ++++++- .../test/docs/comment_action_document.md | 60 ++++++- .../gen_docs/test/docs/election_parameters.md | 60 ++++++- specs/gen_docs/test/docs/proposal.md | 119 ++++++++++++- specs/gen_docs/test/docs/proposal_comment.md | 151 +++++++++++++++- .../docs/proposal_comment_meta_template.md | 88 +++++++++- .../test/docs/proposal_comment_template.md | 97 ++++++++++- .../test/docs/proposal_meta_template.md | 88 +++++++++- .../test/docs/proposal_moderation_action.md | 60 ++++++- .../test/docs/proposal_submission_action.md | 164 +++++++++++++++++- specs/gen_docs/test/docs/proposal_template.md | 97 ++++++++++- specs/gen_docs/test/metadata.md | 94 +++++----- specs/gen_docs/test/spec.md | 2 +- specs/gen_docs/test/types.md | 28 +-- specs/signed_doc.json | 18 +- specs/signed_docs/authors_copyright.cue | 4 +- .../docs/proposal_comment_meta_template.cue | 4 +- .../docs/proposal_comment_template.cue | 4 +- .../docs/proposal_meta_template.cue | 4 +- .../docs/proposal_submission_action.cue | 5 +- specs/signed_docs/docs/proposal_template.cue | 4 +- specs/signed_docs/payload.cue | 2 +- specs/signed_docs/signers.cue | 16 +- 29 files changed, 1371 insertions(+), 115 deletions(-) diff --git a/specs/gen_docs/common.py b/specs/gen_docs/common.py index d0a024bb34..96054420e7 100644 --- a/specs/gen_docs/common.py +++ b/specs/gen_docs/common.py @@ -62,7 +62,22 @@ def metadata_format_link(name: str, depth: int = 0): while depth > 0: link = f"../{link}" - link -= 1 + depth -= 1 + + return f"[{name}]({link})" + +def metadata_doc_ref_link(name: str, depth: int = 0): + """ + Metadata Document Reference link. + """ + link = name.lower().replace(" ","_")+".md" + + if depth == 0: + link = f"./docs/{link}" + else: + while depth > 1: + link = f"../{link}" + depth -= 1 return f"[{name}]({link})" @@ -75,7 +90,7 @@ def metadata_field_link(name: str, depth: int = 0): while depth > 0: link = f"../{link}" - link -= 1 + depth -= 1 return f"[`{name}`]({link})" @@ -100,9 +115,14 @@ def metadata_fields(doc_data: dict, doc_name: str = None, depth: int = 0): field_display = "" for field_name in order: field = fields[field_name] + # Don't display excluded fields in the docs for individual doc pages + if doc_name is not None: + if field["required"] == "excluded": + continue + field_display += f""" {field_title_level} `{field_name}` - + | Parameter | Value | | --- | --- | | Required | {field["required"]} | @@ -113,6 +133,18 @@ def metadata_fields(doc_data: dict, doc_name: str = None, depth: int = 0): field_display += ( f"| Format | {metadata_format_link(field['format'], depth)} |\n" ) + + if doc_name is not None: + if field_name == "type": + # Display the actual documents type values + monospace_types = [] + for type in doc_data["docs"][doc_name]["type"]: + monospace_types.append(f"`{type}`") + field_display += ( + f"| Type | {',
'.join(monospace_types)} |\n" + ) + + if field.get("multiple", False): field_display += f"| Multiple References | {field['multiple']} |\n" if "type" in field: @@ -121,7 +153,7 @@ def metadata_fields(doc_data: dict, doc_name: str = None, depth: int = 0): if isinstance(ref_doc_names, str): ref_doc_names = [ref_doc_names] for ref_doc in ref_doc_names: - field_display += f"| {ref_heading} | {ref_doc} |\n" + field_display += f"| {ref_heading} | {metadata_doc_ref_link(ref_doc,depth)} |\n" ref_heading = "" exclusive = field.get("exclusive", None) if exclusive is not None: @@ -130,7 +162,7 @@ def metadata_fields(doc_data: dict, doc_name: str = None, depth: int = 0): field_display += f"| {exclusive_title} | {ref} |\n" exclusive_title = "" - field_display += f""" + field_display += f""" {field["description"]} {field_title_level}# Validation diff --git a/specs/gen_docs/gen_docs_page_md.py b/specs/gen_docs/gen_docs_page_md.py index 09c077c0ce..e7e4d31d22 100644 --- a/specs/gen_docs/gen_docs_page_md.py +++ b/specs/gen_docs/gen_docs_page_md.py @@ -1,6 +1,88 @@ # Generate the spec.md file -from common import insert_copyright +from common import insert_copyright, metadata_fields +from urllib.parse import urlparse +import json + +def header_parameter_summary(name, doc_defs: dict) -> str: + """ + Generate concrete Cose header parameter settings for a specific document. + """ + headers = doc_defs["docs"][name]["headers"] + header_docs = "" + for header in headers: + value = headers[header]["value"] + if isinstance(value, list): + value = f"[{','.join(value)}]" + link = f"../spec.md#{header.replace(' ', '-')}" + header_docs += f"* [{header}]({link}) = `{value}`\n" + return header_docs.strip() + + +def metadata_summary(name, doc_defs: dict) -> str: + """ + Generate concrete Metadata summary for a specific document. + """ + return metadata_fields(doc_defs, name, depth=1) + +def uri_validator(uri : str): + try: + result = urlparse(uri) + return all([result.scheme in ["http","https"], result.netloc]) + except Exception as _e: + return False + +def document_payload(name: str,doc_defs: dict) -> str: + """ + Generate Payload Documentation + """ + if "payload" not in doc_defs["docs"][name]: + return "TODO" + + payload = doc_defs["docs"][name]["payload"] + + payload_docs = payload["description"]+"\n" + + if "schema" in payload: + schema = payload["schema"] + if uri_validator(schema): + 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() + +def document_signers(name:str, doc_defs: dict) -> str: + """ + Generate documentation about who may sign this document.s + """ + signers = doc_defs["docs"][name]["signers"] + signers_doc = "" + + 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" + for role in roles: + signers_doc += f"* {role}\n" + + 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]: + signers_doc += f"* {updater}\n" + + return signers_doc.strip() def gen_docs_page_md(name: str, doc_defs: dict) -> str: """ @@ -29,11 +111,19 @@ def gen_docs_page_md(name: str, doc_defs: dict) -> str: ## COSE Header Parameters +{header_parameter_summary(name, doc_defs)} + ## Metadata +{metadata_summary(name, doc_defs)} + ## Payload +{document_payload(name,doc_defs)} + ## Signers +{document_signers(name,doc_defs)} + {insert_copyright(doc_defs)} """ diff --git a/specs/gen_docs/gen_types_md.py b/specs/gen_docs/gen_types_md.py index 8ffe826e87..3079ce811b 100644 --- a/specs/gen_docs/gen_types_md.py +++ b/specs/gen_docs/gen_types_md.py @@ -10,7 +10,7 @@ def name_to_spec_link(name, ref=None): """ Create a link to a document type, and an optional ref inside the document. """ - link = "./../catalyst_docs/" + name.lower().replace(" ", "_") + ".md" + link = "./docs/" + name.lower().replace(" ", "_") + ".md" if ref is not None: link += f"#{ref}" return link diff --git a/specs/gen_docs/generate_docs.py b/specs/gen_docs/generate_docs.py index 44564e639d..8246f4d77b 100755 --- a/specs/gen_docs/generate_docs.py +++ b/specs/gen_docs/generate_docs.py @@ -185,6 +185,7 @@ def create_individual_doc_files(docs: dict, args: argparse.Namespace) -> bool: lambda docs: gen_docs_page_md(doc_name, docs), args, docs, + depth=1 ) return good diff --git a/specs/gen_docs/test/docs/brand_parameters.md b/specs/gen_docs/test/docs/brand_parameters.md index 9066fcab16..1144c71133 100644 --- a/specs/gen_docs/test/docs/brand_parameters.md +++ b/specs/gen_docs/test/docs/brand_parameters.md @@ -20,21 +20,79 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `ebcabeeb-5bc5-4f95-91e8-cab8ca724172` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + ## Payload +TODO + ## 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [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/specs/gen_docs/test/docs/campaign_parameters.md b/specs/gen_docs/test/docs/campaign_parameters.md index 7c039c2e2b..00a36b7b0e 100644 --- a/specs/gen_docs/test/docs/campaign_parameters.md +++ b/specs/gen_docs/test/docs/campaign_parameters.md @@ -20,21 +20,79 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `5ef32d5d-f240-462c-a7a4-ba4af221fa23` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + ## Payload +TODO + ## 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [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/specs/gen_docs/test/docs/category_parameters.md b/specs/gen_docs/test/docs/category_parameters.md index 5a4aba221b..60f04f182a 100644 --- a/specs/gen_docs/test/docs/category_parameters.md +++ b/specs/gen_docs/test/docs/category_parameters.md @@ -20,21 +20,79 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `818938c3-3139-4daa-afe6-974c78488e95` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + ## Payload +TODO + ## 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [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/specs/gen_docs/test/docs/comment_action_document.md b/specs/gen_docs/test/docs/comment_action_document.md index d5604e8a5e..903b8e2ae8 100644 --- a/specs/gen_docs/test/docs/comment_action_document.md +++ b/specs/gen_docs/test/docs/comment_action_document.md @@ -20,21 +20,79 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `5e60e623-ad02-4a1b-a1ac-406db978ee48`,
`b679ded3-0e7c-41ba-89f8-da62a17898ea`,
`a5d232b8-5e03-4117-9afd-be32b878fcdd` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + ## Payload +TODO + ## 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [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/specs/gen_docs/test/docs/election_parameters.md b/specs/gen_docs/test/docs/election_parameters.md index d6cfcda76c..a88236b621 100644 --- a/specs/gen_docs/test/docs/election_parameters.md +++ b/specs/gen_docs/test/docs/election_parameters.md @@ -20,21 +20,79 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `788ff4c6-d65a-451f-bb33-575fe056b411` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + ## Payload +TODO + ## 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [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/specs/gen_docs/test/docs/proposal.md b/specs/gen_docs/test/docs/proposal.md index b35efaed0f..d660ecac1c 100644 --- a/specs/gen_docs/test/docs/proposal.md +++ b/specs/gen_docs/test/docs/proposal.md @@ -29,21 +29,138 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `7808d2ba-d511-40af-84e8-c0d1625fdfdc` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + +### `template` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Proposal Template](proposal_template.md) | + +Reference to the template used to create and/or validate this document. + +#### Validation + +In addition to the validation performed for `ref`, +The document payload is not valid if it does not validate completely against the referenced template. + +### `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. + +#### 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. + +### `category_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Category Parameters](category_parameters.md) | +| Exclusive | brand_id | +| | campaign_id | + +A reference to the Category Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`category_id`](../metadata.md#category_id) must match the +[`category_id`](../metadata.md#category_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + ## Payload +Proposal Document drafted for submission to a category of a campaign. + +Must be valid according to the schema of the referenced Template. + ## Signers +The following user roles may sign documents of this type: + +* Proposer + +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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [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/specs/gen_docs/test/docs/proposal_comment.md b/specs/gen_docs/test/docs/proposal_comment.md index 8ae10a262c..e764d4bc5a 100644 --- a/specs/gen_docs/test/docs/proposal_comment.md +++ b/specs/gen_docs/test/docs/proposal_comment.md @@ -27,21 +27,170 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `b679ded3-0e7c-41ba-89f8-da62a17898ea`,
`7808d2ba-d511-40af-84e8-c0d1625fdfdc` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + +### `ref` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Proposal](proposal.md) | + +Reference to a Linked Document or Documents. +This is the primary hierarchical reference to a related document. + +This is an Array of the format: + `[[DocumentID, DocumentVer, DocumentHash],...]` + +* `DocumentID` is the [UUIDv7][RFC9562-V7] ID of the Document being referenced. +* `DocumentVer` is the [UUIDv7][RFC9562-V7] Version of the Document being referenced. +* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload. + It ensures that the intended referenced document is the one used, and there has been no substitution. + Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one. + +#### Validation + +Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document. +The calculated Hash of the Referenced Document **MUST** match the Hash in the reference. + +### `template` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Proposal Comment Template](proposal_comment_template.md) | + +Reference to the template used to create and/or validate this document. + +#### Validation + +In addition to the validation performed for `ref`, +The document payload is not valid if it does not validate completely against the referenced template. + +### `reply` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Proposal Comment](proposal_comment.md) | + +Reference to a Comment document type being referred to. + +#### Validation + +In addition to the validation performed for `ref`, +The [`ref`](../metadata.md#ref) of the [`reply`](../metadata.md#reply) document must be the same as +the original comment document. + +### `section` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Section Reference](../metadata.md#section-reference) | + +A Reference to the original document, or the comment being replied to. + +#### Validation + +For a non-reply this must be a valid section reference into the referenced document. +For a reply, this must be a valid section reference into the comment being replied to. + +### `category_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Category Parameters](category_parameters.md) | +| Exclusive | brand_id | +| | campaign_id | + +A reference to the Category Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`category_id`](../metadata.md#category_id) must match the +[`category_id`](../metadata.md#category_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + ## Payload +[JSON][RFC8259] Document which must validate against the referenced template. + ## 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [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 +[RFC8259]: https://www.rfc-editor.org/rfc/rfc8259.html diff --git a/specs/gen_docs/test/docs/proposal_comment_meta_template.md b/specs/gen_docs/test/docs/proposal_comment_meta_template.md index 12249717fd..267ec5ce26 100644 --- a/specs/gen_docs/test/docs/proposal_comment_meta_template.md +++ b/specs/gen_docs/test/docs/proposal_comment_meta_template.md @@ -25,21 +25,107 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/schema+json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| 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` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + +### `category_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Category Parameters](category_parameters.md) | +| Exclusive | brand_id | +| | campaign_id | + +A reference to the Category Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`category_id`](../metadata.md#category_id) must match the +[`category_id`](../metadata.md#category_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + ## Payload +[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. + +**Must be a valid [JSON Schema] Draft 7 document.** + ## Signers +The following admin roles may sign documents of this type: + +* Root Admin +* 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema]: https://json-schema.org/draft-07 [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/specs/gen_docs/test/docs/proposal_comment_template.md b/specs/gen_docs/test/docs/proposal_comment_template.md index f32adbe56b..8643dcbd0d 100644 --- a/specs/gen_docs/test/docs/proposal_comment_template.md +++ b/specs/gen_docs/test/docs/proposal_comment_template.md @@ -28,21 +28,116 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/schema+json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`b679ded3-0e7c-41ba-89f8-da62a17898ea`,
`7808d2ba-d511-40af-84e8-c0d1625fdfdc` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + +### `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. + +#### Validation + +In addition to the validation performed for `ref`, +The document payload is not valid if it does not validate completely against the referenced template. + +### `category_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Category Parameters](category_parameters.md) | +| Exclusive | brand_id | +| | campaign_id | + +A reference to the Category Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`category_id`](../metadata.md#category_id) must match the +[`category_id`](../metadata.md#category_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + ## Payload +[JSON Schema] document which defines the content of the Proposal Comments. + ## Signers +The following admin roles may sign documents of this type: + +* Brand Admin +* Campaign 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema]: https://json-schema.org/draft-07 [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/specs/gen_docs/test/docs/proposal_meta_template.md b/specs/gen_docs/test/docs/proposal_meta_template.md index c23c5978d0..5b09004454 100644 --- a/specs/gen_docs/test/docs/proposal_meta_template.md +++ b/specs/gen_docs/test/docs/proposal_meta_template.md @@ -25,21 +25,107 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/schema+json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| 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` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + +### `category_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Category Parameters](category_parameters.md) | +| Exclusive | brand_id | +| | campaign_id | + +A reference to the Category Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`category_id`](../metadata.md#category_id) must match the +[`category_id`](../metadata.md#category_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + ## Payload +[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. + +**Must be a valid [JSON Schema] Draft 7 document.** + ## Signers +The following admin roles may sign documents of this type: + +* Root Admin +* 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema]: https://json-schema.org/draft-07 [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/specs/gen_docs/test/docs/proposal_moderation_action.md b/specs/gen_docs/test/docs/proposal_moderation_action.md index 8c76a729e2..aedc780a02 100644 --- a/specs/gen_docs/test/docs/proposal_moderation_action.md +++ b/specs/gen_docs/test/docs/proposal_moderation_action.md @@ -20,21 +20,79 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `5e60e623-ad02-4a1b-a1ac-406db978ee48`,
`7808d2ba-d511-40af-84e8-c0d1625fdfdc`,
`a5d232b8-5e03-4117-9afd-be32b878fcdd` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + ## Payload +TODO + ## 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [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/specs/gen_docs/test/docs/proposal_submission_action.md b/specs/gen_docs/test/docs/proposal_submission_action.md index 3acf24c143..d50aa63b50 100644 --- a/specs/gen_docs/test/docs/proposal_submission_action.md +++ b/specs/gen_docs/test/docs/proposal_submission_action.md @@ -13,8 +13,9 @@ For multiple collaborators, multiple submission actions can be posted independen but none of them will take effect until ALL collaborators have posted equivalent actions. For example, three collaborators Alice/Bob/Claire can each post one submission action -for the same document. Unless they all submit or withdraw the same version of the proposal -the proposal will not be seen as submitted or withdrawn. +for the same document. +Unless they all submit the same version of the proposal +the proposal will not be seen as submitted. The payload is a fixed format. @@ -34,21 +35,178 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `5e60e623-ad02-4a1b-a1ac-406db978ee48`,
`7808d2ba-d511-40af-84e8-c0d1625fdfdc`,
`78927329-cfd9-4ea1-9c71-0e019b126a65` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + +### `ref` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Multiple References | True | +| Valid References | [Proposal](proposal.md) | + +Reference to a Linked Document or Documents. +This is the primary hierarchical reference to a related document. + +This is an Array of the format: + `[[DocumentID, DocumentVer, DocumentHash],...]` + +* `DocumentID` is the [UUIDv7][RFC9562-V7] ID of the Document being referenced. +* `DocumentVer` is the [UUIDv7][RFC9562-V7] Version of the Document being referenced. +* `DocumentHash` is the Blake2b-256 Hash of the entire document being referenced, not just its payload. + It ensures that the intended referenced document is the one used, and there has been no substitution. + Prevents substitutions where a new document with the same Document ID and Ver might be published over an existing one. + +#### Validation + +Every Reference Document **MUST** Exist, and **MUST** be a valid reference to the document. +The calculated Hash of the Referenced Document **MUST** match the Hash in the reference. + +### `category_id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Category Parameters](category_parameters.md) | +| Exclusive | brand_id | +| | campaign_id | + +A reference to the Category Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`category_id`](../metadata.md#category_id) must match the +[`category_id`](../metadata.md#category_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + ## Payload +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. +* `hide` : Requests the proposal be hidden (not final, but a hidden draft). + `hide` is only actioned if sent by the author, for a collaborator its synonymous with `draft`. + +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" + ], + "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", + "x-changelog": { + "2025-03-01": [ + "First Version Created." + ] + } +} +``` + + ## Signers +The following user roles may sign documents of this type: + +* Proposer + +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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [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 +[RFC8259]: https://www.rfc-editor.org/rfc/rfc8259.html diff --git a/specs/gen_docs/test/docs/proposal_template.md b/specs/gen_docs/test/docs/proposal_template.md index 9b4d4d6aa2..d7751566a5 100644 --- a/specs/gen_docs/test/docs/proposal_template.md +++ b/specs/gen_docs/test/docs/proposal_template.md @@ -28,21 +28,116 @@ TODO ## [COSE Header Parameters][RFC9052-HeaderParameters] +* [content type](../spec.md#content-type) = `application/schema+json` +* [content-encoding](../spec.md#content-encoding) = `[br]` + ## Metadata +### `type` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [Document Type](../metadata.md#document-type) | +| Type | `0ce8ab38-9258-4fbc-a62e-7faa6e58318f`,
`7808d2ba-d511-40af-84e8-c0d1625fdfdc` | + +The document TYPE. + +#### Validation + +**MUST** be a known document type. + +### `id` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +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. + +#### 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` + +| Parameter | Value | +| --- | --- | +| Required | yes | +| Format | [UUIDv7](../metadata.md#uuidv7) | + +The unique version of the document. +The first version of the document must set [`ver`](../metadata.md#ver) == [`id`](../metadata.md#id) + +#### Validation + +The document version must always be >= the document ID. + +### `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. + +#### Validation + +In addition to the validation performed for `ref`, +The document payload is not valid if it does not validate completely against the referenced template. + +### `category_id` + +| Parameter | Value | +| --- | --- | +| Required | optional | +| Format | [Document Reference](../metadata.md#document-reference) | +| Valid References | [Category Parameters](category_parameters.md) | +| Exclusive | brand_id | +| | campaign_id | + +A reference to the Category Parameters Document this document lies under. + +#### Validation + +In addition to the validation performed for `ref`, +Any referenced document that includes a [`category_id`](../metadata.md#category_id) must match the +[`category_id`](../metadata.md#category_id) of the referencing document. +It is also valid for the referenced document to not include this field, if it is +optional for the referenced document. + ## Payload +[JSON Schema] document which defines the valid contents of a proposal document. + ## Signers +The following admin roles may sign documents of this type: + +* Brand Admin +* Campaign 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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[JSON Schema]: https://json-schema.org/draft-07 [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/specs/gen_docs/test/metadata.md b/specs/gen_docs/test/metadata.md index c1c571b163..80645b5199 100644 --- a/specs/gen_docs/test/metadata.md +++ b/specs/gen_docs/test/metadata.md @@ -76,12 +76,12 @@ uuid_v7 = 6.37(bytes .size 16) ## Individual Metadata field definitions ### `type` - + | Parameter | Value | | --- | --- | | Required | yes | | Format | [Document Type](metadata.md#document-type) | - + The document TYPE. #### Validation @@ -89,12 +89,12 @@ The document TYPE. **MUST** be a known document type. ### `id` - + | Parameter | Value | | --- | --- | | Required | yes | | Format | [UUIDv7](metadata.md#uuidv7) | - + 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. @@ -105,12 +105,12 @@ IF [`ver`](metadata.md#ver) does not == [`id`](metadata.md#id) then a document w [`id`](metadata.md#id) and [`ver`](metadata.md#ver) being equal *MUST* exist. ### `ver` - + | Parameter | Value | | --- | --- | | Required | yes | | Format | [UUIDv7](metadata.md#uuidv7) | - + The unique version of the document. The first version of the document must set [`ver`](metadata.md#ver) == [`id`](metadata.md#id) @@ -119,25 +119,25 @@ The first version of the document must set [`ver`](metadata.md#ver) == [`id`](me The document version must always be >= the document ID. ### `ref` - + | Parameter | Value | | --- | --- | | Required | optional | | Format | [Document Reference](metadata.md#document-reference) | -| Valid References | Proposal Meta Template | -| | Proposal Template | -| | Proposal | -| | Proposal Comment Meta Template | -| | Proposal Comment Template | -| | Proposal Comment | -| | Proposal Submission Action | -| | Proposal Moderation Action | -| | Comment Action Document | -| | Brand Parameters | -| | Campaign Parameters | -| | Category Parameters | -| | Election Parameters | - +| Valid References | [Proposal Meta Template](./docs/proposal_meta_template.md) | +| | [Proposal Template](./docs/proposal_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](./docs/proposal_comment.md) | +| | [Proposal Submission Action](./docs/proposal_submission_action.md) | +| | [Proposal Moderation Action](./docs/proposal_moderation_action.md) | +| | [Comment Action Document](./docs/comment_action_document.md) | +| | [Brand Parameters](./docs/brand_parameters.md) | +| | [Campaign Parameters](./docs/campaign_parameters.md) | +| | [Category Parameters](./docs/category_parameters.md) | +| | [Election Parameters](./docs/election_parameters.md) | + Reference to a Linked Document or Documents. This is the primary hierarchical reference to a related document. @@ -156,16 +156,16 @@ Every Reference Document **MUST** Exist, and **MUST** be a valid reference to th The calculated Hash of the Referenced Document **MUST** match the Hash in the reference. ### `template` - + | Parameter | Value | | --- | --- | | Required | optional | | Format | [Document Reference](metadata.md#document-reference) | -| Valid References | Proposal Meta Template | -| | Proposal Template | -| | Proposal Comment Meta Template | -| | Proposal Comment Template | - +| 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) | + Reference to the template used to create and/or validate this document. #### Validation @@ -174,13 +174,13 @@ In addition to the validation performed for `ref`, The document payload is not valid if it does not validate completely against the referenced template. ### `reply` - + | Parameter | Value | | --- | --- | | Required | optional | | Format | [Document Reference](metadata.md#document-reference) | -| Valid References | Proposal Comment | - +| Valid References | [Proposal Comment](./docs/proposal_comment.md) | + Reference to a Comment document type being referred to. #### Validation @@ -190,12 +190,12 @@ The [`ref`](metadata.md#ref) of the [`reply`](metadata.md#reply) document must b the original comment document. ### `section` - + | Parameter | Value | | --- | --- | | Required | optional | | Format | [Section Reference](metadata.md#section-reference) | - + A Reference to the original document, or the comment being replied to. #### Validation @@ -204,12 +204,12 @@ For a non-reply this must be a valid section reference into the referenced docum For a reply, this must be a valid section reference into the comment being replied to. ### `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. @@ -225,15 +225,15 @@ However, any document submission referencing a proposal MUST be signed by all co addition to the author. ### `brand_id` - + | Parameter | Value | | --- | --- | | Required | optional | | Format | [Document Reference](metadata.md#document-reference) | -| Valid References | Brand Parameters | +| Valid References | [Brand Parameters](./docs/brand_parameters.md) | | Exclusive | campaign_id | | | category_id | - + A reference to the Brand Parameters Document this document lies under. #### Validation @@ -245,15 +245,15 @@ It is also valid for the referenced document to not include this field, if it is optional for the referenced document. ### `campaign_id` - + | Parameter | Value | | --- | --- | | Required | optional | | Format | [Document Reference](metadata.md#document-reference) | -| Valid References | Campaign Parameters | +| Valid References | [Campaign Parameters](./docs/campaign_parameters.md) | | Exclusive | brand_id | | | category_id | - + A reference to the Campaign Parameters Document this document lies under. #### Validation @@ -265,15 +265,15 @@ It is also valid for the referenced document to not include this field, if it is optional for the referenced document. ### `category_id` - + | Parameter | Value | | --- | --- | | Required | optional | | Format | [Document Reference](metadata.md#document-reference) | -| Valid References | Category Parameters | +| Valid References | [Category Parameters](./docs/category_parameters.md) | | Exclusive | brand_id | | | campaign_id | - + A reference to the Category Parameters Document this document lies under. #### Validation @@ -285,13 +285,13 @@ It is also valid for the referenced document to not include this field, if it is optional for the referenced document. ### `election_id` - + | Parameter | Value | | --- | --- | | Required | optional | | Format | [Document Reference](metadata.md#document-reference) | -| Valid References | Election Parameters | - +| Valid References | [Election Parameters](./docs/election_parameters.md) | + A reference to the Election Parameters Document this document lies under. #### Validation @@ -308,7 +308,7 @@ optional for the referenced document. | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/spec.md b/specs/gen_docs/test/spec.md index 07dba08a45..f82321dd80 100644 --- a/specs/gen_docs/test/spec.md +++ b/specs/gen_docs/test/spec.md @@ -94,7 +94,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-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/types.md b/specs/gen_docs/test/types.md index 0135585b53..7af74859fd 100644 --- a/specs/gen_docs/test/types.md +++ b/specs/gen_docs/test/types.md @@ -24,19 +24,19 @@ All Defined Document Types | Document Type | Base Types | [CBOR][RFC8949] | | :--- | :--- | :--- | -| [Brand Parameters](./../catalyst_docs/brand_parameters.md) | Brand | [37(h'ebcabeeb5bc54f9591e8cab8ca724172')] | -| [Campaign Parameters](./../catalyst_docs/campaign_parameters.md) | Campaign | [37(h'5ef32d5df240462ca7a4ba4af221fa23')] | -| [Category Parameters](./../catalyst_docs/category_parameters.md) | Category | [37(h'818938c331394daaafe6974c78488e95')] | -| [Comment Action Document](./../catalyst_docs/comment_action_document.md) | Action/Comment/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | -| [Election Parameters](./../catalyst_docs/election_parameters.md) | Election | [37(h'788ff4c6d65a451fbb33575fe056b411')] | -| [Proposal](./../catalyst_docs/proposal.md) | Proposal | [37(h'7808d2bad51140af84e8c0d1625fdfdc')] | -| [Proposal Comment](./../catalyst_docs/proposal_comment.md) | Comment/Proposal | [37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | -| [Proposal Comment Meta Template](./../catalyst_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](./../catalyst_docs/proposal_comment_template.md) | Template/Comment/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | -| [Proposal Meta Template](./../catalyst_docs/proposal_meta_template.md) | Template/Template/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | -| [Proposal Moderation Action](./../catalyst_docs/proposal_moderation_action.md) | Action/Proposal/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | -| [Proposal Submission Action](./../catalyst_docs/proposal_submission_action.md) | Action/Proposal/SubmissionAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'78927329cfd94ea19c710e019b126a65')] | -| [Proposal Template](./../catalyst_docs/proposal_template.md) | Template/Proposal | [37(h'0ce8ab3892584fbca62e7faa6e58318f'),
37(h'7808d2bad51140af84e8c0d1625fdfdc')] | +| [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')] | +| [Comment Action Document](./docs/comment_action_document.md) | Action/Comment/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | +| [Election Parameters](./docs/election_parameters.md) | Election | [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 Moderation Action](./docs/proposal_moderation_action.md) | Action/Proposal/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | +| [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')] | ## Copyright @@ -45,7 +45,7 @@ All Defined Document Types | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-03-12 | +| Modified | 2025-04-01 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/signed_doc.json b/specs/signed_doc.json index c6e097e458..66003aab8f 100644 --- a/specs/signed_doc.json +++ b/specs/signed_doc.json @@ -1182,8 +1182,8 @@ "signers": { "roles": { "admin": [ - "RootAdmin", - "BrandAdmin" + "Root Admin", + "Brand Admin" ], "user": [] }, @@ -1324,8 +1324,8 @@ "signers": { "roles": { "admin": [ - "BrandAdmin", - "CampaignAdmin" + "Brand Admin", + "Campaign Admin" ], "user": [] }, @@ -1464,8 +1464,8 @@ "signers": { "roles": { "admin": [ - "RootAdmin", - "BrandAdmin" + "Root Admin", + "Brand Admin" ], "user": [] }, @@ -1612,7 +1612,7 @@ }, "Proposal Submission Action": { "authors": {}, - "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. Unless they all submit or withdraw the same version of the proposal\nthe proposal will not be seen as submitted or withdrawn.\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, @@ -1914,8 +1914,8 @@ "signers": { "roles": { "admin": [ - "BrandAdmin", - "CampaignAdmin" + "Brand Admin", + "Campaign Admin" ], "user": [] }, diff --git a/specs/signed_docs/authors_copyright.cue b/specs/signed_docs/authors_copyright.cue index 4ebf92369c..e202dabc8b 100644 --- a/specs/signed_docs/authors_copyright.cue +++ b/specs/signed_docs/authors_copyright.cue @@ -9,9 +9,7 @@ package signed_docs } // -#authorMinConstraint: { - -} +#authorMinConstraint: {} // General Authors List authors: #authorList & { diff --git a/specs/signed_docs/docs/proposal_comment_meta_template.cue b/specs/signed_docs/docs/proposal_comment_meta_template.cue index de81659af2..fab54297f7 100644 --- a/specs/signed_docs/docs/proposal_comment_meta_template.cue +++ b/specs/signed_docs/docs/proposal_comment_meta_template.cue @@ -45,8 +45,8 @@ docs: #DocumentDefinitions & { // Root Admin and brand Admin may publish this document. admin: [ - "RootAdmin", - "BrandAdmin", + "Root Admin", + "Brand Admin", ] } } diff --git a/specs/signed_docs/docs/proposal_comment_template.cue b/specs/signed_docs/docs/proposal_comment_template.cue index 6f3d15eaec..1015e4eabe 100644 --- a/specs/signed_docs/docs/proposal_comment_template.cue +++ b/specs/signed_docs/docs/proposal_comment_template.cue @@ -47,8 +47,8 @@ docs: #DocumentDefinitions & { // Brand Admin and Lower may publish this document. admin: [ - "BrandAdmin", - "CampaignAdmin", + "Brand Admin", + "Campaign Admin", ] } } diff --git a/specs/signed_docs/docs/proposal_meta_template.cue b/specs/signed_docs/docs/proposal_meta_template.cue index bb6603b84a..e90ade9f5e 100644 --- a/specs/signed_docs/docs/proposal_meta_template.cue +++ b/specs/signed_docs/docs/proposal_meta_template.cue @@ -45,8 +45,8 @@ docs: #DocumentDefinitions & { // Root Admin and brand Admin may publish this document. admin: [ - "RootAdmin", - "BrandAdmin", + "Root Admin", + "Brand Admin", ] } } diff --git a/specs/signed_docs/docs/proposal_submission_action.cue b/specs/signed_docs/docs/proposal_submission_action.cue index 6004066415..71354ce5ec 100644 --- a/specs/signed_docs/docs/proposal_submission_action.cue +++ b/specs/signed_docs/docs/proposal_submission_action.cue @@ -17,8 +17,9 @@ docs: #DocumentDefinitions & { but none of them will take effect until ALL collaborators have posted equivalent actions. For example, three collaborators Alice/Bob/Claire can each post one submission action - for the same document. Unless they all submit or withdraw the same version of the proposal - the proposal will not be seen as submitted or withdrawn. + for the same document. + Unless they all submit the same version of the proposal + the proposal will not be seen as submitted. The payload is a fixed format. """ diff --git a/specs/signed_docs/docs/proposal_template.cue b/specs/signed_docs/docs/proposal_template.cue index 5eeca8a0ce..2b854cd441 100644 --- a/specs/signed_docs/docs/proposal_template.cue +++ b/specs/signed_docs/docs/proposal_template.cue @@ -47,8 +47,8 @@ docs: #DocumentDefinitions & { // Brand Admin and Lower may publish this document. admin: [ - "BrandAdmin", - "CampaignAdmin", + "Brand Admin", + "Campaign Admin", ] } } diff --git a/specs/signed_docs/payload.cue b/specs/signed_docs/payload.cue index 971a538a08..f2dcbec41c 100644 --- a/specs/signed_docs/payload.cue +++ b/specs/signed_docs/payload.cue @@ -3,7 +3,7 @@ package signed_docs // Payload definition _payload: { // Description of the payload - description?: string + description: string // Optional fixed schema for the payload. // A URI or inline JSON Schema that the payload must validate against. schema?: _ diff --git a/specs/signed_docs/signers.cue b/specs/signed_docs/signers.cue index 7f874ee682..fc476c30e9 100644 --- a/specs/signed_docs/signers.cue +++ b/specs/signed_docs/signers.cue @@ -23,14 +23,14 @@ _allUserRoles: or(_allUserRolesList) // Named Admin Roles _allAdminRolesList: list.UniqueItems _allAdminRolesList: [ - "RootCA", - "BrandCA", - "CampaignCA", - "CategoryCA", - "RootAdmin", - "BrandAdmin", - "CampaignAdmin", - "CategoryAdmin", + "Root CA", + "Brand CA", + "Campaign CA", + "Category CA", + "Root Admin", + "Brand Admin", + "Campaign Admin", + "Category Admin", "Moderator", ] _allAdminRoles: or(_allAdminRolesList) From c4b4c9088eee2de5064c0a86cf8e699a3497a15f Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Wed, 2 Apr 2025 21:21:02 +0700 Subject: [PATCH 27/35] feat: Add generation of document realtionship diagram --- .../gen_docs_relationship_diagram_d2.py | 50 +++++ specs/gen_docs/generate_docs.py | 2 + specs/gen_docs/test/doc_relationships.d2 | 180 ++++++++++++++++++ specs/gen_docs/test/doc_relationships.svg | 110 +++++++++++ specs/gen_docs/test/docs/brand_parameters.md | 2 +- .../gen_docs/test/docs/campaign_parameters.md | 2 +- .../gen_docs/test/docs/category_parameters.md | 2 +- .../test/docs/comment_action_document.md | 2 +- .../gen_docs/test/docs/election_parameters.md | 2 +- specs/gen_docs/test/docs/proposal.md | 2 +- specs/gen_docs/test/docs/proposal_comment.md | 2 +- .../docs/proposal_comment_meta_template.md | 2 +- .../test/docs/proposal_comment_template.md | 2 +- .../test/docs/proposal_meta_template.md | 2 +- .../test/docs/proposal_moderation_action.md | 2 +- .../test/docs/proposal_submission_action.md | 2 +- specs/gen_docs/test/docs/proposal_template.md | 2 +- specs/gen_docs/test/metadata.md | 2 +- specs/gen_docs/test/spec.md | 2 +- specs/gen_docs/test/types.md | 2 +- 20 files changed, 358 insertions(+), 16 deletions(-) create mode 100644 specs/gen_docs/gen_docs_relationship_diagram_d2.py create mode 100644 specs/gen_docs/test/doc_relationships.d2 create mode 100644 specs/gen_docs/test/doc_relationships.svg diff --git a/specs/gen_docs/gen_docs_relationship_diagram_d2.py b/specs/gen_docs/gen_docs_relationship_diagram_d2.py new file mode 100644 index 0000000000..6ee99e45c7 --- /dev/null +++ b/specs/gen_docs/gen_docs_relationship_diagram_d2.py @@ -0,0 +1,50 @@ +# Generate the spec.md file +from common import insert_copyright, metadata_fields + + +def gen_docs_relationship_diagram(doc_defs: dict) -> str: + """ + Generate a D2 Relationship diagram for all documents and their references. + """ + doc_config = """ +vars: { + d2-config: { + layout-engine: elk + theme-id: 4 + pad: 100 + center: true + } +} +""" + + doc_tables = "" + for doc in doc_defs["docs"]: + doc_refs = "" + ref_links = "" + uuids = "" + type_count = 0 + for uuid in doc_defs["docs"][doc]["type"]: + uuids += f' "type [{type_count}]": {uuid}\n' + type_count += 1 + + for ref in doc_defs["docs"][doc]["metadata"]: + ref_data = doc_defs["docs"][doc]["metadata"][ref] + if (ref_data["required"] != "excluded") and ref_data["format"] == "Document Reference": + doc_refs += f' "{ref}": {ref_data.get("type", "Unspecified")}\n' + if "type" in ref_data: + optional = ": Optional { style: { stroke: orange } }" if ref_data["required"] == "optional" else "" + ref_links += f'"{doc}"."{ref}"->"{ref_data["type"]}"{optional}\n' + + doc_table = f""" +"{doc}": {{ + shape: sql_table + "content type": {doc_defs["docs"][doc]["headers"]["content type"]["value"]} + {uuids} + {doc_refs} +}} + +{ref_links} +""" + doc_tables += doc_table + + return doc_config + doc_tables diff --git a/specs/gen_docs/generate_docs.py b/specs/gen_docs/generate_docs.py index 8246f4d77b..1ef2c3055b 100755 --- a/specs/gen_docs/generate_docs.py +++ b/specs/gen_docs/generate_docs.py @@ -13,6 +13,7 @@ from gen_spec_index import gen_spec_index from gen_spec_md import gen_spec_md from gen_types_md import gen_types_md +from gen_docs_relationship_diagram_d2 import gen_docs_relationship_diagram SIGNED_DOCS_SPECS = "../signed_doc.json" SIGNED_DOCS_PAGES_DIR = "../../docs/src/architecture/08_concepts/catalyst_docs" @@ -252,6 +253,7 @@ def init_parser() -> argparse.Namespace: good &= save_or_validate("types.md", gen_types_md, args, docs) good &= save_or_validate("metadata.md", gen_metadata_md, args, docs) good &= create_individual_doc_files(docs, args) + good &= save_or_validate("doc_relationships.d2", gen_docs_relationship_diagram, args, docs) if not good: print("File Comparisons Failed, Documentation is not current.") diff --git a/specs/gen_docs/test/doc_relationships.d2 b/specs/gen_docs/test/doc_relationships.d2 new file mode 100644 index 0000000000..009451851e --- /dev/null +++ b/specs/gen_docs/test/doc_relationships.d2 @@ -0,0 +1,180 @@ +vars: { + d2-config: { + layout-engine: elk + theme-id: 4 + pad: 100 + center: true + } +} + +"Brand Parameters": { + shape: sql_table + "content type": application/json + "type [0]": ebcabeeb-5bc5-4f95-91e8-cab8ca724172 + + +} + + + +"Campaign Parameters": { + shape: sql_table + "content type": application/json + "type [0]": 5ef32d5d-f240-462c-a7a4-ba4af221fa23 + + +} + + + +"Category Parameters": { + shape: sql_table + "content type": application/json + "type [0]": 818938c3-3139-4daa-afe6-974c78488e95 + + +} + + + +"Comment Action Document": { + shape: sql_table + "content type": application/json + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd + + +} + + + +"Election Parameters": { + shape: sql_table + "content type": application/json + "type [0]": 788ff4c6-d65a-451f-bb33-575fe056b411 + + +} + + + +"Proposal": { + shape: sql_table + "content type": application/json + "type [0]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + + "category_id": Category Parameters + "template": Proposal Template + +} + +"Proposal"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } +"Proposal"."template"->"Proposal Template" + + +"Proposal Comment": { + shape: sql_table + "content type": application/json + "type [0]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + + "category_id": Category Parameters + "ref": Proposal + "reply": Proposal Comment + "template": Proposal Comment Template + +} + +"Proposal Comment"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } +"Proposal Comment"."ref"->"Proposal" +"Proposal Comment"."reply"->"Proposal Comment": Optional { style: { stroke: orange } } +"Proposal Comment"."template"->"Proposal Comment Template" + + +"Proposal Comment Meta Template": { + shape: sql_table + "content type": application/schema+json + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [2]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [3]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + + "category_id": Category Parameters + +} + +"Proposal Comment Meta Template"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } + + +"Proposal Comment Template": { + shape: sql_table + "content type": application/schema+json + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + + "category_id": Category Parameters + "template": Proposal Comment Meta Template + +} + +"Proposal Comment Template"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } +"Proposal Comment Template"."template"->"Proposal Comment Meta Template": Optional { style: { stroke: orange } } + + +"Proposal Meta Template": { + shape: sql_table + "content type": application/schema+json + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + + "category_id": Category Parameters + +} + +"Proposal Meta Template"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } + + +"Proposal Moderation Action": { + shape: sql_table + "content type": application/json + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd + + +} + + + +"Proposal Submission Action": { + shape: sql_table + "content type": application/json + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "type [2]": 78927329-cfd9-4ea1-9c71-0e019b126a65 + + "category_id": Category Parameters + "ref": Proposal + +} + +"Proposal Submission Action"."category_id"->"Category Parameters" +"Proposal Submission Action"."ref"->"Proposal" + + +"Proposal Template": { + shape: sql_table + "content type": application/schema+json + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + + "category_id": Category Parameters + "template": Proposal Meta Template + +} + +"Proposal Template"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } +"Proposal Template"."template"->"Proposal Meta Template": Optional { style: { stroke: orange } } diff --git a/specs/gen_docs/test/doc_relationships.svg b/specs/gen_docs/test/doc_relationships.svg new file mode 100644 index 0000000000..b0c4a288a4 --- /dev/null +++ b/specs/gen_docs/test/doc_relationships.svg @@ -0,0 +1,110 @@ +Brand Parameterscontent typeapplication/jsontype [0]ebcabeeb-5bc5-4f95-91e8-cab8ca724172Campaign Parameterscontent typeapplication/jsontype [0]5ef32d5d-f240-462c-a7a4-ba4af221fa23Category Parameterscontent typeapplication/jsontype [0]818938c3-3139-4daa-afe6-974c78488e95Comment Action Documentcontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]a5d232b8-5e03-4117-9afd-be32b878fcddElection Parameterscontent typeapplication/jsontype [0]788ff4c6-d65a-451f-bb33-575fe056b411Proposalcontent typeapplication/jsontype [0]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal TemplateProposal Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal Meta TemplateProposal Commentcontent typeapplication/jsontype [0]b679ded3-0e7c-41ba-89f8-da62a17898eatype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersrefProposalreplyProposal CommenttemplateProposal Comment TemplateProposal Comment Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal Comment Meta TemplateProposal Comment Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]b679ded3-0e7c-41ba-89f8-da62a17898eatype [3]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersProposal Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersProposal Moderation Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]a5d232b8-5e03-4117-9afd-be32b878fcddProposal Submission Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]78927329-cfd9-4ea1-9c71-0e019b126a65category_idCategory ParametersrefProposal Optional OptionalOptionalOptionalOptionalOptionalOptionalOptionalOptional + + + + + + + + + + + diff --git a/specs/gen_docs/test/docs/brand_parameters.md b/specs/gen_docs/test/docs/brand_parameters.md index 1144c71133..e214d086b6 100644 --- a/specs/gen_docs/test/docs/brand_parameters.md +++ b/specs/gen_docs/test/docs/brand_parameters.md @@ -89,7 +89,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/campaign_parameters.md b/specs/gen_docs/test/docs/campaign_parameters.md index 00a36b7b0e..d6931ca6be 100644 --- a/specs/gen_docs/test/docs/campaign_parameters.md +++ b/specs/gen_docs/test/docs/campaign_parameters.md @@ -89,7 +89,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/category_parameters.md b/specs/gen_docs/test/docs/category_parameters.md index 60f04f182a..d89acc1cf4 100644 --- a/specs/gen_docs/test/docs/category_parameters.md +++ b/specs/gen_docs/test/docs/category_parameters.md @@ -89,7 +89,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/comment_action_document.md b/specs/gen_docs/test/docs/comment_action_document.md index 903b8e2ae8..c4ea847cf8 100644 --- a/specs/gen_docs/test/docs/comment_action_document.md +++ b/specs/gen_docs/test/docs/comment_action_document.md @@ -89,7 +89,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/election_parameters.md b/specs/gen_docs/test/docs/election_parameters.md index a88236b621..65c6a463db 100644 --- a/specs/gen_docs/test/docs/election_parameters.md +++ b/specs/gen_docs/test/docs/election_parameters.md @@ -89,7 +89,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal.md b/specs/gen_docs/test/docs/proposal.md index d660ecac1c..cf5c3c39cb 100644 --- a/specs/gen_docs/test/docs/proposal.md +++ b/specs/gen_docs/test/docs/proposal.md @@ -157,7 +157,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_comment.md b/specs/gen_docs/test/docs/proposal_comment.md index e764d4bc5a..b51d65586a 100644 --- a/specs/gen_docs/test/docs/proposal_comment.md +++ b/specs/gen_docs/test/docs/proposal_comment.md @@ -186,7 +186,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_comment_meta_template.md b/specs/gen_docs/test/docs/proposal_comment_meta_template.md index 267ec5ce26..39765b581f 100644 --- a/specs/gen_docs/test/docs/proposal_comment_meta_template.md +++ b/specs/gen_docs/test/docs/proposal_comment_meta_template.md @@ -121,7 +121,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_comment_template.md b/specs/gen_docs/test/docs/proposal_comment_template.md index 8643dcbd0d..4b49d974a9 100644 --- a/specs/gen_docs/test/docs/proposal_comment_template.md +++ b/specs/gen_docs/test/docs/proposal_comment_template.md @@ -133,7 +133,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_meta_template.md b/specs/gen_docs/test/docs/proposal_meta_template.md index 5b09004454..c63beb418d 100644 --- a/specs/gen_docs/test/docs/proposal_meta_template.md +++ b/specs/gen_docs/test/docs/proposal_meta_template.md @@ -121,7 +121,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_moderation_action.md b/specs/gen_docs/test/docs/proposal_moderation_action.md index aedc780a02..8fa8a9fc52 100644 --- a/specs/gen_docs/test/docs/proposal_moderation_action.md +++ b/specs/gen_docs/test/docs/proposal_moderation_action.md @@ -89,7 +89,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_submission_action.md b/specs/gen_docs/test/docs/proposal_submission_action.md index d50aa63b50..786189c2ab 100644 --- a/specs/gen_docs/test/docs/proposal_submission_action.md +++ b/specs/gen_docs/test/docs/proposal_submission_action.md @@ -202,7 +202,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_template.md b/specs/gen_docs/test/docs/proposal_template.md index d7751566a5..b38ba76abf 100644 --- a/specs/gen_docs/test/docs/proposal_template.md +++ b/specs/gen_docs/test/docs/proposal_template.md @@ -133,7 +133,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/metadata.md b/specs/gen_docs/test/metadata.md index 80645b5199..20d582c362 100644 --- a/specs/gen_docs/test/metadata.md +++ b/specs/gen_docs/test/metadata.md @@ -308,7 +308,7 @@ optional for the referenced document. | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/spec.md b/specs/gen_docs/test/spec.md index f82321dd80..a9018770b2 100644 --- a/specs/gen_docs/test/spec.md +++ b/specs/gen_docs/test/spec.md @@ -94,7 +94,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-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/types.md b/specs/gen_docs/test/types.md index 7af74859fd..49a9dcf7ec 100644 --- a/specs/gen_docs/test/types.md +++ b/specs/gen_docs/test/types.md @@ -45,7 +45,7 @@ All Defined Document Types | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-04-01 | +| Modified | 2025-04-02 | | Authors | Alex Pozhylenkov | | | Steven Johnson | From 4cc8879448eebd9e67a22a889b20d4c6a0fdc9b9 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 3 Apr 2025 13:45:16 +0700 Subject: [PATCH 28/35] fix: Relationship diagram generation --- specs/gen_docs/common.py | 14 +- specs/gen_docs/gen_docs_page_md.py | 35 +- .../gen_docs_relationship_diagram_d2.py | 34 +- specs/gen_docs/generate_docs.py | 8 +- specs/gen_docs/test/doc_relationships.d2 | 19 +- specs/gen_docs/test/doc_relationships.svg | 956 ++++++++++++++++-- specs/gen_docs/test/docs/brand_parameters.md | 2 +- .../gen_docs/test/docs/campaign_parameters.md | 2 +- .../gen_docs/test/docs/category_parameters.md | 2 +- .../test/docs/comment_action_document.md | 2 +- .../gen_docs/test/docs/election_parameters.md | 2 +- specs/gen_docs/test/docs/proposal.md | 2 +- specs/gen_docs/test/docs/proposal_comment.md | 2 +- .../docs/proposal_comment_meta_template.md | 2 +- .../test/docs/proposal_comment_template.md | 2 +- .../test/docs/proposal_meta_template.md | 2 +- .../test/docs/proposal_moderation_action.md | 2 +- .../test/docs/proposal_submission_action.md | 2 +- specs/gen_docs/test/docs/proposal_template.md | 2 +- specs/gen_docs/test/metadata.md | 2 +- specs/gen_docs/test/spec.md | 2 +- specs/gen_docs/test/types.md | 2 +- 22 files changed, 960 insertions(+), 138 deletions(-) diff --git a/specs/gen_docs/common.py b/specs/gen_docs/common.py index 96054420e7..27ac13394a 100644 --- a/specs/gen_docs/common.py +++ b/specs/gen_docs/common.py @@ -66,15 +66,16 @@ def metadata_format_link(name: str, depth: int = 0): return f"[{name}]({link})" + def metadata_doc_ref_link(name: str, depth: int = 0): """ Metadata Document Reference link. """ - link = name.lower().replace(" ","_")+".md" + link = name.lower().replace(" ", "_") + ".md" if depth == 0: link = f"./docs/{link}" - else: + else: while depth > 1: link = f"../{link}" depth -= 1 @@ -140,10 +141,7 @@ def metadata_fields(doc_data: dict, doc_name: str = None, depth: int = 0): monospace_types = [] for type in doc_data["docs"][doc_name]["type"]: monospace_types.append(f"`{type}`") - field_display += ( - f"| Type | {',
'.join(monospace_types)} |\n" - ) - + field_display += f"| Type | {',
'.join(monospace_types)} |\n" if field.get("multiple", False): field_display += f"| Multiple References | {field['multiple']} |\n" @@ -153,7 +151,9 @@ def metadata_fields(doc_data: dict, doc_name: str = None, depth: int = 0): if isinstance(ref_doc_names, str): ref_doc_names = [ref_doc_names] for ref_doc in ref_doc_names: - field_display += f"| {ref_heading} | {metadata_doc_ref_link(ref_doc,depth)} |\n" + field_display += ( + f"| {ref_heading} | {metadata_doc_ref_link(ref_doc, depth)} |\n" + ) ref_heading = "" exclusive = field.get("exclusive", None) if exclusive is not None: diff --git a/specs/gen_docs/gen_docs_page_md.py b/specs/gen_docs/gen_docs_page_md.py index e7e4d31d22..6d1af357c7 100644 --- a/specs/gen_docs/gen_docs_page_md.py +++ b/specs/gen_docs/gen_docs_page_md.py @@ -1,8 +1,9 @@ # Generate the spec.md file +import json +from urllib.parse import urlparse + from common import insert_copyright, metadata_fields -from urllib.parse import urlparse -import json def header_parameter_summary(name, doc_defs: dict) -> str: """ @@ -25,43 +26,46 @@ def metadata_summary(name, doc_defs: dict) -> str: """ return metadata_fields(doc_defs, name, depth=1) -def uri_validator(uri : str): + +def uri_validator(uri: str): try: result = urlparse(uri) - return all([result.scheme in ["http","https"], result.netloc]) + return all([result.scheme in ["http", "https"], result.netloc]) except Exception as _e: return False - -def document_payload(name: str,doc_defs: dict) -> str: + + +def document_payload(name: str, doc_defs: dict) -> str: """ Generate Payload Documentation """ if "payload" not in doc_defs["docs"][name]: return "TODO" - + payload = doc_defs["docs"][name]["payload"] - payload_docs = payload["description"]+"\n" + payload_docs = payload["description"] + "\n" if "schema" in payload: schema = payload["schema"] if uri_validator(schema): if schema == "https://json-schema.org/draft-07/schema": - payload_docs += "\n**Must be a valid JSON Schema Draft 7 document.**" + payload_docs += "\n**Must be a valid JSON Schema Draft 7 document.**" else: - payload_docs += f"\nMust be a valid according to <{schema}>." + payload_docs += f"\nMust be a valid according to <{schema}>." else: payload_docs += f"""\nSchema : ```json -{json.dumps(schema,indent=2,sort_keys=True)} +{json.dumps(schema, indent=2, sort_keys=True)} ``` """ return payload_docs.strip() -def document_signers(name:str, doc_defs: dict) -> str: + +def document_signers(name: str, doc_defs: dict) -> str: """ Generate documentation about who may sign this document.s """ @@ -74,7 +78,7 @@ def document_signers(name:str, doc_defs: dict) -> str: signers_doc += f"\nThe following {role_group} roles may sign documents of this type:\n\n" for role in roles: signers_doc += f"* {role}\n" - + signers_doc = signers_doc.strip() signers_doc += "\n\nNew versions of this document may be published by:\n\n" @@ -84,6 +88,7 @@ def document_signers(name:str, doc_defs: dict) -> str: return signers_doc.strip() + def gen_docs_page_md(name: str, doc_defs: dict) -> str: """ Generate an individual Documents Specification Page file from the definitions. @@ -119,11 +124,11 @@ def gen_docs_page_md(name: str, doc_defs: dict) -> str: ## Payload -{document_payload(name,doc_defs)} +{document_payload(name, doc_defs)} ## Signers -{document_signers(name,doc_defs)} +{document_signers(name, doc_defs)} {insert_copyright(doc_defs)} """ diff --git a/specs/gen_docs/gen_docs_relationship_diagram_d2.py b/specs/gen_docs/gen_docs_relationship_diagram_d2.py index 6ee99e45c7..39f6aaa903 100644 --- a/specs/gen_docs/gen_docs_relationship_diagram_d2.py +++ b/specs/gen_docs/gen_docs_relationship_diagram_d2.py @@ -1,5 +1,5 @@ # Generate the spec.md file -from common import insert_copyright, metadata_fields +from common import insert_copyright def gen_docs_relationship_diagram(doc_defs: dict) -> str: @@ -15,6 +15,18 @@ def gen_docs_relationship_diagram(doc_defs: dict) -> str: center: true } } +""" + + title = """ +title: |~md + # Signed Document Relationship Hierarchy +~| {near: top-center} +""" + + copyright = f""" +copyright: |~md + {insert_copyright(doc_defs)} +~| {{near: bottom-right}} """ doc_tables = "" @@ -29,10 +41,22 @@ def gen_docs_relationship_diagram(doc_defs: dict) -> str: for ref in doc_defs["docs"][doc]["metadata"]: ref_data = doc_defs["docs"][doc]["metadata"][ref] - if (ref_data["required"] != "excluded") and ref_data["format"] == "Document Reference": - doc_refs += f' "{ref}": {ref_data.get("type", "Unspecified")}\n' + if (ref_data["required"] != "excluded") and ref_data[ + "format" + ] == "Document Reference": + ref_doc = ref_data.get("type", "Unspecified") + doc_refs += f' "{ref}": {ref_doc}\n' if "type" in ref_data: - optional = ": Optional { style: { stroke: orange } }" if ref_data["required"] == "optional" else "" + optional = ( + "Optional { style: { stroke: orange } }" + if ref_data["required"] == "optional" + else "" + ) + # Self Reference + if ref_doc == doc: + optional = f"({ref}) {optional}" + if len(optional) > 0: + optional = f": {optional}".strip() ref_links += f'"{doc}"."{ref}"->"{ref_data["type"]}"{optional}\n' doc_table = f""" @@ -47,4 +71,4 @@ def gen_docs_relationship_diagram(doc_defs: dict) -> str: """ doc_tables += doc_table - return doc_config + doc_tables + return doc_config + title + copyright + doc_tables diff --git a/specs/gen_docs/generate_docs.py b/specs/gen_docs/generate_docs.py index 1ef2c3055b..3a56bb1dd9 100755 --- a/specs/gen_docs/generate_docs.py +++ b/specs/gen_docs/generate_docs.py @@ -9,11 +9,11 @@ from common import metadata_field_link from gen_docs_page_md import gen_docs_page_md +from gen_docs_relationship_diagram_d2 import gen_docs_relationship_diagram from gen_metadata_md import gen_metadata_md from gen_spec_index import gen_spec_index from gen_spec_md import gen_spec_md from gen_types_md import gen_types_md -from gen_docs_relationship_diagram_d2 import gen_docs_relationship_diagram SIGNED_DOCS_SPECS = "../signed_doc.json" SIGNED_DOCS_PAGES_DIR = "../../docs/src/architecture/08_concepts/catalyst_docs" @@ -186,7 +186,7 @@ def create_individual_doc_files(docs: dict, args: argparse.Namespace) -> bool: lambda docs: gen_docs_page_md(doc_name, docs), args, docs, - depth=1 + depth=1, ) return good @@ -253,7 +253,9 @@ def init_parser() -> argparse.Namespace: good &= save_or_validate("types.md", gen_types_md, args, docs) good &= save_or_validate("metadata.md", gen_metadata_md, args, docs) good &= create_individual_doc_files(docs, args) - good &= save_or_validate("doc_relationships.d2", gen_docs_relationship_diagram, args, docs) + good &= save_or_validate( + "doc_relationships.d2", gen_docs_relationship_diagram, args, docs + ) if not good: print("File Comparisons Failed, Documentation is not current.") diff --git a/specs/gen_docs/test/doc_relationships.d2 b/specs/gen_docs/test/doc_relationships.d2 index 009451851e..20988e8a2c 100644 --- a/specs/gen_docs/test/doc_relationships.d2 +++ b/specs/gen_docs/test/doc_relationships.d2 @@ -7,6 +7,23 @@ vars: { } } +title: |~md + # Signed Document Relationship Hierarchy +~| {near: top-center} + +copyright: |~md + ## 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-04-03 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +~| {near: bottom-right} + "Brand Parameters": { shape: sql_table "content type": application/json @@ -88,7 +105,7 @@ vars: { "Proposal Comment"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } "Proposal Comment"."ref"->"Proposal" -"Proposal Comment"."reply"->"Proposal Comment": Optional { style: { stroke: orange } } +"Proposal Comment"."reply"->"Proposal Comment": (reply) Optional { style: { stroke: orange } } "Proposal Comment"."template"->"Proposal Comment Template" diff --git a/specs/gen_docs/test/doc_relationships.svg b/specs/gen_docs/test/doc_relationships.svg index b0c4a288a4..3ac481f503 100644 --- a/specs/gen_docs/test/doc_relationships.svg +++ b/specs/gen_docs/test/doc_relationships.svg @@ -1,17 +1,21 @@ -Brand Parameterscontent typeapplication/jsontype [0]ebcabeeb-5bc5-4f95-91e8-cab8ca724172Campaign Parameterscontent typeapplication/jsontype [0]5ef32d5d-f240-462c-a7a4-ba4af221fa23Category Parameterscontent typeapplication/jsontype [0]818938c3-3139-4daa-afe6-974c78488e95Comment Action Documentcontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]a5d232b8-5e03-4117-9afd-be32b878fcddElection Parameterscontent typeapplication/jsontype [0]788ff4c6-d65a-451f-bb33-575fe056b411Proposalcontent typeapplication/jsontype [0]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal TemplateProposal Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal Meta TemplateProposal Commentcontent typeapplication/jsontype [0]b679ded3-0e7c-41ba-89f8-da62a17898eatype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersrefProposalreplyProposal CommenttemplateProposal Comment TemplateProposal Comment Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal Comment Meta TemplateProposal Comment Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]b679ded3-0e7c-41ba-89f8-da62a17898eatype [3]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersProposal Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersProposal Moderation Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]a5d232b8-5e03-4117-9afd-be32b878fcddProposal Submission Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]78927329-cfd9-4ea1-9c71-0e019b126a65category_idCategory ParametersrefProposal Optional OptionalOptionalOptionalOptionalOptionalOptionalOptionalOptional - - - - - - - - - - + .d2-2874731016 .fill-N1{fill:#0A0F25;} + .d2-2874731016 .fill-N2{fill:#676C7E;} + .d2-2874731016 .fill-N3{fill:#9499AB;} + .d2-2874731016 .fill-N4{fill:#CFD2DD;} + .d2-2874731016 .fill-N5{fill:#DEE1EB;} + .d2-2874731016 .fill-N6{fill:#EEF1F8;} + .d2-2874731016 .fill-N7{fill:#FFFFFF;} + .d2-2874731016 .fill-B1{fill:#000536;} + .d2-2874731016 .fill-B2{fill:#0F66B7;} + .d2-2874731016 .fill-B3{fill:#4393DD;} + .d2-2874731016 .fill-B4{fill:#87BFF3;} + .d2-2874731016 .fill-B5{fill:#BCDDFB;} + .d2-2874731016 .fill-B6{fill:#E5F3FF;} + .d2-2874731016 .fill-AA2{fill:#076F6F;} + .d2-2874731016 .fill-AA4{fill:#77DEDE;} + .d2-2874731016 .fill-AA5{fill:#C3F8F8;} + .d2-2874731016 .fill-AB4{fill:#C1A2F3;} + .d2-2874731016 .fill-AB5{fill:#DACEFB;} + .d2-2874731016 .stroke-N1{stroke:#0A0F25;} + .d2-2874731016 .stroke-N2{stroke:#676C7E;} + .d2-2874731016 .stroke-N3{stroke:#9499AB;} + .d2-2874731016 .stroke-N4{stroke:#CFD2DD;} + .d2-2874731016 .stroke-N5{stroke:#DEE1EB;} + .d2-2874731016 .stroke-N6{stroke:#EEF1F8;} + .d2-2874731016 .stroke-N7{stroke:#FFFFFF;} + .d2-2874731016 .stroke-B1{stroke:#000536;} + .d2-2874731016 .stroke-B2{stroke:#0F66B7;} + .d2-2874731016 .stroke-B3{stroke:#4393DD;} + .d2-2874731016 .stroke-B4{stroke:#87BFF3;} + .d2-2874731016 .stroke-B5{stroke:#BCDDFB;} + .d2-2874731016 .stroke-B6{stroke:#E5F3FF;} + .d2-2874731016 .stroke-AA2{stroke:#076F6F;} + .d2-2874731016 .stroke-AA4{stroke:#77DEDE;} + .d2-2874731016 .stroke-AA5{stroke:#C3F8F8;} + .d2-2874731016 .stroke-AB4{stroke:#C1A2F3;} + .d2-2874731016 .stroke-AB5{stroke:#DACEFB;} + .d2-2874731016 .background-color-N1{background-color:#0A0F25;} + .d2-2874731016 .background-color-N2{background-color:#676C7E;} + .d2-2874731016 .background-color-N3{background-color:#9499AB;} + .d2-2874731016 .background-color-N4{background-color:#CFD2DD;} + .d2-2874731016 .background-color-N5{background-color:#DEE1EB;} + .d2-2874731016 .background-color-N6{background-color:#EEF1F8;} + .d2-2874731016 .background-color-N7{background-color:#FFFFFF;} + .d2-2874731016 .background-color-B1{background-color:#000536;} + .d2-2874731016 .background-color-B2{background-color:#0F66B7;} + .d2-2874731016 .background-color-B3{background-color:#4393DD;} + .d2-2874731016 .background-color-B4{background-color:#87BFF3;} + .d2-2874731016 .background-color-B5{background-color:#BCDDFB;} + .d2-2874731016 .background-color-B6{background-color:#E5F3FF;} + .d2-2874731016 .background-color-AA2{background-color:#076F6F;} + .d2-2874731016 .background-color-AA4{background-color:#77DEDE;} + .d2-2874731016 .background-color-AA5{background-color:#C3F8F8;} + .d2-2874731016 .background-color-AB4{background-color:#C1A2F3;} + .d2-2874731016 .background-color-AB5{background-color:#DACEFB;} + .d2-2874731016 .color-N1{color:#0A0F25;} + .d2-2874731016 .color-N2{color:#676C7E;} + .d2-2874731016 .color-N3{color:#9499AB;} + .d2-2874731016 .color-N4{color:#CFD2DD;} + .d2-2874731016 .color-N5{color:#DEE1EB;} + .d2-2874731016 .color-N6{color:#EEF1F8;} + .d2-2874731016 .color-N7{color:#FFFFFF;} + .d2-2874731016 .color-B1{color:#000536;} + .d2-2874731016 .color-B2{color:#0F66B7;} + .d2-2874731016 .color-B3{color:#4393DD;} + .d2-2874731016 .color-B4{color:#87BFF3;} + .d2-2874731016 .color-B5{color:#BCDDFB;} + .d2-2874731016 .color-B6{color:#E5F3FF;} + .d2-2874731016 .color-AA2{color:#076F6F;} + .d2-2874731016 .color-AA4{color:#77DEDE;} + .d2-2874731016 .color-AA5{color:#C3F8F8;} + .d2-2874731016 .color-AB4{color:#C1A2F3;} + .d2-2874731016 .color-AB5{color:#DACEFB;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#000536;--color-border-muted:#0F66B7;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0F66B7;--color-accent-emphasis:#0F66B7;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker-d2-2874731016);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-dark-d2-2874731016);mix-blend-mode:overlay}.sketch-overlay-B3{fill:url(#streaks-dark-d2-2874731016);mix-blend-mode:overlay}.sketch-overlay-B4{fill:url(#streaks-normal-d2-2874731016);mix-blend-mode:color-burn}.sketch-overlay-B5{fill:url(#streaks-normal-d2-2874731016);mix-blend-mode:color-burn}.sketch-overlay-B6{fill:url(#streaks-bright-d2-2874731016);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark-d2-2874731016);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-normal-d2-2874731016);mix-blend-mode:color-burn}.sketch-overlay-AA5{fill:url(#streaks-bright-d2-2874731016);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-normal-d2-2874731016);mix-blend-mode:color-burn}.sketch-overlay-AB5{fill:url(#streaks-normal-d2-2874731016);mix-blend-mode:color-burn}.sketch-overlay-N1{fill:url(#streaks-darker-d2-2874731016);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark-d2-2874731016);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal-d2-2874731016);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal-d2-2874731016);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright-d2-2874731016);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright-d2-2874731016);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright-d2-2874731016);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>

Signed Document Relationship Hierarchy

+

Copyright

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Copyright:copyright: 2024-2025 IOG Singapore, All Rights Reserved
LicenseThis document is licensed under CC-BY-4.0
Created2024-12-27
Modified2025-04-03
AuthorsAlex Pozhylenkov alex.pozhylenkov@iohk.io
Steven Johnson steven.johnson@iohk.io
+
Brand Parameterscontent typeapplication/jsontype [0]ebcabeeb-5bc5-4f95-91e8-cab8ca724172Campaign Parameterscontent typeapplication/jsontype [0]5ef32d5d-f240-462c-a7a4-ba4af221fa23Category Parameterscontent typeapplication/jsontype [0]818938c3-3139-4daa-afe6-974c78488e95Comment Action Documentcontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]a5d232b8-5e03-4117-9afd-be32b878fcddElection Parameterscontent typeapplication/jsontype [0]788ff4c6-d65a-451f-bb33-575fe056b411Proposalcontent typeapplication/jsontype [0]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal TemplateProposal Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal Meta TemplateProposal Commentcontent typeapplication/jsontype [0]b679ded3-0e7c-41ba-89f8-da62a17898eatype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersrefProposalreplyProposal CommenttemplateProposal Comment TemplateProposal Comment Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal Comment Meta TemplateProposal Comment Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]b679ded3-0e7c-41ba-89f8-da62a17898eatype [3]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersProposal Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersProposal Moderation Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]a5d232b8-5e03-4117-9afd-be32b878fcddProposal Submission Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]78927329-cfd9-4ea1-9c71-0e019b126a65category_idCategory ParametersrefProposal Optional Optional(reply) OptionalOptionalOptionalOptionalOptionalOptionalOptional + + + + + + + + + + + +
diff --git a/specs/gen_docs/test/docs/brand_parameters.md b/specs/gen_docs/test/docs/brand_parameters.md index e214d086b6..d709134968 100644 --- a/specs/gen_docs/test/docs/brand_parameters.md +++ b/specs/gen_docs/test/docs/brand_parameters.md @@ -89,7 +89,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/campaign_parameters.md b/specs/gen_docs/test/docs/campaign_parameters.md index d6931ca6be..b5f0a95644 100644 --- a/specs/gen_docs/test/docs/campaign_parameters.md +++ b/specs/gen_docs/test/docs/campaign_parameters.md @@ -89,7 +89,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/category_parameters.md b/specs/gen_docs/test/docs/category_parameters.md index d89acc1cf4..32449573ca 100644 --- a/specs/gen_docs/test/docs/category_parameters.md +++ b/specs/gen_docs/test/docs/category_parameters.md @@ -89,7 +89,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/comment_action_document.md b/specs/gen_docs/test/docs/comment_action_document.md index c4ea847cf8..b3ef1d239c 100644 --- a/specs/gen_docs/test/docs/comment_action_document.md +++ b/specs/gen_docs/test/docs/comment_action_document.md @@ -89,7 +89,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/election_parameters.md b/specs/gen_docs/test/docs/election_parameters.md index 65c6a463db..6b0a7b0203 100644 --- a/specs/gen_docs/test/docs/election_parameters.md +++ b/specs/gen_docs/test/docs/election_parameters.md @@ -89,7 +89,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal.md b/specs/gen_docs/test/docs/proposal.md index cf5c3c39cb..2d3616821d 100644 --- a/specs/gen_docs/test/docs/proposal.md +++ b/specs/gen_docs/test/docs/proposal.md @@ -157,7 +157,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_comment.md b/specs/gen_docs/test/docs/proposal_comment.md index b51d65586a..047ba2643f 100644 --- a/specs/gen_docs/test/docs/proposal_comment.md +++ b/specs/gen_docs/test/docs/proposal_comment.md @@ -186,7 +186,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_comment_meta_template.md b/specs/gen_docs/test/docs/proposal_comment_meta_template.md index 39765b581f..0494dafc2f 100644 --- a/specs/gen_docs/test/docs/proposal_comment_meta_template.md +++ b/specs/gen_docs/test/docs/proposal_comment_meta_template.md @@ -121,7 +121,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_comment_template.md b/specs/gen_docs/test/docs/proposal_comment_template.md index 4b49d974a9..29b02d82bf 100644 --- a/specs/gen_docs/test/docs/proposal_comment_template.md +++ b/specs/gen_docs/test/docs/proposal_comment_template.md @@ -133,7 +133,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_meta_template.md b/specs/gen_docs/test/docs/proposal_meta_template.md index c63beb418d..05f46cbe0f 100644 --- a/specs/gen_docs/test/docs/proposal_meta_template.md +++ b/specs/gen_docs/test/docs/proposal_meta_template.md @@ -121,7 +121,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_moderation_action.md b/specs/gen_docs/test/docs/proposal_moderation_action.md index 8fa8a9fc52..64760c7145 100644 --- a/specs/gen_docs/test/docs/proposal_moderation_action.md +++ b/specs/gen_docs/test/docs/proposal_moderation_action.md @@ -89,7 +89,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_submission_action.md b/specs/gen_docs/test/docs/proposal_submission_action.md index 786189c2ab..34cb92179c 100644 --- a/specs/gen_docs/test/docs/proposal_submission_action.md +++ b/specs/gen_docs/test/docs/proposal_submission_action.md @@ -202,7 +202,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/docs/proposal_template.md b/specs/gen_docs/test/docs/proposal_template.md index b38ba76abf..031a99d43a 100644 --- a/specs/gen_docs/test/docs/proposal_template.md +++ b/specs/gen_docs/test/docs/proposal_template.md @@ -133,7 +133,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/metadata.md b/specs/gen_docs/test/metadata.md index 20d582c362..9e67d78917 100644 --- a/specs/gen_docs/test/metadata.md +++ b/specs/gen_docs/test/metadata.md @@ -308,7 +308,7 @@ optional for the referenced document. | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/spec.md b/specs/gen_docs/test/spec.md index a9018770b2..22d44c6ac2 100644 --- a/specs/gen_docs/test/spec.md +++ b/specs/gen_docs/test/spec.md @@ -94,7 +94,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-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/test/types.md b/specs/gen_docs/test/types.md index 49a9dcf7ec..97e17f4e0c 100644 --- a/specs/gen_docs/test/types.md +++ b/specs/gen_docs/test/types.md @@ -45,7 +45,7 @@ All Defined Document Types | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-04-02 | +| Modified | 2025-04-03 | | Authors | Alex Pozhylenkov | | | Steven Johnson | From e887b49f94e19e63ddf497771507a449e4f47f8f Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 3 Apr 2025 19:08:06 +0700 Subject: [PATCH 29/35] fix: Build signed doc specs into the architecture documentation --- docs/macros/__init__.py | 54 ----- docs/macros/signed_docs.py | 201 ------------------ .../catalyst_docs/brand_parameters.md | 1 - .../catalyst_docs/campaign_parameters.md | 1 - .../catalyst_docs/category_parameters.md | 1 - .../{old_comment.md => comment.md} | 10 +- .../catalyst_docs/comment_action_document.md | 1 - .../catalyst_docs/election_parameters.md | 1 - .../08_concepts/catalyst_docs/old_proposal.md | 159 -------------- .../08_concepts/catalyst_docs/proposal.md | 160 +++++++++++++- .../catalyst_docs/proposal_comment.md | 1 - .../proposal_comment_meta_template.md | 1 - .../proposal_comment_template.md | 1 - .../catalyst_docs/proposal_meta_template.md | 1 - .../proposal_moderation_action.md | 1 - .../proposal_submission_action.md | 1 - .../catalyst_docs/proposal_template.md | 1 - .../{old_review.md => review.md} | 2 +- .../08_concepts/catalyst_voting/v2.md | 18 +- .../08_concepts/immutable_ledger/ledger.md | 36 ++-- .../08_concepts/signed_doc/.pages | 2 +- .../signed_doc}/doc_relationships.d2 | 0 .../signed_doc}/doc_relationships.svg | 0 .../08_concepts/signed_doc/docs/.pages | 1 + .../signed_doc}/docs/brand_parameters.md | 0 .../signed_doc}/docs/campaign_parameters.md | 0 .../signed_doc}/docs/category_parameters.md | 0 .../docs/comment_action_document.md | 0 .../signed_doc}/docs/election_parameters.md | 0 .../08_concepts/signed_doc}/docs/proposal.md | 0 .../signed_doc}/docs/proposal_comment.md | 0 .../docs/proposal_comment_meta_template.md | 0 .../docs/proposal_comment_template.md | 0 .../docs/proposal_meta_template.md | 0 .../docs/proposal_moderation_action.md | 0 .../docs/proposal_submission_action.md | 0 .../signed_doc}/docs/proposal_template.md | 0 .../08_concepts/signed_doc/meta copy.md | 126 ----------- .../08_concepts/signed_doc/meta.md | 105 --------- .../08_concepts/signed_doc}/metadata.md | 0 .../08_concepts/signed_doc/spec.md | 91 +++++--- .../08_concepts/signed_doc/types.md | 57 ++++- .../08_concepts/signed_doc/validation.md | 21 -- specs/Justfile | 6 +- specs/gen_docs/gen_spec_md.py | 2 +- specs/gen_docs/gen_types_md.py | 4 + specs/gen_docs/test/.pages | 5 - specs/gen_docs/test/spec.md | 115 ---------- specs/gen_docs/test/types.md | 54 ----- 49 files changed, 309 insertions(+), 932 deletions(-) delete mode 100644 docs/macros/__init__.py delete mode 100644 docs/macros/signed_docs.py delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/brand_parameters.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/campaign_parameters.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md rename docs/src/architecture/08_concepts/catalyst_docs/{old_comment.md => comment.md} (93%) delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/election_parameters.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/old_proposal.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md delete mode 100644 docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md rename docs/src/architecture/08_concepts/catalyst_docs/{old_review.md => review.md} (97%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/doc_relationships.d2 (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/doc_relationships.svg (100%) create mode 100644 docs/src/architecture/08_concepts/signed_doc/docs/.pages rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/brand_parameters.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/campaign_parameters.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/category_parameters.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/comment_action_document.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/election_parameters.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/proposal.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/proposal_comment.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/proposal_comment_meta_template.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/proposal_comment_template.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/proposal_meta_template.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/proposal_moderation_action.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/proposal_submission_action.md (100%) rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/docs/proposal_template.md (100%) delete mode 100644 docs/src/architecture/08_concepts/signed_doc/meta copy.md delete mode 100644 docs/src/architecture/08_concepts/signed_doc/meta.md rename {specs/gen_docs/test => docs/src/architecture/08_concepts/signed_doc}/metadata.md (100%) delete mode 100644 docs/src/architecture/08_concepts/signed_doc/validation.md delete mode 100644 specs/gen_docs/test/.pages delete mode 100644 specs/gen_docs/test/spec.md delete mode 100644 specs/gen_docs/test/types.md diff --git a/docs/macros/__init__.py b/docs/macros/__init__.py deleted file mode 100644 index 635fd5e3d0..0000000000 --- a/docs/macros/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -from .include import inc_file -from .signed_docs import ( - cose_header_parameters, - doc_type_details, - doc_type_summary, - external_links, - signed_doc_details, -) - - -def define_env(env): - """ - This is the hook for defining variables, macros and filters - """ - - @env.macro - def include_file(filename, start_line=0, end_line=None, indent=None): - # Provided by the base mkdocs config. - return inc_file(env, filename, start_line, end_line, indent) - - @env.macro - def insert_doc_type_summary(): - try: - return doc_type_summary(env) - except Exception as exc: - return f"Macro Expansion Error: {exc}" - - @env.macro - def insert_doc_type_details(): - try: - return doc_type_details(env) - except Exception as exc: - return f"Macro Expansion Error: {exc}" - - @env.macro - def insert_cose_header_parameters(): - try: - return cose_header_parameters(env) - except Exception as exc: - return f"Macro Expansion Error: {exc}" - - @env.macro - def insert_signed_doc_details(name): - try: - return signed_doc_details(env, name) - except Exception as exc: - return f"Macro Expansion Error: {exc}" - - @env.macro - def insert_external_links(): - try: - return external_links(env) - except Exception as exc: - return f"Macro Expansion Error: {exc}" diff --git a/docs/macros/signed_docs.py b/docs/macros/signed_docs.py deleted file mode 100644 index b2266c9a9a..0000000000 --- a/docs/macros/signed_docs.py +++ /dev/null @@ -1,201 +0,0 @@ -import json -import os - -# import re -# import textwrap - -if __name__ == "__main__": - SIGNED_DOCS_SPECS = "signed_doc.json" -else: - SIGNED_DOCS_SPECS = "includes/signed_doc.json" - - -def uuid_as_cbor(uuid): - return f"37(h'{uuid.replace('-', '')}')" - - -def get_signed_doc_data(env): - """ - Load the Signed Document Data from its json file. - """ - full_filename = os.path.join(env.project_dir, SIGNED_DOCS_SPECS) - - with open(full_filename, "r") as f: - return json.load(f) - - -def doc_type_summary(env): - """ - Generate a Document Base Type Summary from the Document Specifications Data - """ - - doc_data = get_signed_doc_data(env) - doc_types = doc_data["base_types"] - - doc_type_summary = """ -| Base Type | [UUID] | [CBOR] | -| :--- | :--- | :--- | -""" - - for k in doc_types: - doc_type_summary += ( - f"| {k} | `{doc_types[k]}` | `{uuid_as_cbor(doc_types[k])}` |\n" - ) - - return doc_type_summary - - -def name_for_uuid(doc_types, uuid): - """ - Get the name for a document base type, given its uuid - """ - for k in doc_types: - if doc_types[k] == uuid: - return k - return "Unknown" - - -def name_to_spec_link(name, ref=None): - """ - Create a link to a document type, and an optional ref inside the document. - """ - link = "./../catalyst_docs/" + name.lower().replace(" ", "_") + ".md" - if ref is not None: - link += f"#{ref}" - return link - - -def base_types(docs, doc_types, name): - types = docs[name]["type"] - type_names = "" - for sub_type in types: - type_names += name_for_uuid(doc_types, sub_type) + "/" - return type_names[:-1] - - -def types_as_cbor(docs, name): - types = docs[name]["type"] - type_names = "[" - for sub_type in types: - type_names += uuid_as_cbor(sub_type) + ",
" - return type_names[:-6] + "]" - - -def doc_type_details(env): - """ - Generate a Document Type Detailed Summary from the Document Specifications Data - """ - - doc_data = get_signed_doc_data(env) - doc_types = doc_data["base_types"] - docs = doc_data["docs"] - - doc_type_details = """ -| Document Type | Base Types | [CBOR] | Specification | -| :--- | :--- | :--- | :--- | -""" - - for k in docs: - doc_type_details += f"| {k} | {base_types(docs, doc_types, k)} | {types_as_cbor(docs, k)} | [Specification]({name_to_spec_link(k)}) | \n" - - return doc_type_details - - -def external_links(env): - """ - Insert External Links we might have used in descriptions. - """ - doc_data = get_signed_doc_data(env) - links = doc_data["documentationLinks"] - - link_display = "" - for name in links: - link_display += f"[{name}]: {links[name]}\n" - - return link_display - - -def metadata_fields(env, doc_name=None): - """ - Display Metadata fields for the default set, or a specific document. - """ - doc_data = get_signed_doc_data(env) - if doc_name is not None: - fields = doc_data["docs"][doc_name]["metadata"] - field_title_level = "###" - else: - fields = doc_data["metadata"] - field_title_level = "##" - - order = doc_data["metadata_order"] - - # make sure every field is listed in the ordering - for field_name in fields: - if field_name not in order: - order += field_name - - field_display = "" - for field_name in order: - field = fields[field_name] - field_display += f""" -{field_title_level} `{field_name}` - -| Parameter | Value | -| --- | --- | -| Required | {field["required"]} | -""" - if field["required"] != "excluded": - field_display += f"| Format | {field['format']} |\n" - if "multiple" in field: - field_display += f"| Multiple References | {field['multiple']} |\n" - if "type" in field: - ref_heading = "Valid References" - ref_doc_names = field["type"] - if isinstance(ref_doc_names, str): - ref_doc_names = [ref_doc_names] - for ref_doc in ref_doc_names: - field_display += f"| {ref_heading} | {ref_doc} |\n" - ref_heading = "" - - field_display += f""" -{field["description"]} - -{field_title_level}# Validation - -{field["validation"]} -""" - return field_display - - -def signed_doc_details(env, name): - """ - Generate Signed Document Detailed Documentation Page. - """ - return name + "\n" + "test\n" - - -# run as a program to debug the macros -if __name__ == "__main__": - - class env: - project_dir = "/home/steven/Development/iohk/catalyst-libs/specs" - - print() - print("### DOC TYPE DETAILS ###") - print(doc_type_details(env)) - - print() - print("### DOC TYPE SUMMARY ###") - print(doc_type_summary(env)) - - print() - print("### COSE HEADER PARAMETERS ###") - print(cose_header_parameters(env)) - - print() - print("### EXTERNAL LINKS ###") - print(external_links(env)) - - print() - print("### GLOBAL METADATA ###") - print(metadata_fields(env)) diff --git a/docs/src/architecture/08_concepts/catalyst_docs/brand_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/brand_parameters.md deleted file mode 100644 index 374ff296fb..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/brand_parameters.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Brand Parameters" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/campaign_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/campaign_parameters.md deleted file mode 100644 index d26f8b3a1b..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/campaign_parameters.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Campaign Parameters" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md deleted file mode 100644 index b751009bde..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/category_parameters.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Category Parameters" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/old_comment.md b/docs/src/architecture/08_concepts/catalyst_docs/comment.md similarity index 93% rename from docs/src/architecture/08_concepts/catalyst_docs/old_comment.md rename to docs/src/architecture/08_concepts/catalyst_docs/comment.md index 3dc31f92f3..a177cf8fc1 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/old_comment.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/comment.md @@ -46,17 +46,17 @@ A list of used [Catalyst Signed Document protected header fields](./../signed_do "content-encoding" => "br" ``` -* [`ref`](./../signed_doc/meta.md#ref-document-reference). +* [`ref`](./../signed_doc/metadata.md#ref-document-reference). Reference to a related [Proposal Document], which [`type`](./../signed_doc/spec.md#type) must be equal to [proposal document `type`][Proposal Document] field value. -* [`template`](./../signed_doc/meta.md#ref-document-reference). +* [`template`](./../signed_doc/metadata.md#ref-document-reference). A reference to the comment template document, which [`type`](./../signed_doc/spec.md#type) must be equal to [comment template `type`](#comment-template) field value. -* [`reply`](./../signed_doc/meta.md#reply-reply-reference) (optional). +* [`reply`](./../signed_doc/metadata.md#reply-reply-reference) (optional). A reference to another comment document, where the comment is in reply to the referenced comment. The [`type`](./../signed_doc/spec.md#type) of the replied document @@ -65,7 +65,7 @@ A list of used [Catalyst Signed Document protected header fields](./../signed_do The referenced `comment` must be for the same proposal [`id`](./../signed_doc/spec.md#id), but can be for a different proposal [`ver`](./../signed_doc/spec.md#ver). -* [`section`](./../signed_doc/meta.md#section-section-reference) (optional). +* [`section`](./../signed_doc/metadata.md#section-section-reference) (optional). Used when the comment only applies to a specific section to the document being commented upon, and not the entire document. @@ -106,7 +106,7 @@ A list of used [Catalyst Signed Document protected header fields](./../signed_do "content-encoding" => "br" ``` -* [`category_id`](./../signed_doc/meta.md#category_id) (optional). +* [`category_id`](./../signed_doc/metadata.md#category_id) (optional). A reference to the category document, which [`type`](./../signed_doc/spec.md#type) must be equal to `48c20109-362a-4d32-9bba-e0a9cf8b45be` value. diff --git a/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md b/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md deleted file mode 100644 index 5b819f440f..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/comment_action_document.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Comment Action Document" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/election_parameters.md b/docs/src/architecture/08_concepts/catalyst_docs/election_parameters.md deleted file mode 100644 index 5749f999c4..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/election_parameters.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Election Parameters" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/old_proposal.md b/docs/src/architecture/08_concepts/catalyst_docs/old_proposal.md deleted file mode 100644 index 95390a229e..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/old_proposal.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -Title: Catalyst Proposal Document -Category: Catalyst -Status: Proposed -Authors: - - Steven Johnson -Implementors: - - Catalyst Fund 14 -Discussions: [] -Created: 2024-12-29 -License: CC-BY-4.0 ---- - -## Abstract - -## Proposal Document - -This is a document, formatted against the referenced proposal template, which defines a proposal which may be submitted -for consideration under one or more brand campaign categories. - -The brand, campaign and category are not part of the document because the document can exist outside this boundary. -They are defined when a specific document is submitted for consideration. - -### Specification - -Catalyst Proposal document is a [Catalyst Signed Document], -so its fully follows the structure of the [Catalyst Signed Document] specification. - -#### Metadata Fields - -A list of used [Catalyst Signed Document protected header fields](./../signed_doc/spec.md#signed-object-fields). - -* [`type`](./../signed_doc/spec.md#type): `7808d2ba-d511-40af-84e8-c0d1625fdfdc` [UUID] value. - - ```CDDL - "type" => 37(h'7808d2bad51140af84e8c0d1625fdfdc') - ``` - -* [`content type`](./../signed_doc/spec.md#content-type): `application/json`. - [Catalyst Signed Document content] must be in [JSON] format. - - ```CDDL - 3 => 30 - ``` - -* [`content encoding`](./../signed_doc/spec.md#content-encoding-optional): - [Catalyst Signed Document content] must be [Brotli] compressed. - - ```CDDL - "content-encoding" => "br" - ``` - -* [`template`](./../signed_doc/meta.md#ref-document-reference). - A reference to the proposal template document, - which [`type`](./../signed_doc/spec.md#type) must be equal to - [proposal template `type`](#proposal-template) field value. - -* [`category_id`](./../signed_doc/meta.md#category_id) (optional). - A reference to the category document, - which [`type`](./../signed_doc/spec.md#type) must be equal to - `48c20109-362a-4d32-9bba-e0a9cf8b45be` value. - -#### Fund 14 defined category ids - -* id: `0194d490-30bf-7473-81c8-a0eaef369619` -* id: `0194d490-30bf-7043-8c5c-f0e09f8a6d8c` -* id: `0194d490-30bf-7e75-95c1-a6cf0e8086d9` -* id: `0194d490-30bf-7703-a1c0-83a916b001e7` -* id: `0194d490-30bf-79d1-9a0f-84943123ef38` -* id: `0194d490-30bf-706d-91c6-0d4707f74cdf` -* id: `0194d490-30bf-759e-b729-304306fbaa5e` -* id: `0194d490-30bf-7e27-b5fd-de3133b54bf6` -* id: `0194d490-30bf-7f9e-8a5d-91fb67c078f2` -* id: `0194d490-30bf-7676-9658-36c0b67e656e` -* id: `0194d490-30bf-7978-b031-7aa2ccc5e3fd` -* id: `0194d490-30bf-7d34-bba9-8498094bd627` - -#### Content format - -TODO - -## Proposal Template - -This document provides the template structure which a Proposal must be formatted to, and validated against. - -### Specification - -Catalyst Proposal Template document is a [Catalyst Signed Document], -so its fully follows the structure of the [Catalyst Signed Document] specification. - -#### Metadata Fields - -A list of used [Catalyst Signed Document protected header fields](./../signed_doc/spec.md#signed-object-fields). - -* [`type`](./../signed_doc/spec.md#type): `0ce8ab38-9258-4fbc-a62e-7faa6e58318f` [UUID] value. - - ```CDDL - "type" => 37(h'0ce8ab3892584fbca62e7faa6e58318f') - ``` - -* [`content type`](./../signed_doc/spec.md#content-type): `application/json`. - [Catalyst Signed Document content] must be in [JSON] format. - - ```CDDL - 3 => 30 - ``` - -* [`content encoding`](./../signed_doc/spec.md#content-encoding-optional): - [Catalyst Signed Document content] must be [Brotli] compressed. - - ```CDDL - "content-encoding" => "br" - ``` - -* [`category_id`](./../signed_doc/meta.md#category_id) (optional). - A reference to the category document, - which [`type`](./../signed_doc/spec.md#type) must be equal to - `48c20109-362a-4d32-9bba-e0a9cf8b45be` value. - -#### Fund 14 defined templates ids - -* id: `0194d492-1daa-75b5-b4a4-5cf331cd8d1a`, ver: `0194d492-1daa-75b5-b4a4-5cf331cd8d1a`, - category: `0194d490-30bf-7473-81c8-a0eaef369619` -* id: `0194d492-1daa-7371-8bd3-c15811b2b063`, ver: `0194d492-1daa-7371-8bd3-c15811b2b063`, - category: `0194d490-30bf-7043-8c5c-f0e09f8a6d8c` -* id: `0194d492-1daa-79c7-a222-2c3b581443a8`, ver: `0194d492-1daa-79c7-a222-2c3b581443a8`, - category: `0194d490-30bf-7e75-95c1-a6cf0e8086d9` -* id: `0194d492-1daa-716f-a04e-f422f08a99dc`, ver: `0194d492-1daa-716f-a04e-f422f08a99dc`, - category: `0194d490-30bf-7703-a1c0-83a916b001e7` -* id: `0194d492-1daa-78fc-818a-bf20fc3e9b87`, ver: `0194d492-1daa-78fc-818a-bf20fc3e9b87`, - category: `0194d490-30bf-79d1-9a0f-84943123ef38` -* id: `0194d492-1daa-7d98-a3aa-c57d99121f78`, ver: `0194d492-1daa-7d98-a3aa-c57d99121f78`, - category: `0194d490-30bf-706d-91c6-0d4707f74cdf` -* id: `0194d492-1daa-77be-a1a5-c238fe25fe4f`, ver: `0194d492-1daa-77be-a1a5-c238fe25fe4f`, - category: `0194d490-30bf-759e-b729-304306fbaa5e` -* id: `0194d492-1daa-7254-a512-30a4cdecfb90`, ver: `0194d492-1daa-7254-a512-30a4cdecfb90`, - category: `0194d490-30bf-7e27-b5fd-de3133b54bf6` -* id: `0194d492-1daa-7de9-b535-1a0b0474ed4e`, ver: `0194d492-1daa-7de9-b535-1a0b0474ed4e`, - category: `0194d490-30bf-7f9e-8a5d-91fb67c078f2` -* id: `0194d492-1daa-7fce-84ee-b872a4661075`, ver: `0194d492-1daa-7fce-84ee-b872a4661075`, - category: `0194d490-30bf-7676-9658-36c0b67e656e` -* id: `0194d492-1daa-7878-9bcc-2c79fef0fc13`, ver: `0194d492-1daa-7878-9bcc-2c79fef0fc13`, - category: `0194d490-30bf-7978-b031-7aa2ccc5e3fd` -* id: `0194d492-1daa-722f-94f4-687f2c068a5d`, ver: `0194d492-1daa-722f-94f4-687f2c068a5d`, - category: `0194d490-30bf-7d34-bba9-8498094bd627` - -#### Content format - -TODO - -## Copyright - -This document is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode). - -[Catalyst Signed Document]: ./../signed_doc/spec.md -[Catalyst Signed Document content]: ./../signed_doc/spec.md#signed-object-content -[Brotli]: https://datatracker.ietf.org/doc/html/rfc7932 -[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 -[UUID]: https://www.rfc-editor.org/rfc/rfc9562.html diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal.md index 70b956cc20..5f5483353a 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/proposal.md @@ -1 +1,159 @@ -# {{ insert_signed_doc_details( "Proposal" ) }} +--- +Title: Catalyst Proposal Document +Category: Catalyst +Status: Proposed +Authors: + - Steven Johnson +Implementors: + - Catalyst Fund 14 +Discussions: [] +Created: 2024-12-29 +License: CC-BY-4.0 +--- + +## Abstract + +## Proposal Document + +This is a document, formatted against the referenced proposal template, which defines a proposal which may be submitted +for consideration under one or more brand campaign categories. + +The brand, campaign and category are not part of the document because the document can exist outside this boundary. +They are defined when a specific document is submitted for consideration. + +### Specification + +Catalyst Proposal document is a [Catalyst Signed Document], +so its fully follows the structure of the [Catalyst Signed Document] specification. + +#### Metadata Fields + +A list of used [Catalyst Signed Document protected header fields](./../signed_doc/spec.md#signed-object-fields). + +* [`type`](./../signed_doc/spec.md#type): `7808d2ba-d511-40af-84e8-c0d1625fdfdc` [UUID] value. + + ```CDDL + "type" => 37(h'7808d2bad51140af84e8c0d1625fdfdc') + ``` + +* [`content type`](./../signed_doc/spec.md#content-type): `application/json`. + [Catalyst Signed Document content] must be in [JSON] format. + + ```CDDL + 3 => 30 + ``` + +* [`content encoding`](./../signed_doc/spec.md#content-encoding-optional): + [Catalyst Signed Document content] must be [Brotli] compressed. + + ```CDDL + "content-encoding" => "br" + ``` + +* [`template`](./../signed_doc/metadata.md#ref-document-reference). + A reference to the proposal template document, + which [`type`](./../signed_doc/spec.md#type) must be equal to + [proposal template `type`](#proposal-template) field value. + +* [`category_id`](./../signed_doc/metadata.md#category_id) (optional). + A reference to the category document, + which [`type`](./../signed_doc/spec.md#type) must be equal to + `48c20109-362a-4d32-9bba-e0a9cf8b45be` value. + +#### Fund 14 defined category ids + +* id: `0194d490-30bf-7473-81c8-a0eaef369619` +* id: `0194d490-30bf-7043-8c5c-f0e09f8a6d8c` +* id: `0194d490-30bf-7e75-95c1-a6cf0e8086d9` +* id: `0194d490-30bf-7703-a1c0-83a916b001e7` +* id: `0194d490-30bf-79d1-9a0f-84943123ef38` +* id: `0194d490-30bf-706d-91c6-0d4707f74cdf` +* id: `0194d490-30bf-759e-b729-304306fbaa5e` +* id: `0194d490-30bf-7e27-b5fd-de3133b54bf6` +* id: `0194d490-30bf-7f9e-8a5d-91fb67c078f2` +* id: `0194d490-30bf-7676-9658-36c0b67e656e` +* id: `0194d490-30bf-7978-b031-7aa2ccc5e3fd` +* id: `0194d490-30bf-7d34-bba9-8498094bd627` + +#### Content format + +TODO + +## Proposal Template + +This document provides the template structure which a Proposal must be formatted to, and validated against. + +### Specification + +Catalyst Proposal Template document is a [Catalyst Signed Document], +so its fully follows the structure of the [Catalyst Signed Document] specification. + +#### Metadata Fields + +A list of used [Catalyst Signed Document protected header fields](./../signed_doc/spec.md#signed-object-fields). + +* [`type`](./../signed_doc/spec.md#type): `0ce8ab38-9258-4fbc-a62e-7faa6e58318f` [UUID] value. + + ```CDDL + "type" => 37(h'0ce8ab3892584fbca62e7faa6e58318f') + ``` + +* [`content type`](./../signed_doc/spec.md#content-type): `application/json`. + [Catalyst Signed Document content] must be in [JSON] format. + + ```CDDL + 3 => 30 + ``` + +* [`content encoding`](./../signed_doc/spec.md#content-encoding-optional): + [Catalyst Signed Document content] must be [Brotli] compressed. + + ```CDDL + "content-encoding" => "br" + ``` + +* [`category_id`](./../signed_doc/metadata.md#category_id) (optional). + A reference to the category document, + which [`type`](./../signed_doc/spec.md#type) must be equal to + `48c20109-362a-4d32-9bba-e0a9cf8b45be` value. + +#### Fund 14 defined templates ids + +* id: `0194d492-1daa-75b5-b4a4-5cf331cd8d1a`, ver: `0194d492-1daa-75b5-b4a4-5cf331cd8d1a`, + category: `0194d490-30bf-7473-81c8-a0eaef369619` +* id: `0194d492-1daa-7371-8bd3-c15811b2b063`, ver: `0194d492-1daa-7371-8bd3-c15811b2b063`, + category: `0194d490-30bf-7043-8c5c-f0e09f8a6d8c` +* id: `0194d492-1daa-79c7-a222-2c3b581443a8`, ver: `0194d492-1daa-79c7-a222-2c3b581443a8`, + category: `0194d490-30bf-7e75-95c1-a6cf0e8086d9` +* id: `0194d492-1daa-716f-a04e-f422f08a99dc`, ver: `0194d492-1daa-716f-a04e-f422f08a99dc`, + category: `0194d490-30bf-7703-a1c0-83a916b001e7` +* id: `0194d492-1daa-78fc-818a-bf20fc3e9b87`, ver: `0194d492-1daa-78fc-818a-bf20fc3e9b87`, + category: `0194d490-30bf-79d1-9a0f-84943123ef38` +* id: `0194d492-1daa-7d98-a3aa-c57d99121f78`, ver: `0194d492-1daa-7d98-a3aa-c57d99121f78`, + category: `0194d490-30bf-706d-91c6-0d4707f74cdf` +* id: `0194d492-1daa-77be-a1a5-c238fe25fe4f`, ver: `0194d492-1daa-77be-a1a5-c238fe25fe4f`, + category: `0194d490-30bf-759e-b729-304306fbaa5e` +* id: `0194d492-1daa-7254-a512-30a4cdecfb90`, ver: `0194d492-1daa-7254-a512-30a4cdecfb90`, + category: `0194d490-30bf-7e27-b5fd-de3133b54bf6` +* id: `0194d492-1daa-7de9-b535-1a0b0474ed4e`, ver: `0194d492-1daa-7de9-b535-1a0b0474ed4e`, + category: `0194d490-30bf-7f9e-8a5d-91fb67c078f2` +* id: `0194d492-1daa-7fce-84ee-b872a4661075`, ver: `0194d492-1daa-7fce-84ee-b872a4661075`, + category: `0194d490-30bf-7676-9658-36c0b67e656e` +* id: `0194d492-1daa-7878-9bcc-2c79fef0fc13`, ver: `0194d492-1daa-7878-9bcc-2c79fef0fc13`, + category: `0194d490-30bf-7978-b031-7aa2ccc5e3fd` +* id: `0194d492-1daa-722f-94f4-687f2c068a5d`, ver: `0194d492-1daa-722f-94f4-687f2c068a5d`, + category: `0194d490-30bf-7d34-bba9-8498094bd627` + +#### Content format + +TODO + +## Copyright + +This document is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode). + +[Catalyst Signed Document]: ./../signed_doc/spec.md +[Catalyst Signed Document content]: ./../signed_doc/spec.md#signed-object-content +[Brotli]: https://datatracker.ietf.org/doc/html/rfc7932 +[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 +[UUID]: https://www.rfc-editor.org/rfc/rfc9562.html diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md deleted file mode 100644 index 3b42dfa6eb..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Proposal Comment" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md deleted file mode 100644 index e6ba1239fa..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_meta_template.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Proposal Comment Meta Template" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md deleted file mode 100644 index ed0adefd44..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_comment_template.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Proposal Comment Template" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md deleted file mode 100644 index 2fa7ff69a9..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_meta_template.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Proposal Meta Template" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md deleted file mode 100644 index 6e2cd8b7a0..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_moderation_action.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Proposal Moderation Action" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md deleted file mode 100644 index 3368648bc8..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_submission_action.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Proposal Submission Action" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md b/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md deleted file mode 100644 index abe2348a39..0000000000 --- a/docs/src/architecture/08_concepts/catalyst_docs/proposal_template.md +++ /dev/null @@ -1 +0,0 @@ -# {{ insert_signed_doc_details( "Proposal Template" ) }} diff --git a/docs/src/architecture/08_concepts/catalyst_docs/old_review.md b/docs/src/architecture/08_concepts/catalyst_docs/review.md similarity index 97% rename from docs/src/architecture/08_concepts/catalyst_docs/old_review.md rename to docs/src/architecture/08_concepts/catalyst_docs/review.md index 749bbdb1dc..09a2a5ae75 100644 --- a/docs/src/architecture/08_concepts/catalyst_docs/old_review.md +++ b/docs/src/architecture/08_concepts/catalyst_docs/review.md @@ -46,7 +46,7 @@ A list of used [Catalyst Signed Document protected header fields](./../signed_do "content-encoding" => "br" ``` -* [`template`](./../signed_doc/meta.md#ref-document-reference). +* [`template`](./../signed_doc/metadata.md#ref-document-reference). A reference to the review template document, which [`type`](./../signed_doc/spec.md#type) must be equal to [review template `type`](#review-template) field value. diff --git a/docs/src/architecture/08_concepts/catalyst_voting/v2.md b/docs/src/architecture/08_concepts/catalyst_voting/v2.md index 45c1192581..e7fee18641 100644 --- a/docs/src/architecture/08_concepts/catalyst_voting/v2.md +++ b/docs/src/architecture/08_concepts/catalyst_voting/v2.md @@ -35,16 +35,16 @@ A list of used [Catalyst Signed Document protected header fields](./../signed_do "content-type" => "br" ``` -* [`brand_id`](./../signed_doc/meta.md#brand_id). -* [`campaign_id`](./../signed_doc/meta.md#campaign_id). -* [`election_id`](./../signed_doc/meta.md#election_id). -* [`category_id`](./../signed_doc/meta.md#category_id). +* [`brand_id`](./../signed_doc/metadata.md#brand_id). +* [`campaign_id`](./../signed_doc/metadata.md#campaign_id). +* [`election_id`](./../signed_doc/metadata.md#election_id). +* [`category_id`](./../signed_doc/metadata.md#category_id). #### Public vote -For the public vote [`type`](./../signed_doc/spec.md#type) value defined as follows: +For the public vote [`type`](./../signed_doc/metadata.md#type) value defined as follows: -* [`type`](./../signed_doc/spec.md#type): `8de5586c-e998-4b95-8742-7be3c8592803` [UUID] value. +* [`type`](./../signed_doc/metadata.md#type): `8de5586c-e998-4b95-8742-7be3c8592803` [UUID] value. ```CDDL "type" => 37(h'8DE5586CE9984B9587427BE3C8592803') @@ -66,9 +66,9 @@ Following that spec need to define a `choice`, `proof` and `prop-id`. #### Private vote -For the private vote [`type`](./../signed_doc/spec.md#type) value defined as follows: +For the private vote [`type`](./../signed_doc/metadata.md#type) value defined as follows: -* [`type`](./../signed_doc/spec.md#type): `e78ee18d-f380-44c1-a852-80aa6ecb07fe` [UUID] value. +* [`type`](./../signed_doc/metadata.md#type): `e78ee18d-f380-44c1-a852-80aa6ecb07fe` [UUID] value. ```CDDL "type" => 37(h'E78EE18DF38044C1A85280AA6ECB07FE') @@ -112,7 +112,7 @@ the following properties are used: [Catalyst Signed Document]: ./../signed_doc/spec.md -[Catalyst Signed Document content]: ./../signed_doc/spec.md#signed-object-content +[Catalyst Signed Document content]: ./../signed_doc/spec.md#content-type [Generalized Vote Transaction Structure]: ./gen_vote_tx.md [BLAKE2b-512]: https://www.blake2.net/blake2.pdf [ristretto255]: https://ristretto.group diff --git a/docs/src/architecture/08_concepts/immutable_ledger/ledger.md b/docs/src/architecture/08_concepts/immutable_ledger/ledger.md index f3731abdad..d157387a16 100644 --- a/docs/src/architecture/08_concepts/immutable_ledger/ledger.md +++ b/docs/src/architecture/08_concepts/immutable_ledger/ledger.md @@ -77,14 +77,14 @@ so its fully follows the structure of the [Catalyst Signed Document] specificati ### Metadata Fields -* [`id`](./../signed_doc/spec.md#id). +* [`id`](./../signed_doc/metadata.md#id). Used as a unique identifier of the chain. So all blocks from the same chain must have the same - [`id`](./../signed_doc/spec.md#id) field value. -* [`ver`](./../signed_doc/spec.md#ver). + [`id`](./../signed_doc/metadata.md#id) field value. +* [`ver`](./../signed_doc/metadata.md#ver). Used as a unique identifier of the block itself. Also the block's creation `timestamp` value is determined from the - [`ver`](./../signed_doc/spec.md#ver) field. + [`ver`](./../signed_doc/metadata.md#ver) field. * [`content type`](./../signed_doc/spec.md#content-type): `application/cbor`. [Catalyst Signed Document content] must be a [CBOR] encoded. @@ -92,24 +92,21 @@ so its fully follows the structure of the [Catalyst Signed Document] specificati 3 => 50 ``` -* [`content encoding`](./../signed_doc/spec.md#content-encoding-optional): +* [`content encoding`](./../signed_doc/spec.md#content-encoding): [Catalyst Signed Document content] must be [Brotli] compressed. ```CDDL "content-type" => "br" ``` -* [`type`](./../signed_doc/spec.md#type): `d9e7e6ce-2401-4d7d-9492-f4f7c64241c3` [UUID] value. +* [`type`](./../signed_doc/metadata.md#type): `d9e7e6ce-2401-4d7d-9492-f4f7c64241c3` [UUID] value. ```CDDL "type" => 37(h'D9E7E6CE24014D7D9492F4F7C64241C3') ``` -* [`ref_hash`](./../signed_doc/meta.md#ref-hash-secured-document-reference). - Previous block reference. - A [`ref`](./../signed_doc/meta.md#ref-document-reference) part **must** be a pair of - [`id`](./../signed_doc/spec.md#id) and - [`ver`](./../signed_doc/spec.md#ver). +* [`ref`](./../signed_doc/metadata.md#ref). + Previous block reference, including Hash of the previous block. ### Content format @@ -144,7 +141,7 @@ Block: ### Block validation rules -* [`id`](./../signed_doc/spec.md#id) +* [`id`](./../signed_doc/metadata.md#id) **MUST** be the same as for the previous block (except for genesis). * `height` **MUST** be incremented by `1` from the previous block height value (except for genesis and final block). *Genesis* block **MUST** have `0` value. @@ -152,24 +149,17 @@ Block: E.g. previous block height is `9` and the *Final* block height is `-10`. * *Final* block is the last one for the specific chain and any other block could not be referenced to the *Final* one. -* [`ver`](./../signed_doc/spec.md#ver) +* [`ver`](./../signed_doc/metadata.md#ver) timestamp value **MUST** be greater or equals than the corresponding `timestamp` of the previous block (except for genesis). -* [`ref_hash`](./../signed_doc/meta.md#ref-hash-secured-document-reference) +* [`ref`](./../signed_doc/metadata.md#ref) **MUST** be a reference to the previous block (except for genesis). * `ledger-type` **MUST** be the same as for the previous block if present (except for genesis). **MANDATORY** field for *Genesis* and *Final* blocks. * `purpose-id` **MUST** be the same as for the previous block if present (except for genesis). **MANDATORY** field for *Genesis* and *Final* blocks. -* [`kid`](./../signed_doc/spec.md#cose-signature-protected-header) field +* [`kid`](./../signed_doc/spec.md#kid) field **MUST** be the same as for the previous block (except for genesis). -* [`ref_hash`](./../signed_doc/meta.md#ref-hash-secured-document-reference)'s - `hash-bytes` CBOR tag value and `bytes` size - **MUST** be the same as for the previous block (except for genesis). - Means that the hash function type and hash size itself must be the same. -* [`ref_hash`](./../signed_doc/meta.md#ref-hash-secured-document-reference) - field for the *Genesis* block **MUST** be omitted. -* `block-data` **MUST** be a [deterministically][CBOR-deterministically-encoded] encoded CBOR. ## Rationale @@ -184,7 +174,7 @@ Block: [Catalyst Signed Document]: ./../signed_doc/spec.md -[Catalyst Signed Document content]: ./../signed_doc/spec.md#signed-object-content +[Catalyst Signed Document content]: ./../signed_doc/spec.md#content-type [CBOR-deterministically-encoded]: https://datatracker.ietf.org/doc/html/rfc8949#name-deterministically-encoded-c [Brotli]: https://datatracker.ietf.org/doc/html/rfc7932 [CBOR]: https://datatracker.ietf.org/doc/rfc8949/ diff --git a/docs/src/architecture/08_concepts/signed_doc/.pages b/docs/src/architecture/08_concepts/signed_doc/.pages index ffda03396a..883e563a83 100644 --- a/docs/src/architecture/08_concepts/signed_doc/.pages +++ b/docs/src/architecture/08_concepts/signed_doc/.pages @@ -1,5 +1,5 @@ title: Catalyst Signed Document nav: - Specification: spec.md - - Metadata Fields: meta.md + - Metadata Fields: metadata.md - Document Types: types.md diff --git a/specs/gen_docs/test/doc_relationships.d2 b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 similarity index 100% rename from specs/gen_docs/test/doc_relationships.d2 rename to docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 diff --git a/specs/gen_docs/test/doc_relationships.svg b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg similarity index 100% rename from specs/gen_docs/test/doc_relationships.svg rename to docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/.pages b/docs/src/architecture/08_concepts/signed_doc/docs/.pages new file mode 100644 index 0000000000..fb5a24abff --- /dev/null +++ b/docs/src/architecture/08_concepts/signed_doc/docs/.pages @@ -0,0 +1 @@ +title: Defined Document Types \ No newline at end of file diff --git a/specs/gen_docs/test/docs/brand_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters.md similarity index 100% rename from specs/gen_docs/test/docs/brand_parameters.md rename to docs/src/architecture/08_concepts/signed_doc/docs/brand_parameters.md diff --git a/specs/gen_docs/test/docs/campaign_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters.md similarity index 100% rename from specs/gen_docs/test/docs/campaign_parameters.md rename to docs/src/architecture/08_concepts/signed_doc/docs/campaign_parameters.md diff --git a/specs/gen_docs/test/docs/category_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/category_parameters.md similarity index 100% rename from specs/gen_docs/test/docs/category_parameters.md rename to docs/src/architecture/08_concepts/signed_doc/docs/category_parameters.md diff --git a/specs/gen_docs/test/docs/comment_action_document.md b/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md similarity index 100% rename from specs/gen_docs/test/docs/comment_action_document.md rename to docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md diff --git a/specs/gen_docs/test/docs/election_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md similarity index 100% rename from specs/gen_docs/test/docs/election_parameters.md rename to docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md diff --git a/specs/gen_docs/test/docs/proposal.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md similarity index 100% rename from specs/gen_docs/test/docs/proposal.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal.md diff --git a/specs/gen_docs/test/docs/proposal_comment.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment.md similarity index 100% rename from specs/gen_docs/test/docs/proposal_comment.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment.md diff --git a/specs/gen_docs/test/docs/proposal_comment_meta_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_meta_template.md similarity index 100% rename from specs/gen_docs/test/docs/proposal_comment_meta_template.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_meta_template.md diff --git a/specs/gen_docs/test/docs/proposal_comment_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md similarity index 100% rename from specs/gen_docs/test/docs/proposal_comment_template.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md diff --git a/specs/gen_docs/test/docs/proposal_meta_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md similarity index 100% rename from specs/gen_docs/test/docs/proposal_meta_template.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_meta_template.md diff --git a/specs/gen_docs/test/docs/proposal_moderation_action.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_moderation_action.md similarity index 100% rename from specs/gen_docs/test/docs/proposal_moderation_action.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_moderation_action.md diff --git a/specs/gen_docs/test/docs/proposal_submission_action.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_submission_action.md similarity index 100% rename from specs/gen_docs/test/docs/proposal_submission_action.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_submission_action.md diff --git a/specs/gen_docs/test/docs/proposal_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md similarity index 100% rename from specs/gen_docs/test/docs/proposal_template.md rename to docs/src/architecture/08_concepts/signed_doc/docs/proposal_template.md diff --git a/docs/src/architecture/08_concepts/signed_doc/meta copy.md b/docs/src/architecture/08_concepts/signed_doc/meta copy.md deleted file mode 100644 index c40491897d..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/meta copy.md +++ /dev/null @@ -1,126 +0,0 @@ -# Metadata Fields List - - -??? note "Additional Metadata fields: `additional_meta.cddl`" - - ```CDDL - {{ include_file('src/architecture/08_concepts/signed_doc/cddl/additional_meta.cddl', indent=4) }} - ``` - - -* [Metadata Fields List](#metadata-fields-list) - * [`ref` Document Reference](#ref-document-reference) - * [Validation](#validation) - * [`ref_hash` Secured Document Reference](#ref_hash-secured-document-reference) - * [`template` Template Reference](#template-template-reference) - * [`reply` Reply Reference](#reply-reply-reference) - * [`section` Section Reference](#section-section-reference) - * [`collabs` Authorized Collaborators](#collabs-authorized-collaborators) - * [`brand_id`](#brand_id) - * [`campaign_id`](#campaign_id) - * [`election_id`](#election_id) - * [`category_id`](#category_id) - -## `ref` Document Reference - -This is a reference to another document. -The purpose of the `ref` will vary depending on the document [`type`](./spec.md#type). - -The `ref` can be either a single [UUID] or a [CBOR] Array of Two [UUID]. - -If the `ref` is a single [UUID] v7, it is a reference to the document of that [`id`](./spec.md#id). -If the `ref` is a [CBOR] array, it has the form `[,]` where: - -* `` - the [UUID] v7 of the referenced documents [`id`](./spec.md#id). -* `` - the [UUID] v7 of the referenced documents [`ver`](./spec.md#ver). - -### Validation - -For any document type, `ref` can refer to only 1 other document type which must be different than -the type of document `ref` appears in. -For example `ref` for a Proposal Comment Document, is always a Proposal type document. - -## `ref_hash` Secured Document Reference - -This is a cryptographically secured reference to another document. - -It consists of two fields: - -* [`ref`](#ref-document-reference) - simple reference to the document. -* `hash` - hash of the referenced document [CBOR] bytes. - -## `template` Template Reference - -If the document was formed from a template, this is a reference to that template document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -It is invalid not to reference the template that formed a document. -If this is missing from such documents, the document will itself be considered invalid. - -Template references must explicitly reference both the Template Document ID, and Version. - -## `reply` Reply Reference - -This is a reply to another document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -`reply` is always referencing a document of the same type, and that document must `ref` reference the same document `id`. -However, depending on the document type, it may reference a different `ver` of that `id`. - -## `section` Section Reference - -This is a reference to a section of a document. -It is a CBOR String, and contains a [JSON Path] identifying the section in question. - -Because this metadata field uses [JSON Path], it can only be used to reference a document whose payload is [JSON]. - -## `collabs` Authorized Collaborators - -This is a list of entities other than the original author that may also publish versions of this document. -This may be updated by the original author, or any collaborator that is given "author" privileges. - -The latest `collabs` list in the latest version, published by an authorized author is the definitive -list of allowed collaborators after that point. - -The `collabs` list is a [CBOR] Array. -The contents of the array are TBD. - -However, they will contain enough information such that each collaborator can be uniquely identified and validated. - -*Note: An Author can unilaterally set the `collabs` list to any list of collaborators. -It does NOT mean that the listed collaborators have agreed to collaborate, only that the Author -gives them permission to.* - -This list can impact actions that can be performed by the `Proposal Action Document`. - -## `brand_id` - -This is a reply to another document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -`brand_id` represents a "brand" who is running the voting, e.g. Catalyst, Midnight. - -## `campaign_id` - -This is a reply to another document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -`campaign_id` defines a "campaign" of voting, e.g. "treasury campaign". - -## `election_id` - -Unique identifier [UUID] v4, which defines an election, -e.g. "Catalyst Fund 1", "Catalyst Fund 2". - -## `category_id` - -This is a reply to another document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -`campaign_id` defines a voting category as a collection of proposals, -e.g. "Development & Infrastructure", "Products & Integrations". - -[UUID]: https://www.rfc-editor.org/rfc/rfc9562.html -[CBOR]: https://datatracker.ietf.org/doc/rfc8949/ -[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 -[JSON Path]: https://datatracker.ietf.org/doc/html/rfc9535 diff --git a/docs/src/architecture/08_concepts/signed_doc/meta.md b/docs/src/architecture/08_concepts/signed_doc/meta.md deleted file mode 100644 index 2b5148cb00..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/meta.md +++ /dev/null @@ -1,105 +0,0 @@ -# Metadata Fields - -## `ref` Document Reference - -This is a reference to another document. -The purpose of the `ref` will vary depending on the document [`type`](./spec.md#type). - -The `ref` can be either a single [UUID] or a [CBOR] Array of Two [UUID]. - -If the `ref` is a single [UUID] v7, it is a reference to the document of that [`id`](./spec.md#id). -If the `ref` is a [CBOR] array, it has the form `[,]` where: - -* `` - the [UUID] v7 of the referenced documents [`id`](./spec.md#id). -* `` - the [UUID] v7 of the referenced documents [`ver`](./spec.md#ver). - -### Validation - -For any document type, `ref` can refer to only 1 other document type which must be different than -the type of document `ref` appears in. -For example `ref` for a Proposal Comment Document, is always a Proposal type document. - -## `ref_hash` Secured Document Reference - -This is a cryptographically secured reference to another document. - -It consists of two fields: - -* [`ref`](#ref-document-reference) - simple reference to the document. -* `hash` - hash of the referenced document [CBOR] bytes. - -## `template` Template Reference - -If the document was formed from a template, this is a reference to that template document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -It is invalid not to reference the template that formed a document. -If this is missing from such documents, the document will itself be considered invalid. - -Template references must explicitly reference both the Template Document ID, and Version. - -## `reply` Reply Reference - -This is a reply to another document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -`reply` is always referencing a document of the same type, and that document must `ref` reference the same document `id`. -However, depending on the document type, it may reference a different `ver` of that `id`. - -## `section` Section Reference - -This is a reference to a section of a document. -It is a CBOR String, and contains a [JSON Path] identifying the section in question. - -Because this metadata field uses [JSON Path], it can only be used to reference a document whose payload is [JSON]. - -## `collabs` Authorized Collaborators - -This is a list of entities other than the original author that may also publish versions of this document. -This may be updated by the original author, or any collaborator that is given "author" privileges. - -The latest `collabs` list in the latest version, published by an authorized author is the definitive -list of allowed collaborators after that point. - -The `collabs` list is a [CBOR] Array. -The contents of the array are TBD. - -However, they will contain enough information such that each collaborator can be uniquely identified and validated. - -*Note: An Author can unilaterally set the `collabs` list to any list of collaborators. -It does NOT mean that the listed collaborators have agreed to collaborate, only that the Author -gives them permission to.* - -This list can impact actions that can be performed by the `Proposal Action Document`. - -## `brand_id` - -This is a reply to another document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -`brand_id` represents a "brand" who is running the voting, e.g. Catalyst, Midnight. - -## `campaign_id` - -This is a reply to another document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -`campaign_id` defines a "campaign" of voting, e.g. "treasury campaign". - -## `election_id` - -Unique identifier [UUID] v4, which defines an election, -e.g. "Catalyst Fund 1", "Catalyst Fund 2". - -## `category_id` - -This is a reply to another document. -The format is the same as the [CBOR] Array form of [`ref`](#ref-document-reference). - -`campaign_id` defines a voting category as a collection of proposals, -e.g. "Development & Infrastructure", "Products & Integrations". - -[UUID]: https://www.rfc-editor.org/rfc/rfc9562.html -[CBOR]: https://datatracker.ietf.org/doc/rfc8949/ -[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 -[JSON Path]: https://datatracker.ietf.org/doc/html/rfc9535 diff --git a/specs/gen_docs/test/metadata.md b/docs/src/architecture/08_concepts/signed_doc/metadata.md similarity index 100% rename from specs/gen_docs/test/metadata.md rename to docs/src/architecture/08_concepts/signed_doc/metadata.md diff --git a/docs/src/architecture/08_concepts/signed_doc/spec.md b/docs/src/architecture/08_concepts/signed_doc/spec.md index f47dbb9213..506e94ef31 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec.md +++ b/docs/src/architecture/08_concepts/signed_doc/spec.md @@ -1,7 +1,4 @@ -# Specification - - - +# Catalyst Signed Document Specification ## Abstract @@ -25,21 +22,49 @@ However, we also require the ability to publish new versions of documents, and for documents to be able to securely reference one another. Catalyst Signed Documents are based on [COSE][RFC9052]. -Specifically the [COSE Sign][RFC9052-CoseSign] format is used. +Specifically, the [COSE Sign][RFC9052-CoseSign] format is used. This allows one or more signatures to be attached to the same document. -### Cose Header Parameters +### [COSE Header Parameters][RFC9052-HeaderParameters] + +[COSE][RFC9052] documents define a set of standard [COSE header parameters][RFC9052-HeaderParameters]. +All [COSE Header Parameters][RFC9052-HeaderParameters] are protected and +*MUST* appear in the protected headers section of the document. +The [COSE header parameters][RFC9052-HeaderParameters] defined and used by Catalyst Signed Documents are as follows: + +#### content type + +IANA Media Type/s allowed in the Payload + +* Required : yes +* [Cose][RFC9052] Label : 3 +* Format : IANA 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: + * This is an unofficial media type + * [RFC9165] Additional Control Operators for [CDDL][RFC8610] are supported. + * Must not have Modules, schema must be self-contained. -Cose documents define a set of standard [header parameters][RFC9052-HeaderParameters]. -All Headers Parameters are protected and *MUST* appear in the protected headers section of the document. -The header parameters defined and used by Catalyst Signed Documents are as follows: +#### content-encoding -{{ insert_cose_header_parameters() }} +Supported HTTP Encodings of the Payload. +If no compression or encoding is used, then this field must not be present. + +* Required : optional +* [Cose][RFC9052] Label : content-encoding ***Custom Header*** +* Format : HTTP Content Encoding + * Supported Values: + * [br] : [BROTLI][RFC7932] Compression ### Metadata Catalyst Signed Documents extend the Header Parameters with a series of Metadata fields. -These fields are defined [here](./meta.md). +These fields are defined [here](./metadata.md). ### Signing Catalyst Signed Documents @@ -54,25 +79,37 @@ The headers currently defined for the signatures are: #### `kid` -The kid is a [UTF-8][RFC3629] encoded [Catalyst ID]. -Any `kid` format which conforms to the [Catalyst ID] specification may be used. -The [Catalyst ID] unambiguously defines both the signing keys and signing algorithm used to sign the protected portion of the document. +The kid is a [UTF-8][RFC3629] encoded Catalyst ID. +Any `kid` format which conforms to the Catalyst ID specification may be used. +The Catalyst ID unambiguously defines both the signing keys and signing algorithm +used to sign the protected portion of the document. * Required: yes -* Cose Label: 4 -* Format: [UTF-8][RFC3629] encoded [Catalyst ID] +* [Cose][RFC9052] Label: 4 +* Format: [UTF-8][RFC3629] encoded Catalyst ID ## Copyright - -| Copyright | :copyright: 2024, IOG Singapore, All Rights Reserved | +| Copyright | :copyright: 2024-2025 IOG Singapore, All Rights Reserved | | --- | --- | -| License | This document is licensed under [CC-BY-4.0]. | -| Created | 2024-12-27 | -| Authors | Steven Johnson | -| | Alex Pozhylenkov | - -{{ insert_external_links() }} - - -[Catalyst ID]: ../rbac_id_uri/catalyst-id-uri.md \ No newline at end of file +| License | This document is licensed under [CC-BY-4.0] | +| Created | 2024-12-27 | +| Modified | 2025-04-03 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[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 +[application/json]: https://www.iana.org/assignments/media-types/application/json +[JSON Schema]: https://json-schema.org/draft-07 +[RFC9052-CoseSign]: https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si +[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 +[br]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index 8c622818db..4860f055da 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -4,18 +4,55 @@ All Document Types are defined by composing these base document types: -{{ insert_doc_type_summary() }} +| Base Type | [UUID][RFC9562] | [CBOR][RFC8949] | +| :--- | :--- | :--- | +| Action | `5e60e623-ad02-4a1b-a1ac-406db978ee48` | `37(h'5e60e623ad024a1ba1ac406db978ee48')` | +| Brand | `ebcabeeb-5bc5-4f95-91e8-cab8ca724172` | `37(h'ebcabeeb5bc54f9591e8cab8ca724172')` | +| 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')` | +| Election | `788ff4c6-d65a-451f-bb33-575fe056b411` | `37(h'788ff4c6d65a451fbb33575fe056b411')` | +| ModerationAction | `a5d232b8-5e03-4117-9afd-be32b878fcdd` | `37(h'a5d232b85e0341179afdbe32b878fcdd')` | +| 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 All Defined Document Types -{{ insert_doc_type_details() }} - - - - - - -[CBOR]: https://datatracker.ietf.org/doc/html/rfc8610 -[UUID]: https://www.rfc-editor.org/rfc/rfc9562.html + +| 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')] | +| [Comment Action Document](./docs/comment_action_document.md) | Action/Comment/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | +| [Election Parameters](./docs/election_parameters.md) | Election | [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 Moderation Action](./docs/proposal_moderation_action.md) | Action/Proposal/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | +| [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 + +![Document Relationship Hierarchy](doc_relationships.svg) + +## 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-04-03 | +| Authors | Alex Pozhylenkov | +| | Steven Johnson | + +[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode +[RFC8949]: https://www.rfc-editor.org/rfc/rfc8949.html +[RFC9562]: https://www.rfc-editor.org/rfc/rfc9562.html diff --git a/docs/src/architecture/08_concepts/signed_doc/validation.md b/docs/src/architecture/08_concepts/signed_doc/validation.md deleted file mode 100644 index 80d530965e..0000000000 --- a/docs/src/architecture/08_concepts/signed_doc/validation.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -Title: Catalyst Signed Documents - Validation Summary -Category: Catalyst -Status: Proposed -Authors: - - Steven Johnson -Implementors: - - Catalyst Fund 14 -Discussions: [] -Created: 2024-12-29 -License: CC-BY-4.0 ---- - -## Validation - -This is a list of Metadata fields that apply to each document type, and how they are to be validated. - -| Document Type |`ref` | `ref_hash` | `template` | `reply` | `section` | `brand_id` | `campaign_id` | `category_id` | -| ------------- | ----- | ---------- | --------- | ------- | --------- | ---------- | ------------ | ----------------- | -| Proposal | None | `p` | `p` | `p` | `p` | `p` | `p` | `p` | -| Comment | `c` | `p` | `p` | `p` | `p` | `p` | `p` | `p` | diff --git a/specs/Justfile b/specs/Justfile index e693b0e2f9..d9982359eb 100644 --- a/specs/Justfile +++ b/specs/Justfile @@ -21,9 +21,11 @@ regenerate: check # 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 # Generate the markdown docs from the specification. - cd gen_docs; ./generate_docs.py -g -o test ../signed_doc.json + cd gen_docs; ./generate_docs.py -g -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json # Check our validation code actually works properly - cd gen_docs; ./generate_docs.py -o test ../signed_doc.json + cd gen_docs; ./generate_docs.py -o "../../docs/src/architecture/08_concepts/signed_doc" ../signed_doc.json + # Generate an .svg from the d2 diagram + d2 "../docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2" # Validate the generated signed_docs.json is correct against the cue schema. diff --git a/specs/gen_docs/gen_spec_md.py b/specs/gen_docs/gen_spec_md.py index 9bc7a6101a..e0fcd65572 100644 --- a/specs/gen_docs/gen_spec_md.py +++ b/specs/gen_docs/gen_spec_md.py @@ -107,7 +107,7 @@ def gen_spec_md(doc_defs): ### Metadata Catalyst Signed Documents extend the Header Parameters with a series of Metadata fields. -These fields are defined [here](./meta.md). +These fields are defined [here](./metadata.md). ### Signing Catalyst Signed Documents diff --git a/specs/gen_docs/gen_types_md.py b/specs/gen_docs/gen_types_md.py index 3079ce811b..b94fbd1699 100644 --- a/specs/gen_docs/gen_types_md.py +++ b/specs/gen_docs/gen_types_md.py @@ -102,5 +102,9 @@ def gen_types_md(doc_defs): {doc_type_details(doc_defs)} +## Document Relationship Hierarchy + +![Document Relationship Hierarchy](doc_relationships.svg) + {insert_copyright(doc_defs)} """ diff --git a/specs/gen_docs/test/.pages b/specs/gen_docs/test/.pages deleted file mode 100644 index 883e563a83..0000000000 --- a/specs/gen_docs/test/.pages +++ /dev/null @@ -1,5 +0,0 @@ -title: Catalyst Signed Document -nav: - - Specification: spec.md - - Metadata Fields: metadata.md - - Document Types: types.md diff --git a/specs/gen_docs/test/spec.md b/specs/gen_docs/test/spec.md deleted file mode 100644 index 22d44c6ac2..0000000000 --- a/specs/gen_docs/test/spec.md +++ /dev/null @@ -1,115 +0,0 @@ -# Catalyst Signed Document Specification - -## Abstract - -Project Catalyst requires a verifiable data format for the publication and validation of -large volumes of off chain information. - -The Catalyst Signed Documents Specification is based on [COSE][RFC9052] -and provides the basis of this document specification. - -## Motivation - -As Project Catalyst decentralizes via both on-chain and off-chain mechanisms, a reliable, -standardized process for authenticating documents and their relationships is required. - -## Specification - -Project Catalyst generates a large volume of off chain information. -This information requires similar guarantees as on-chain data. -It needs to be verifiably published and also immutable. -However, we also require the ability to publish new versions of documents, -and for documents to be able to securely reference one another. - -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. - -### [COSE Header Parameters][RFC9052-HeaderParameters] - -[COSE][RFC9052] documents define a set of standard [COSE header parameters][RFC9052-HeaderParameters]. -All [COSE Header Parameters][RFC9052-HeaderParameters] are protected and -*MUST* appear in the protected headers section of the document. -The [COSE header parameters][RFC9052-HeaderParameters] defined and used by Catalyst Signed Documents are as follows: - -#### content type - -IANA Media Type/s allowed in the Payload - -* Required : yes -* [Cose][RFC9052] Label : 3 -* Format : IANA 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: - * This is an unofficial media type - * [RFC9165] Additional Control Operators for [CDDL][RFC8610] are supported. - * Must not have Modules, schema must be self-contained. - -#### content-encoding - -Supported HTTP Encodings of the Payload. -If no compression or encoding is used, then this field must not be present. - -* Required : optional -* [Cose][RFC9052] Label : content-encoding ***Custom Header*** -* Format : HTTP Content Encoding - * Supported Values: - * [br] : [BROTLI][RFC7932] Compression - -### Metadata - -Catalyst Signed Documents extend the Header Parameters with a series of Metadata fields. -These fields are defined [here](./meta.md). - -### Signing Catalyst Signed Documents - -Catalyst Signed Documents are based on the [COSE Sign][RFC9052-CoseSign] format. -This allows one or more signatures to be attached to the same document. -A catalyst signed document *MUST* have at least one valid signature attached. -Multiple signatures may also be attached to the same document, where that is required. - -Each signature is contained in an array of signatures attached to the document. -The signatures contain protected headers, and the signature itself. -The headers currently defined for the signatures are: - -#### `kid` - -The kid is a [UTF-8][RFC3629] encoded Catalyst ID. -Any `kid` format which conforms to the Catalyst ID specification may be used. -The Catalyst ID unambiguously defines both the signing keys and signing algorithm -used to sign the protected portion of the document. - -* Required: yes -* [Cose][RFC9052] Label: 4 -* Format: [UTF-8][RFC3629] encoded Catalyst ID - -## 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-04-03 | -| Authors | Alex Pozhylenkov | -| | Steven Johnson | - -[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 -[application/json]: https://www.iana.org/assignments/media-types/application/json -[JSON Schema]: https://json-schema.org/draft-07 -[RFC9052-CoseSign]: https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si -[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 -[br]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding#br diff --git a/specs/gen_docs/test/types.md b/specs/gen_docs/test/types.md deleted file mode 100644 index 97e17f4e0c..0000000000 --- a/specs/gen_docs/test/types.md +++ /dev/null @@ -1,54 +0,0 @@ -# Document Types Table - -## Document Base Types - -All Document Types are defined by composing these base document types: - -| Base Type | [UUID][RFC9562] | [CBOR][RFC8949] | -| :--- | :--- | :--- | -| Action | `5e60e623-ad02-4a1b-a1ac-406db978ee48` | `37(h'5e60e623ad024a1ba1ac406db978ee48')` | -| Brand | `ebcabeeb-5bc5-4f95-91e8-cab8ca724172` | `37(h'ebcabeeb5bc54f9591e8cab8ca724172')` | -| 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')` | -| Election | `788ff4c6-d65a-451f-bb33-575fe056b411` | `37(h'788ff4c6d65a451fbb33575fe056b411')` | -| ModerationAction | `a5d232b8-5e03-4117-9afd-be32b878fcdd` | `37(h'a5d232b85e0341179afdbe32b878fcdd')` | -| 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 - -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')] | -| [Comment Action Document](./docs/comment_action_document.md) | Action/Comment/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'b679ded30e7c41ba89f8da62a17898ea'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | -| [Election Parameters](./docs/election_parameters.md) | Election | [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 Moderation Action](./docs/proposal_moderation_action.md) | Action/Proposal/ModerationAction | [37(h'5e60e623ad024a1ba1ac406db978ee48'),
37(h'7808d2bad51140af84e8c0d1625fdfdc'),
37(h'a5d232b85e0341179afdbe32b878fcdd')] | -| [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')] | - - -## 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-04-03 | -| Authors | Alex Pozhylenkov | -| | Steven Johnson | - -[CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode -[RFC8949]: https://www.rfc-editor.org/rfc/rfc8949.html -[RFC9562]: https://www.rfc-editor.org/rfc/rfc9562.html From 3fff05859d1fbb47da55c9ac4121790cd604958b Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 3 Apr 2025 19:14:00 +0700 Subject: [PATCH 30/35] fix: remove unused link --- docs/src/architecture/08_concepts/immutable_ledger/ledger.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/architecture/08_concepts/immutable_ledger/ledger.md b/docs/src/architecture/08_concepts/immutable_ledger/ledger.md index d157387a16..4013616331 100644 --- a/docs/src/architecture/08_concepts/immutable_ledger/ledger.md +++ b/docs/src/architecture/08_concepts/immutable_ledger/ledger.md @@ -175,6 +175,5 @@ Block: [Catalyst Signed Document]: ./../signed_doc/spec.md [Catalyst Signed Document content]: ./../signed_doc/spec.md#content-type -[CBOR-deterministically-encoded]: https://datatracker.ietf.org/doc/html/rfc8949#name-deterministically-encoded-c [Brotli]: https://datatracker.ietf.org/doc/html/rfc7932 [CBOR]: https://datatracker.ietf.org/doc/rfc8949/ From 513bbc3387518b0c6f0ff0be2726c31ce6253e1b Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 3 Apr 2025 19:16:43 +0700 Subject: [PATCH 31/35] fix: spelling --- .config/dictionaries/project.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index f9152e1510..200715c2ac 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -143,6 +143,7 @@ logcall lookaside maindbname mapref +markdownlint mdlint mdns MEMMAP From 450f28a7abbead936123a6f00ba44ed2bb3d9996 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 3 Apr 2025 21:48:44 +0700 Subject: [PATCH 32/35] fix: spec index needs sub documents --- docs/src/architecture/08_concepts/signed_doc/.pages | 1 + specs/gen_docs/gen_spec_index.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/src/architecture/08_concepts/signed_doc/.pages b/docs/src/architecture/08_concepts/signed_doc/.pages index 883e563a83..176b5b0eb8 100644 --- a/docs/src/architecture/08_concepts/signed_doc/.pages +++ b/docs/src/architecture/08_concepts/signed_doc/.pages @@ -3,3 +3,4 @@ nav: - Specification: spec.md - Metadata Fields: metadata.md - Document Types: types.md + - docs diff --git a/specs/gen_docs/gen_spec_index.py b/specs/gen_docs/gen_spec_index.py index 6ecd4a27ee..2e9afcc0bd 100644 --- a/specs/gen_docs/gen_spec_index.py +++ b/specs/gen_docs/gen_spec_index.py @@ -11,4 +11,5 @@ def gen_spec_index(doc_defs): - Specification: spec.md - Metadata Fields: metadata.md - Document Types: types.md + - docs """ From e2f1eb49670ad458234e92e7f1aa4807e0ff8b7a Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 3 Apr 2025 23:21:38 +0700 Subject: [PATCH 33/35] fix: Put all metadata in doc diafram. Add doc diagram to pages --- .../signed_doc/doc_relationships.d2 | 107 ++-- .../signed_doc/doc_relationships.svg | 596 +++++++++--------- .../signed_doc/docs/brand_parameters.md | 16 + .../signed_doc/docs/campaign_parameters.md | 16 + .../signed_doc/docs/category_parameters.md | 16 + .../docs/comment_action_document.md | 18 + .../signed_doc/docs/election_parameters.md | 16 + .../08_concepts/signed_doc/docs/proposal.md | 23 +- .../signed_doc/docs/proposal_comment.md | 28 +- .../docs/proposal_comment_meta_template.md | 21 + .../docs/proposal_comment_template.md | 22 + .../signed_doc/docs/proposal_meta_template.md | 20 + .../docs/proposal_moderation_action.md | 18 + .../docs/proposal_submission_action.md | 26 +- .../signed_doc/docs/proposal_template.md | 21 + specs/gen_docs/common.py | 6 +- specs/gen_docs/gen_docs_page_md.py | 5 + .../gen_docs_relationship_diagram_d2.py | 109 ++-- specs/gen_docs/generate_docs.py | 26 +- 19 files changed, 713 insertions(+), 397 deletions(-) diff --git a/docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 index 20988e8a2c..2fb07fe721 100644 --- a/docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 +++ b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 @@ -27,8 +27,9 @@ copyright: |~md "Brand Parameters": { shape: sql_table "content type": application/json - "type [0]": ebcabeeb-5bc5-4f95-91e8-cab8ca724172 - + "type [0]": ebcabeeb-5bc5-4f95-91e8-cab8ca724172 + "id": UUIDv7 + "ver": UUIDv7 } @@ -37,8 +38,9 @@ copyright: |~md "Campaign Parameters": { shape: sql_table "content type": application/json - "type [0]": 5ef32d5d-f240-462c-a7a4-ba4af221fa23 - + "type [0]": 5ef32d5d-f240-462c-a7a4-ba4af221fa23 + "id": UUIDv7 + "ver": UUIDv7 } @@ -47,8 +49,9 @@ copyright: |~md "Category Parameters": { shape: sql_table "content type": application/json - "type [0]": 818938c3-3139-4daa-afe6-974c78488e95 - + "type [0]": 818938c3-3139-4daa-afe6-974c78488e95 + "id": UUIDv7 + "ver": UUIDv7 } @@ -57,10 +60,11 @@ copyright: |~md "Comment Action Document": { shape: sql_table "content type": application/json - "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd - + "id": UUIDv7 + "ver": UUIDv7 } @@ -69,8 +73,9 @@ copyright: |~md "Election Parameters": { shape: sql_table "content type": application/json - "type [0]": 788ff4c6-d65a-451f-bb33-575fe056b411 - + "type [0]": 788ff4c6-d65a-451f-bb33-575fe056b411 + "id": UUIDv7 + "ver": UUIDv7 } @@ -79,88 +84,96 @@ copyright: |~md "Proposal": { shape: sql_table "content type": application/json - "type [0]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - - "category_id": Category Parameters + "type [0]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": UUIDv7 + "ver": UUIDv7 "template": Proposal Template + "collaborators": Collaborators Reference List + "category_id": Category Parameters (Optional) } -"Proposal"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } "Proposal"."template"->"Proposal Template" +"Proposal"."category_id"->"Category Parameters": Optional "Proposal Comment": { shape: sql_table "content type": application/json - "type [0]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [0]": b679ded3-0e7c-41ba-89f8-da62a17898ea "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - - "category_id": Category Parameters + "id": UUIDv7 + "ver": UUIDv7 "ref": Proposal - "reply": Proposal Comment "template": Proposal Comment Template + "reply": Proposal Comment (Optional) + "section": Section Reference + "category_id": Category Parameters (Optional) } -"Proposal Comment"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } "Proposal Comment"."ref"->"Proposal" -"Proposal Comment"."reply"->"Proposal Comment": (reply) Optional { style: { stroke: orange } } "Proposal Comment"."template"->"Proposal Comment Template" +"Proposal Comment"."reply"->"Proposal Comment": Optional +"Proposal Comment"."category_id"->"Category Parameters": Optional "Proposal Comment Meta Template": { shape: sql_table "content type": application/schema+json - "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f "type [2]": b679ded3-0e7c-41ba-89f8-da62a17898ea "type [3]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - - "category_id": Category Parameters + "id": UUIDv7 + "ver": UUIDv7 + "category_id": Category Parameters (Optional) } -"Proposal Comment Meta Template"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } +"Proposal Comment Meta Template"."category_id"->"Category Parameters": Optional "Proposal Comment Template": { shape: sql_table "content type": application/schema+json - "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - - "category_id": Category Parameters - "template": Proposal Comment Meta Template + "id": UUIDv7 + "ver": UUIDv7 + "template": Proposal Comment Meta Template (Optional) + "category_id": Category Parameters (Optional) } -"Proposal Comment Template"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } -"Proposal Comment Template"."template"->"Proposal Comment Meta Template": Optional { style: { stroke: orange } } +"Proposal Comment Template"."template"->"Proposal Comment Meta Template": Optional +"Proposal Comment Template"."category_id"->"Category Parameters": Optional "Proposal Meta Template": { shape: sql_table "content type": application/schema+json - "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - - "category_id": Category Parameters + "id": UUIDv7 + "ver": UUIDv7 + "category_id": Category Parameters (Optional) } -"Proposal Meta Template"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } +"Proposal Meta Template"."category_id"->"Category Parameters": Optional "Proposal Moderation Action": { shape: sql_table "content type": application/json - "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd - + "id": UUIDv7 + "ver": UUIDv7 } @@ -169,29 +182,31 @@ copyright: |~md "Proposal Submission Action": { shape: sql_table "content type": application/json - "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc "type [2]": 78927329-cfd9-4ea1-9c71-0e019b126a65 - - "category_id": Category Parameters + "id": UUIDv7 + "ver": UUIDv7 "ref": Proposal + "category_id": Category Parameters } -"Proposal Submission Action"."category_id"->"Category Parameters" "Proposal Submission Action"."ref"->"Proposal" +"Proposal Submission Action"."category_id"->"Category Parameters" "Proposal Template": { shape: sql_table "content type": application/schema+json - "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - - "category_id": Category Parameters - "template": Proposal Meta Template + "id": UUIDv7 + "ver": UUIDv7 + "template": Proposal Meta Template (Optional) + "category_id": Category Parameters (Optional) } -"Proposal Template"."category_id"->"Category Parameters": Optional { style: { stroke: orange } } -"Proposal Template"."template"->"Proposal Meta Template": Optional { style: { stroke: orange } } +"Proposal Template"."template"->"Proposal Meta Template": Optional +"Proposal Template"."category_id"->"Category Parameters": Optional diff --git a/docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg index 3ac481f503..4a1efc5921 100644 --- a/docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg +++ b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg @@ -1,21 +1,21 @@ -

Signed Document Relationship Hierarchy

-

Copyright

+

Signed Document Relationship Hierarchy

+

Copyright

@@ -868,17 +868,17 @@
-
Brand Parameterscontent typeapplication/jsontype [0]ebcabeeb-5bc5-4f95-91e8-cab8ca724172Campaign Parameterscontent typeapplication/jsontype [0]5ef32d5d-f240-462c-a7a4-ba4af221fa23Category Parameterscontent typeapplication/jsontype [0]818938c3-3139-4daa-afe6-974c78488e95Comment Action Documentcontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]a5d232b8-5e03-4117-9afd-be32b878fcddElection Parameterscontent typeapplication/jsontype [0]788ff4c6-d65a-451f-bb33-575fe056b411Proposalcontent typeapplication/jsontype [0]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal TemplateProposal Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal Meta TemplateProposal Commentcontent typeapplication/jsontype [0]b679ded3-0e7c-41ba-89f8-da62a17898eatype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersrefProposalreplyProposal CommenttemplateProposal Comment TemplateProposal Comment Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParameterstemplateProposal Comment Meta TemplateProposal Comment Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]b679ded3-0e7c-41ba-89f8-da62a17898eatype [3]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersProposal Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdccategory_idCategory ParametersProposal Moderation Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]a5d232b8-5e03-4117-9afd-be32b878fcddProposal Submission Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]78927329-cfd9-4ea1-9c71-0e019b126a65category_idCategory ParametersrefProposal Optional Optional(reply) OptionalOptionalOptionalOptionalOptionalOptionalOptional - - - - - - - - - - - - +
Brand Parameterscontent typeapplication/jsontype [0]ebcabeeb-5bc5-4f95-91e8-cab8ca724172idUUIDv7verUUIDv7Campaign Parameterscontent typeapplication/jsontype [0]5ef32d5d-f240-462c-a7a4-ba4af221fa23idUUIDv7verUUIDv7Category Parameterscontent typeapplication/jsontype [0]818938c3-3139-4daa-afe6-974c78488e95idUUIDv7verUUIDv7Comment Action Documentcontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]a5d232b8-5e03-4117-9afd-be32b878fcddidUUIDv7verUUIDv7Election Parameterscontent typeapplication/jsontype [0]788ff4c6-d65a-451f-bb33-575fe056b411idUUIDv7verUUIDv7Proposalcontent typeapplication/jsontype [0]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7templateProposal TemplatecollaboratorsCollaborators Reference Listcategory_idCategory Parameters (Optional)Proposal Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7templateProposal Meta Template (Optional)category_idCategory Parameters (Optional)Proposal Commentcontent typeapplication/jsontype [0]b679ded3-0e7c-41ba-89f8-da62a17898eatype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7refProposaltemplateProposal Comment TemplatereplyProposal Comment (Optional)sectionSection Referencecategory_idCategory Parameters (Optional)Proposal Comment Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7templateProposal Comment Meta Template (Optional)category_idCategory Parameters (Optional)Proposal Comment Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]b679ded3-0e7c-41ba-89f8-da62a17898eatype [3]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7category_idCategory Parameters (Optional)Proposal Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7category_idCategory Parameters (Optional)Proposal Moderation Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]a5d232b8-5e03-4117-9afd-be32b878fcddidUUIDv7verUUIDv7Proposal Submission Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]78927329-cfd9-4ea1-9c71-0e019b126a65idUUIDv7verUUIDv7refProposalcategory_idCategory Parameters Optional<reply> OptionalOptionalOptionalOptionalOptionalOptionalOptionalOptional + + + + + + + + + + + +
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 d709134968..5012ceaadb 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 @@ -4,6 +4,21 @@ TODO +```d2 layout=elk + +"Brand Parameters": { + shape: sql_table + "content type": [application/json] + "type [0]": ebcabeeb-5bc5-4f95-91e8-cab8ca724172 + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + +} + + + +``` + ### Validation TODO @@ -94,5 +109,6 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[application/json]: https://www.iana.org/assignments/media-types/application/json [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 b5f0a95644..f298500609 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 @@ -4,6 +4,21 @@ TODO +```d2 layout=elk + +"Campaign Parameters": { + shape: sql_table + "content type": [application/json] + "type [0]": 5ef32d5d-f240-462c-a7a4-ba4af221fa23 + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + +} + + + +``` + ### Validation TODO @@ -94,5 +109,6 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[application/json]: https://www.iana.org/assignments/media-types/application/json [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 32449573ca..ebb47663ee 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 @@ -4,6 +4,21 @@ TODO +```d2 layout=elk + +"Category Parameters": { + shape: sql_table + "content type": [application/json] + "type [0]": 818938c3-3139-4daa-afe6-974c78488e95 + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + +} + + + +``` + ### Validation TODO @@ -94,5 +109,6 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[application/json]: https://www.iana.org/assignments/media-types/application/json [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_action_document.md b/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md index b3ef1d239c..fa04461e4b 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md @@ -4,6 +4,23 @@ TODO +```d2 layout=elk + +"Comment Action Document": { + shape: sql_table + "content type": [application/json] + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + +} + + + +``` + ### Validation TODO @@ -94,5 +111,6 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[application/json]: https://www.iana.org/assignments/media-types/application/json [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/election_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md index 6b0a7b0203..990f381bc4 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md @@ -4,6 +4,21 @@ TODO +```d2 layout=elk + +"Election Parameters": { + shape: sql_table + "content type": [application/json] + "type [0]": 788ff4c6-d65a-451f-bb33-575fe056b411 + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + +} + + + +``` + ### Validation TODO @@ -94,5 +109,6 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[application/json]: https://www.iana.org/assignments/media-types/application/json [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.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md index 2d3616821d..5ce7f983b0 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md @@ -6,13 +6,33 @@ A Proposal is a document which describes a proposed solution or project to address the criteria of a category within a campaign. The proposal itself is a draft document, it is not submitted for consideration -unless a `Proposal Submission Action` is submitted which references it. +unless a [Proposal Submission Action](proposal_submission_action.md) is submitted which references it. 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. +```d2 layout=elk + +"Proposal": { + shape: sql_table + "content type": [application/json] + "type [0]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + "template": Proposal Template + "collaborators": Collaborators Reference List + "category_id": Category Parameters (Optional) + +} + +"Proposal"."template"->"Proposal Template" +"Proposal"."category_id"->"Category Parameters": Optional + + +``` + ### Validation TODO @@ -162,5 +182,6 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[application/json]: https://www.iana.org/assignments/media-types/application/json [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.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment.md index 047ba2643f..95570dc2e5 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 @@ -11,6 +11,31 @@ 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. +```d2 layout=elk + +"Proposal Comment": { + shape: sql_table + "content type": [application/json] + "type [0]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + "ref": Proposal + "template": Proposal Comment Template + "reply": Proposal Comment (Optional) + "section": Section Reference + "category_id": Category Parameters (Optional) + +} + +"Proposal Comment"."ref"->"Proposal" +"Proposal Comment"."template"->"Proposal Comment Template" +"Proposal Comment"."reply"->"Proposal Comment": Optional +"Proposal Comment"."category_id"->"Category Parameters": Optional + + +``` + ### Validation TODO @@ -88,7 +113,7 @@ Reference to a Linked Document or Documents. This is the primary hierarchical reference to a related document. This is an Array of the format: - `[[DocumentID, DocumentVer, DocumentHash],...]` + `[[DocumentID, DocumentVer, DocumentHash],...]` * `DocumentID` is the [UUIDv7][RFC9562-V7] ID of the Document being referenced. * `DocumentVer` is the [UUIDv7][RFC9562-V7] Version of the Document being referenced. @@ -191,6 +216,7 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[application/json]: https://www.iana.org/assignments/media-types/application/json [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 [RFC8259]: https://www.rfc-editor.org/rfc/rfc8259.html 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 0494dafc2f..baccb9c969 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 @@ -9,6 +9,26 @@ are met in any Proposal Comment Template. The payload of a proposal comment template is controlled by its meta template. +```d2 layout=elk + +"Proposal Comment Meta Template": { + shape: sql_table + "content type": [application/schema+json] + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [2]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [3]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + "category_id": Category Parameters (Optional) + +} + +"Proposal Comment Meta Template"."category_id"->"Category Parameters": Optional + + +``` + ### Validation TODO @@ -125,6 +145,7 @@ New versions of this document may be published by: | Authors | Alex Pozhylenkov | | | Steven Johnson | +[application/schema+json]: https://datatracker.ietf.org/doc/draft-bhutton-json-schema/ [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema]: https://json-schema.org/draft-07 [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_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md index 29b02d82bf..fcd9b16926 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 @@ -12,6 +12,27 @@ 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. +```d2 layout=elk + +"Proposal Comment Template": { + shape: sql_table + "content type": [application/schema+json] + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + "template": Proposal Comment Meta Template (Optional) + "category_id": Category Parameters (Optional) + +} + +"Proposal Comment Template"."template"->"Proposal Comment Meta Template": Optional +"Proposal Comment Template"."category_id"->"Category Parameters": Optional + + +``` + ### Validation TODO @@ -137,6 +158,7 @@ New versions of this document may be published by: | Authors | Alex Pozhylenkov | | | Steven Johnson | +[application/schema+json]: https://datatracker.ietf.org/doc/draft-bhutton-json-schema/ [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema]: https://json-schema.org/draft-07 [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_meta_template.md index 05f46cbe0f..6ebbbbc740 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 @@ -9,6 +9,25 @@ are met in any Proposal Template. The payload of a proposal template is controlled by its meta template. +```d2 layout=elk + +"Proposal Meta Template": { + shape: sql_table + "content type": [application/schema+json] + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + "category_id": Category Parameters (Optional) + +} + +"Proposal Meta Template"."category_id"->"Category Parameters": Optional + + +``` + ### Validation TODO @@ -125,6 +144,7 @@ New versions of this document may be published by: | Authors | Alex Pozhylenkov | | | Steven Johnson | +[application/schema+json]: https://datatracker.ietf.org/doc/draft-bhutton-json-schema/ [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema]: https://json-schema.org/draft-07 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode 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 64760c7145..0853f706fe 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 @@ -4,6 +4,23 @@ TODO +```d2 layout=elk + +"Proposal Moderation Action": { + shape: sql_table + "content type": [application/json] + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + +} + + + +``` + ### Validation TODO @@ -94,5 +111,6 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[application/json]: https://www.iana.org/assignments/media-types/application/json [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_submission_action.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_submission_action.md index 34cb92179c..29aeb5d3dc 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 @@ -19,6 +19,27 @@ the proposal will not be seen as submitted. The payload is a fixed format. +```d2 layout=elk + +"Proposal Submission Action": { + shape: sql_table + "content type": [application/json] + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "type [2]": 78927329-cfd9-4ea1-9c71-0e019b126a65 + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + "ref": Proposal + "category_id": Category Parameters + +} + +"Proposal Submission Action"."ref"->"Proposal" +"Proposal Submission Action"."category_id"->"Category Parameters" + + +``` + ### Validation TODO @@ -97,7 +118,7 @@ Reference to a Linked Document or Documents. This is the primary hierarchical reference to a related document. This is an Array of the format: - `[[DocumentID, DocumentVer, DocumentHash],...]` + `[[DocumentID, DocumentVer, DocumentHash],...]` * `DocumentID` is the [UUIDv7][RFC9562-V7] ID of the Document being referenced. * `DocumentVer` is the [UUIDv7][RFC9562-V7] Version of the Document being referenced. @@ -140,7 +161,7 @@ States: * `final` : All collaborators must publish a `final` status for the proposal to be `final`. * `draft` : Reverses the previous `final` state for a signer. * `hide` : Requests the proposal be hidden (not final, but a hidden draft). - `hide` is only actioned if sent by the author, for a collaborator its synonymous with `draft`. + `hide` is only actioned if sent by the author, for a collaborator its synonymous with `draft`. Schema : @@ -207,6 +228,7 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 +[application/json]: https://www.iana.org/assignments/media-types/application/json [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 [RFC8259]: https://www.rfc-editor.org/rfc/rfc8259.html 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 031a99d43a..1f2fdaa4ac 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 @@ -12,6 +12,26 @@ linked to a brand/campaign or category via the template used by the proposal. The payload of a proposal is controlled by its template. +```d2 layout=elk + +"Proposal Template": { + shape: sql_table + "content type": [application/schema+json] + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": [UUIDv7][RFC9562-V7] + "ver": [UUIDv7][RFC9562-V7] + "template": Proposal Meta Template (Optional) + "category_id": Category Parameters (Optional) + +} + +"Proposal Template"."template"->"Proposal Meta Template": Optional +"Proposal Template"."category_id"->"Category Parameters": Optional + + +``` + ### Validation TODO @@ -137,6 +157,7 @@ New versions of this document may be published by: | Authors | Alex Pozhylenkov | | | Steven Johnson | +[application/schema+json]: https://datatracker.ietf.org/doc/draft-bhutton-json-schema/ [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema]: https://json-schema.org/draft-07 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode diff --git a/specs/gen_docs/common.py b/specs/gen_docs/common.py index 27ac13394a..63549797ee 100644 --- a/specs/gen_docs/common.py +++ b/specs/gen_docs/common.py @@ -67,7 +67,7 @@ def metadata_format_link(name: str, depth: int = 0): return f"[{name}]({link})" -def metadata_doc_ref_link(name: str, depth: int = 0): +def doc_ref_link(name: str, depth: int = 0): """ Metadata Document Reference link. """ @@ -151,9 +151,7 @@ def metadata_fields(doc_data: dict, doc_name: str = None, depth: int = 0): if isinstance(ref_doc_names, str): ref_doc_names = [ref_doc_names] for ref_doc in ref_doc_names: - field_display += ( - f"| {ref_heading} | {metadata_doc_ref_link(ref_doc, depth)} |\n" - ) + field_display += f"| {ref_heading} | {doc_ref_link(ref_doc, depth)} |\n" ref_heading = "" exclusive = field.get("exclusive", None) if exclusive is not None: diff --git a/specs/gen_docs/gen_docs_page_md.py b/specs/gen_docs/gen_docs_page_md.py index 6d1af357c7..cbb573f6ee 100644 --- a/specs/gen_docs/gen_docs_page_md.py +++ b/specs/gen_docs/gen_docs_page_md.py @@ -3,6 +3,7 @@ from urllib.parse import urlparse from common import insert_copyright, metadata_fields +from gen_docs_relationship_diagram_d2 import gen_doc_d2 def header_parameter_summary(name, doc_defs: dict) -> str: @@ -100,6 +101,10 @@ def gen_docs_page_md(name: str, doc_defs: dict) -> str: {doc_defs["docs"][name].get("description", "TODO")} +```d2 layout=elk +{gen_doc_d2(name, doc_defs)} +``` + ### Validation {doc_defs["docs"][name].get("validation", "TODO")} diff --git a/specs/gen_docs/gen_docs_relationship_diagram_d2.py b/specs/gen_docs/gen_docs_relationship_diagram_d2.py index 39f6aaa903..ffc8823628 100644 --- a/specs/gen_docs/gen_docs_relationship_diagram_d2.py +++ b/specs/gen_docs/gen_docs_relationship_diagram_d2.py @@ -1,12 +1,7 @@ # Generate the spec.md file from common import insert_copyright - -def gen_docs_relationship_diagram(doc_defs: dict) -> str: - """ - Generate a D2 Relationship diagram for all documents and their references. - """ - doc_config = """ +doc_config = """ vars: { d2-config: { layout-engine: elk @@ -17,58 +12,84 @@ def gen_docs_relationship_diagram(doc_defs: dict) -> str: } """ - title = """ +title = """ title: |~md # Signed Document Relationship Hierarchy ~| {near: top-center} """ - copyright = f""" -copyright: |~md - {insert_copyright(doc_defs)} -~| {{near: bottom-right}} -""" - doc_tables = "" - for doc in doc_defs["docs"]: - doc_refs = "" - ref_links = "" - uuids = "" - type_count = 0 - for uuid in doc_defs["docs"][doc]["type"]: - uuids += f' "type [{type_count}]": {uuid}\n' - type_count += 1 - - for ref in doc_defs["docs"][doc]["metadata"]: - ref_data = doc_defs["docs"][doc]["metadata"][ref] - if (ref_data["required"] != "excluded") and ref_data[ - "format" - ] == "Document Reference": - ref_doc = ref_data.get("type", "Unspecified") - doc_refs += f' "{ref}": {ref_doc}\n' - if "type" in ref_data: - optional = ( - "Optional { style: { stroke: orange } }" - if ref_data["required"] == "optional" - else "" - ) - # Self Reference +def gen_doc_d2(doc: str, doc_defs: dict) -> str: + """ + Generate an individual d2 table for an individual document. + """ + ref_links = "" + + doc_data = doc_defs["docs"][doc] + doc_metadata = doc_data["metadata"] + doc_type = doc_data["type"] + + metadata_rows = "" + + for meta in doc_defs["metadata_order"]: + if meta in doc_metadata and doc_metadata[meta]["required"] != "excluded": + if meta == "type": + type_count = 0 + for uuid in doc_type: + metadata_rows += f' "type [{type_count}]": {uuid}\n' + type_count += 1 + elif doc_metadata[meta]["format"] == "Document Reference": + ref_doc = doc_metadata[meta].get("type", "Unspecified") + if doc_metadata[meta]["required"] == "optional": + metadata_rows += f' "{meta}": {ref_doc} (Optional)\n' if ref_doc == doc: - optional = f"({ref}) {optional}" - if len(optional) > 0: - optional = f": {optional}".strip() - ref_links += f'"{doc}"."{ref}"->"{ref_data["type"]}"{optional}\n' + ref_links += f'"{doc}"."{meta}"->"{doc_metadata[meta]["type"]}": <{meta}> Optional\n' + else: + ref_links += f'"{doc}"."{meta}"->"{doc_metadata[meta]["type"]}": Optional\n' + else: + metadata_rows += f' "{meta}": {ref_doc}\n' + if ref_doc == doc: + ref_links += f'"{doc}"."{meta}"->"{doc_metadata[meta]["type"]}": <{meta}>n' + else: + ref_links += ( + f'"{doc}"."{meta}"->"{doc_metadata[meta]["type"]}"\n' + ) + else: + metadata_rows += f' "{meta}": {doc_metadata[meta]["format"]}\n' - doc_table = f""" + return f""" "{doc}": {{ shape: sql_table "content type": {doc_defs["docs"][doc]["headers"]["content type"]["value"]} - {uuids} - {doc_refs} +{metadata_rows} }} {ref_links} """ - doc_tables += doc_table + + +def gen_doc_diagram(doc, doc_defs: dict) -> str: + """ + Generate a D2 Relationship diagram for a single document. + """ + doc_table = gen_doc_d2(doc, doc_defs) + + return doc_config + doc_table + + +def gen_docs_relationship_diagram(doc_defs: dict) -> str: + """ + Generate a D2 Relationship diagram for all documents and their references. + """ + + copyright = f""" +copyright: |~md + {insert_copyright(doc_defs)} +~| {{near: bottom-right}} +""" + + doc_tables = "" + for doc in doc_defs["docs"]: + doc_tables += gen_doc_d2(doc, doc_defs) return doc_config + title + copyright + doc_tables diff --git a/specs/gen_docs/generate_docs.py b/specs/gen_docs/generate_docs.py index 3a56bb1dd9..4ce0e5cfeb 100755 --- a/specs/gen_docs/generate_docs.py +++ b/specs/gen_docs/generate_docs.py @@ -7,7 +7,7 @@ import re from pathlib import Path -from common import metadata_field_link +from common import doc_ref_link, metadata_field_link from gen_docs_page_md import gen_docs_page_md from gen_docs_relationship_diagram_d2 import gen_docs_relationship_diagram from gen_metadata_md import gen_metadata_md @@ -61,6 +61,29 @@ def strip_end_whitespace(s: str) -> str: return "\n".join(stripped_lines).strip() + "\n" +def add_doc_ref_links(file_data: str, doc_data: dict, depth: int = 0) -> str: + """ + Add Individual Document Reference cross reference links to the document. + All Document References in text must be as `` or they will not be linked. + """ + lines = file_data.splitlines() + file_data = "" + for line in lines: + if not line.startswith("#"): + for field_name in doc_data["docs"]: + fieldNameRegex = f"(^|\\s)`{field_name}`(\\.|\\s|$)" + replacement = f"\\1{doc_ref_link(field_name, depth)}\\2" + line = re.sub( + fieldNameRegex, + replacement, + line, + flags=re.IGNORECASE | re.MULTILINE, + ) + file_data += f"{line}\n" + + return file_data + + def add_metadata_links(file_data: str, doc_data: dict, depth: int = 0) -> str: """ Add metadata field documentation cross reference links to the document. @@ -145,6 +168,7 @@ def save_or_validate( if file_name.endswith(".md"): file_data = add_reference_links(file_data, doc_data) file_data = add_metadata_links(file_data, doc_data, depth) + file_data = add_doc_ref_links(file_data, doc_data, depth) # Remove any leading or trailing newlines and add a single newline at the end/ # Helps make clean markdown files. From 3e5e5d826dc491af44d1260e624087849dd44f61 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 3 Apr 2025 23:31:21 +0700 Subject: [PATCH 34/35] fix: Remove single doc diagram untilwe fix links --- .../signed_doc/docs/brand_parameters.md | 16 ----------- .../signed_doc/docs/campaign_parameters.md | 16 ----------- .../signed_doc/docs/category_parameters.md | 16 ----------- .../docs/comment_action_document.md | 18 ------------ .../signed_doc/docs/election_parameters.md | 16 ----------- .../08_concepts/signed_doc/docs/proposal.md | 21 -------------- .../signed_doc/docs/proposal_comment.md | 28 +------------------ .../docs/proposal_comment_meta_template.md | 21 -------------- .../docs/proposal_comment_template.md | 22 --------------- .../signed_doc/docs/proposal_meta_template.md | 20 ------------- .../docs/proposal_moderation_action.md | 18 ------------ .../docs/proposal_submission_action.md | 26 ++--------------- .../signed_doc/docs/proposal_template.md | 21 -------------- specs/gen_docs/gen_docs_page_md.py | 13 ++++++--- 14 files changed, 12 insertions(+), 260 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 5012ceaadb..d709134968 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 @@ -4,21 +4,6 @@ TODO -```d2 layout=elk - -"Brand Parameters": { - shape: sql_table - "content type": [application/json] - "type [0]": ebcabeeb-5bc5-4f95-91e8-cab8ca724172 - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - -} - - - -``` - ### Validation TODO @@ -109,6 +94,5 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[application/json]: https://www.iana.org/assignments/media-types/application/json [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 f298500609..b5f0a95644 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 @@ -4,21 +4,6 @@ TODO -```d2 layout=elk - -"Campaign Parameters": { - shape: sql_table - "content type": [application/json] - "type [0]": 5ef32d5d-f240-462c-a7a4-ba4af221fa23 - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - -} - - - -``` - ### Validation TODO @@ -109,6 +94,5 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[application/json]: https://www.iana.org/assignments/media-types/application/json [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 ebb47663ee..32449573ca 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 @@ -4,21 +4,6 @@ TODO -```d2 layout=elk - -"Category Parameters": { - shape: sql_table - "content type": [application/json] - "type [0]": 818938c3-3139-4daa-afe6-974c78488e95 - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - -} - - - -``` - ### Validation TODO @@ -109,6 +94,5 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[application/json]: https://www.iana.org/assignments/media-types/application/json [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_action_document.md b/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md index fa04461e4b..b3ef1d239c 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md @@ -4,23 +4,6 @@ TODO -```d2 layout=elk - -"Comment Action Document": { - shape: sql_table - "content type": [application/json] - "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 - "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea - "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - -} - - - -``` - ### Validation TODO @@ -111,6 +94,5 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[application/json]: https://www.iana.org/assignments/media-types/application/json [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/election_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md index 990f381bc4..6b0a7b0203 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md @@ -4,21 +4,6 @@ TODO -```d2 layout=elk - -"Election Parameters": { - shape: sql_table - "content type": [application/json] - "type [0]": 788ff4c6-d65a-451f-bb33-575fe056b411 - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - -} - - - -``` - ### Validation TODO @@ -109,6 +94,5 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[application/json]: https://www.iana.org/assignments/media-types/application/json [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.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md index 5ce7f983b0..094de9d66e 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md @@ -13,26 +13,6 @@ linked to a brand/campaign or category via the template used by the proposal. The payload of a proposal is controlled by its template. -```d2 layout=elk - -"Proposal": { - shape: sql_table - "content type": [application/json] - "type [0]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - "template": Proposal Template - "collaborators": Collaborators Reference List - "category_id": Category Parameters (Optional) - -} - -"Proposal"."template"->"Proposal Template" -"Proposal"."category_id"->"Category Parameters": Optional - - -``` - ### Validation TODO @@ -182,6 +162,5 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[application/json]: https://www.iana.org/assignments/media-types/application/json [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.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment.md index 95570dc2e5..047ba2643f 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 @@ -11,31 +11,6 @@ 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. -```d2 layout=elk - -"Proposal Comment": { - shape: sql_table - "content type": [application/json] - "type [0]": b679ded3-0e7c-41ba-89f8-da62a17898ea - "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - "ref": Proposal - "template": Proposal Comment Template - "reply": Proposal Comment (Optional) - "section": Section Reference - "category_id": Category Parameters (Optional) - -} - -"Proposal Comment"."ref"->"Proposal" -"Proposal Comment"."template"->"Proposal Comment Template" -"Proposal Comment"."reply"->"Proposal Comment": Optional -"Proposal Comment"."category_id"->"Category Parameters": Optional - - -``` - ### Validation TODO @@ -113,7 +88,7 @@ Reference to a Linked Document or Documents. This is the primary hierarchical reference to a related document. This is an Array of the format: - `[[DocumentID, DocumentVer, DocumentHash],...]` + `[[DocumentID, DocumentVer, DocumentHash],...]` * `DocumentID` is the [UUIDv7][RFC9562-V7] ID of the Document being referenced. * `DocumentVer` is the [UUIDv7][RFC9562-V7] Version of the Document being referenced. @@ -216,7 +191,6 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[application/json]: https://www.iana.org/assignments/media-types/application/json [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 [RFC8259]: https://www.rfc-editor.org/rfc/rfc8259.html 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 baccb9c969..0494dafc2f 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 @@ -9,26 +9,6 @@ are met in any Proposal Comment Template. The payload of a proposal comment template is controlled by its meta template. -```d2 layout=elk - -"Proposal Comment Meta Template": { - shape: sql_table - "content type": [application/schema+json] - "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f - "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f - "type [2]": b679ded3-0e7c-41ba-89f8-da62a17898ea - "type [3]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - "category_id": Category Parameters (Optional) - -} - -"Proposal Comment Meta Template"."category_id"->"Category Parameters": Optional - - -``` - ### Validation TODO @@ -145,7 +125,6 @@ New versions of this document may be published by: | Authors | Alex Pozhylenkov | | | Steven Johnson | -[application/schema+json]: https://datatracker.ietf.org/doc/draft-bhutton-json-schema/ [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema]: https://json-schema.org/draft-07 [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_template.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_comment_template.md index fcd9b16926..29b02d82bf 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 @@ -12,27 +12,6 @@ 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. -```d2 layout=elk - -"Proposal Comment Template": { - shape: sql_table - "content type": [application/schema+json] - "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f - "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea - "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - "template": Proposal Comment Meta Template (Optional) - "category_id": Category Parameters (Optional) - -} - -"Proposal Comment Template"."template"->"Proposal Comment Meta Template": Optional -"Proposal Comment Template"."category_id"->"Category Parameters": Optional - - -``` - ### Validation TODO @@ -158,7 +137,6 @@ New versions of this document may be published by: | Authors | Alex Pozhylenkov | | | Steven Johnson | -[application/schema+json]: https://datatracker.ietf.org/doc/draft-bhutton-json-schema/ [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema]: https://json-schema.org/draft-07 [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_meta_template.md index 6ebbbbc740..05f46cbe0f 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 @@ -9,25 +9,6 @@ are met in any Proposal Template. The payload of a proposal template is controlled by its meta template. -```d2 layout=elk - -"Proposal Meta Template": { - shape: sql_table - "content type": [application/schema+json] - "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f - "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f - "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - "category_id": Category Parameters (Optional) - -} - -"Proposal Meta Template"."category_id"->"Category Parameters": Optional - - -``` - ### Validation TODO @@ -144,7 +125,6 @@ New versions of this document may be published by: | Authors | Alex Pozhylenkov | | | Steven Johnson | -[application/schema+json]: https://datatracker.ietf.org/doc/draft-bhutton-json-schema/ [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema]: https://json-schema.org/draft-07 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode 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 0853f706fe..64760c7145 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 @@ -4,23 +4,6 @@ TODO -```d2 layout=elk - -"Proposal Moderation Action": { - shape: sql_table - "content type": [application/json] - "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 - "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - -} - - - -``` - ### Validation TODO @@ -111,6 +94,5 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[application/json]: https://www.iana.org/assignments/media-types/application/json [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_submission_action.md b/docs/src/architecture/08_concepts/signed_doc/docs/proposal_submission_action.md index 29aeb5d3dc..34cb92179c 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 @@ -19,27 +19,6 @@ the proposal will not be seen as submitted. The payload is a fixed format. -```d2 layout=elk - -"Proposal Submission Action": { - shape: sql_table - "content type": [application/json] - "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 - "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - "type [2]": 78927329-cfd9-4ea1-9c71-0e019b126a65 - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - "ref": Proposal - "category_id": Category Parameters - -} - -"Proposal Submission Action"."ref"->"Proposal" -"Proposal Submission Action"."category_id"->"Category Parameters" - - -``` - ### Validation TODO @@ -118,7 +97,7 @@ Reference to a Linked Document or Documents. This is the primary hierarchical reference to a related document. This is an Array of the format: - `[[DocumentID, DocumentVer, DocumentHash],...]` + `[[DocumentID, DocumentVer, DocumentHash],...]` * `DocumentID` is the [UUIDv7][RFC9562-V7] ID of the Document being referenced. * `DocumentVer` is the [UUIDv7][RFC9562-V7] Version of the Document being referenced. @@ -161,7 +140,7 @@ States: * `final` : All collaborators must publish a `final` status for the proposal to be `final`. * `draft` : Reverses the previous `final` state for a signer. * `hide` : Requests the proposal be hidden (not final, but a hidden draft). - `hide` is only actioned if sent by the author, for a collaborator its synonymous with `draft`. + `hide` is only actioned if sent by the author, for a collaborator its synonymous with `draft`. Schema : @@ -228,7 +207,6 @@ New versions of this document may be published by: | | Steven Johnson | [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 -[application/json]: https://www.iana.org/assignments/media-types/application/json [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 [RFC8259]: https://www.rfc-editor.org/rfc/rfc8259.html 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 1f2fdaa4ac..031a99d43a 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 @@ -12,26 +12,6 @@ linked to a brand/campaign or category via the template used by the proposal. The payload of a proposal is controlled by its template. -```d2 layout=elk - -"Proposal Template": { - shape: sql_table - "content type": [application/schema+json] - "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f - "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc - "id": [UUIDv7][RFC9562-V7] - "ver": [UUIDv7][RFC9562-V7] - "template": Proposal Meta Template (Optional) - "category_id": Category Parameters (Optional) - -} - -"Proposal Template"."template"->"Proposal Meta Template": Optional -"Proposal Template"."category_id"->"Category Parameters": Optional - - -``` - ### Validation TODO @@ -157,7 +137,6 @@ New versions of this document may be published by: | Authors | Alex Pozhylenkov | | | Steven Johnson | -[application/schema+json]: https://datatracker.ietf.org/doc/draft-bhutton-json-schema/ [RFC9052-HeaderParameters]: https://www.rfc-editor.org/rfc/rfc8152#section-3.1 [JSON Schema]: https://json-schema.org/draft-07 [CC-BY-4.0]: https://creativecommons.org/licenses/by/4.0/legalcode diff --git a/specs/gen_docs/gen_docs_page_md.py b/specs/gen_docs/gen_docs_page_md.py index cbb573f6ee..3bbb8aa4d2 100644 --- a/specs/gen_docs/gen_docs_page_md.py +++ b/specs/gen_docs/gen_docs_page_md.py @@ -93,7 +93,16 @@ def document_signers(name: str, doc_defs: dict) -> str: def gen_docs_page_md(name: str, doc_defs: dict) -> str: """ Generate an individual Documents Specification Page file from the definitions. + + TODO: Add this to insert an image (needs link escaping fixed) + + ```d2 layout=elk + {doc_d1} + ``` + """ + + _doc_d2 = gen_doc_d2(name, doc_defs) return f""" # {name} @@ -101,10 +110,6 @@ def gen_docs_page_md(name: str, doc_defs: dict) -> str: {doc_defs["docs"][name].get("description", "TODO")} -```d2 layout=elk -{gen_doc_d2(name, doc_defs)} -``` - ### Validation {doc_defs["docs"][name].get("validation", "TODO")} From 403479975166fbf73ac8c9fb0a49e07207a86939 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Fri, 4 Apr 2025 11:40:40 +0700 Subject: [PATCH 35/35] fix: Add individual document relationship images to each page --- .../signed_doc/doc_relationships.d2 | 2 +- .../signed_doc/doc_relationships.svg | 564 +++++++++--------- .../signed_doc/docs/brand_parameters.md | 13 +- .../signed_doc/docs/campaign_parameters.md | 13 +- .../signed_doc/docs/category_parameters.md | 13 +- .../docs/comment_action_document.md | 15 +- .../signed_doc/docs/election_parameters.md | 13 +- .../08_concepts/signed_doc/docs/proposal.md | 19 +- .../signed_doc/docs/proposal_comment.md | 24 +- .../docs/proposal_comment_meta_template.md | 19 +- .../docs/proposal_comment_template.md | 20 +- .../signed_doc/docs/proposal_meta_template.md | 18 +- .../docs/proposal_moderation_action.md | 15 +- .../docs/proposal_submission_action.md | 24 +- .../signed_doc/docs/proposal_template.md | 19 +- .../08_concepts/signed_doc/metadata.md | 2 +- .../08_concepts/signed_doc/spec.md | 2 +- .../08_concepts/signed_doc/types.md | 2 +- specs/gen_docs/gen_docs_page_md.py | 13 +- .../gen_docs_relationship_diagram_d2.py | 19 +- specs/gen_docs/generate_docs.py | 35 +- 21 files changed, 544 insertions(+), 320 deletions(-) diff --git a/docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 index 2fb07fe721..5a188d40d2 100644 --- a/docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 +++ b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.d2 @@ -18,7 +18,7 @@ copyright: |~md | --- | --- | | License | This document is licensed under CC-BY-4.0 | | Created | 2024-12-27 | -| Modified | 2025-04-03 | +| Modified | 2025-04-04 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg index 4a1efc5921..8611613820 100644 --- a/docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg +++ b/docs/src/architecture/08_concepts/signed_doc/doc_relationships.svg @@ -1,20 +1,20 @@ -

Signed Document Relationship Hierarchy

@@ -856,7 +856,7 @@ Modified -2025-04-03 +2025-04-04 Authors @@ -868,7 +868,7 @@ -
Brand Parameterscontent typeapplication/jsontype [0]ebcabeeb-5bc5-4f95-91e8-cab8ca724172idUUIDv7verUUIDv7Campaign Parameterscontent typeapplication/jsontype [0]5ef32d5d-f240-462c-a7a4-ba4af221fa23idUUIDv7verUUIDv7Category Parameterscontent typeapplication/jsontype [0]818938c3-3139-4daa-afe6-974c78488e95idUUIDv7verUUIDv7Comment Action Documentcontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]a5d232b8-5e03-4117-9afd-be32b878fcddidUUIDv7verUUIDv7Election Parameterscontent typeapplication/jsontype [0]788ff4c6-d65a-451f-bb33-575fe056b411idUUIDv7verUUIDv7Proposalcontent typeapplication/jsontype [0]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7templateProposal TemplatecollaboratorsCollaborators Reference Listcategory_idCategory Parameters (Optional)Proposal Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7templateProposal Meta Template (Optional)category_idCategory Parameters (Optional)Proposal Commentcontent typeapplication/jsontype [0]b679ded3-0e7c-41ba-89f8-da62a17898eatype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7refProposaltemplateProposal Comment TemplatereplyProposal Comment (Optional)sectionSection Referencecategory_idCategory Parameters (Optional)Proposal Comment Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7templateProposal Comment Meta Template (Optional)category_idCategory Parameters (Optional)Proposal Comment Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]b679ded3-0e7c-41ba-89f8-da62a17898eatype [3]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7category_idCategory Parameters (Optional)Proposal Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7category_idCategory Parameters (Optional)Proposal Moderation Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]a5d232b8-5e03-4117-9afd-be32b878fcddidUUIDv7verUUIDv7Proposal Submission Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]78927329-cfd9-4ea1-9c71-0e019b126a65idUUIDv7verUUIDv7refProposalcategory_idCategory Parameters Optional<reply> OptionalOptionalOptionalOptionalOptionalOptionalOptionalOptional +Brand Parameterscontent typeapplication/jsontype [0]ebcabeeb-5bc5-4f95-91e8-cab8ca724172idUUIDv7verUUIDv7Campaign Parameterscontent typeapplication/jsontype [0]5ef32d5d-f240-462c-a7a4-ba4af221fa23idUUIDv7verUUIDv7Category Parameterscontent typeapplication/jsontype [0]818938c3-3139-4daa-afe6-974c78488e95idUUIDv7verUUIDv7Comment Action Documentcontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]a5d232b8-5e03-4117-9afd-be32b878fcddidUUIDv7verUUIDv7Election Parameterscontent typeapplication/jsontype [0]788ff4c6-d65a-451f-bb33-575fe056b411idUUIDv7verUUIDv7Proposalcontent typeapplication/jsontype [0]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7templateProposal TemplatecollaboratorsCollaborators Reference Listcategory_idCategory Parameters (Optional)Proposal Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7templateProposal Meta Template (Optional)category_idCategory Parameters (Optional)Proposal Commentcontent typeapplication/jsontype [0]b679ded3-0e7c-41ba-89f8-da62a17898eatype [1]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7refProposaltemplateProposal Comment TemplatereplyProposal Comment (Optional)sectionSection Referencecategory_idCategory Parameters (Optional)Proposal Comment Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]b679ded3-0e7c-41ba-89f8-da62a17898eatype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7templateProposal Comment Meta Template (Optional)category_idCategory Parameters (Optional)Proposal Comment Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]b679ded3-0e7c-41ba-89f8-da62a17898eatype [3]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7category_idCategory Parameters (Optional)Proposal Meta Templatecontent typeapplication/schema+jsontype [0]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [1]0ce8ab38-9258-4fbc-a62e-7faa6e58318ftype [2]7808d2ba-d511-40af-84e8-c0d1625fdfdcidUUIDv7verUUIDv7category_idCategory Parameters (Optional)Proposal Moderation Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]a5d232b8-5e03-4117-9afd-be32b878fcddidUUIDv7verUUIDv7Proposal Submission Actioncontent typeapplication/jsontype [0]5e60e623-ad02-4a1b-a1ac-406db978ee48type [1]7808d2ba-d511-40af-84e8-c0d1625fdfdctype [2]78927329-cfd9-4ea1-9c71-0e019b126a65idUUIDv7verUUIDv7refProposalcategory_idCategory Parameters Optional<reply> OptionalOptionalOptionalOptionalOptionalOptionalOptionalOptional 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 d709134968..75563da5b0 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 @@ -4,6 +4,17 @@ TODO +```d2 layout="elk" +"Brand Parameters": { + shape: sql_table + "content type": application/json + "type [0]": ebcabeeb-5bc5-4f95-91e8-cab8ca724172 + "id": UUIDv7 + "ver": UUIDv7 + +} +``` + ### Validation TODO @@ -89,7 +100,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-04-03 | +| Modified | 2025-04-04 | | 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 b5f0a95644..db8819dd94 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 @@ -4,6 +4,17 @@ TODO +```d2 layout="elk" +"Campaign Parameters": { + shape: sql_table + "content type": application/json + "type [0]": 5ef32d5d-f240-462c-a7a4-ba4af221fa23 + "id": UUIDv7 + "ver": UUIDv7 + +} +``` + ### Validation TODO @@ -89,7 +100,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-04-03 | +| Modified | 2025-04-04 | | 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 32449573ca..0a92b2d0b7 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 @@ -4,6 +4,17 @@ TODO +```d2 layout="elk" +"Category Parameters": { + shape: sql_table + "content type": application/json + "type [0]": 818938c3-3139-4daa-afe6-974c78488e95 + "id": UUIDv7 + "ver": UUIDv7 + +} +``` + ### Validation TODO @@ -89,7 +100,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-04-03 | +| Modified | 2025-04-04 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md b/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md index b3ef1d239c..ad3713daaa 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/comment_action_document.md @@ -4,6 +4,19 @@ TODO +```d2 layout="elk" +"Comment Action Document": { + shape: sql_table + "content type": application/json + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd + "id": UUIDv7 + "ver": UUIDv7 + +} +``` + ### Validation TODO @@ -89,7 +102,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-04-03 | +| Modified | 2025-04-04 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md b/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md index 6b0a7b0203..132fa96e3a 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/election_parameters.md @@ -4,6 +4,17 @@ TODO +```d2 layout="elk" +"Election Parameters": { + shape: sql_table + "content type": application/json + "type [0]": 788ff4c6-d65a-451f-bb33-575fe056b411 + "id": UUIDv7 + "ver": UUIDv7 + +} +``` + ### Validation TODO @@ -89,7 +100,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-04-03 | +| Modified | 2025-04-04 | | 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 094de9d66e..12a9edea7c 100644 --- a/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md +++ b/docs/src/architecture/08_concepts/signed_doc/docs/proposal.md @@ -13,6 +13,23 @@ linked to a brand/campaign or category via the template used by the proposal. The payload of a proposal is controlled by its template. +```d2 layout="elk" +"Proposal": { + shape: sql_table + "content type": application/json + "type [0]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": UUIDv7 + "ver": UUIDv7 + "template": Proposal Template + "collaborators": Collaborators Reference List + "category_id": Category Parameters (Optional) + +} + +"Proposal"."template"->"Proposal Template" +"Proposal"."category_id"->"Category Parameters": Optional +``` + ### Validation TODO @@ -157,7 +174,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-04-03 | +| Modified | 2025-04-04 | | 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 047ba2643f..87468a74ca 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 @@ -11,6 +11,28 @@ 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. +```d2 layout="elk" +"Proposal Comment": { + shape: sql_table + "content type": application/json + "type [0]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": UUIDv7 + "ver": UUIDv7 + "ref": Proposal + "template": Proposal Comment Template + "reply": Proposal Comment (Optional) + "section": Section Reference + "category_id": Category Parameters (Optional) + +} + +"Proposal Comment"."ref"->"Proposal" +"Proposal Comment"."template"->"Proposal Comment Template" +"Proposal Comment"."reply"->"Proposal Comment": Optional +"Proposal Comment"."category_id"->"Category Parameters": Optional +``` + ### Validation TODO @@ -186,7 +208,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-04-03 | +| Modified | 2025-04-04 | | 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 0494dafc2f..9a373c6a4f 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 @@ -9,6 +9,23 @@ are met in any Proposal Comment Template. The payload of a proposal comment template is controlled by its meta template. +```d2 layout="elk" +"Proposal Comment Meta Template": { + shape: sql_table + "content type": application/schema+json + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [2]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [3]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": UUIDv7 + "ver": UUIDv7 + "category_id": Category Parameters (Optional) + +} + +"Proposal Comment Meta Template"."category_id"->"Category Parameters": Optional +``` + ### Validation TODO @@ -121,7 +138,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-04-03 | +| Modified | 2025-04-04 | | 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 29b02d82bf..1f8a19e751 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 @@ -12,6 +12,24 @@ 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. +```d2 layout="elk" +"Proposal Comment Template": { + shape: sql_table + "content type": application/schema+json + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": b679ded3-0e7c-41ba-89f8-da62a17898ea + "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": UUIDv7 + "ver": UUIDv7 + "template": Proposal Comment Meta Template (Optional) + "category_id": Category Parameters (Optional) + +} + +"Proposal Comment Template"."template"->"Proposal Comment Meta Template": Optional +"Proposal Comment Template"."category_id"->"Category Parameters": Optional +``` + ### Validation TODO @@ -133,7 +151,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-04-03 | +| Modified | 2025-04-04 | | 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 05f46cbe0f..8c9915a8c4 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 @@ -9,6 +9,22 @@ are met in any Proposal Template. The payload of a proposal template is controlled by its meta template. +```d2 layout="elk" +"Proposal Meta Template": { + shape: sql_table + "content type": application/schema+json + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [2]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": UUIDv7 + "ver": UUIDv7 + "category_id": Category Parameters (Optional) + +} + +"Proposal Meta Template"."category_id"->"Category Parameters": Optional +``` + ### Validation TODO @@ -121,7 +137,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-04-03 | +| Modified | 2025-04-04 | | 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 64760c7145..7aca07eecf 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 @@ -4,6 +4,19 @@ TODO +```d2 layout="elk" +"Proposal Moderation Action": { + shape: sql_table + "content type": application/json + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "type [2]": a5d232b8-5e03-4117-9afd-be32b878fcdd + "id": UUIDv7 + "ver": UUIDv7 + +} +``` + ### Validation TODO @@ -89,7 +102,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-04-03 | +| Modified | 2025-04-04 | | 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 34cb92179c..f05b8dfbda 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 @@ -19,6 +19,24 @@ the proposal will not be seen as submitted. The payload is a fixed format. +```d2 layout="elk" +"Proposal Submission Action": { + shape: sql_table + "content type": application/json + "type [0]": 5e60e623-ad02-4a1b-a1ac-406db978ee48 + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "type [2]": 78927329-cfd9-4ea1-9c71-0e019b126a65 + "id": UUIDv7 + "ver": UUIDv7 + "ref": Proposal + "category_id": Category Parameters + +} + +"Proposal Submission Action"."ref"->"Proposal" +"Proposal Submission Action"."category_id"->"Category Parameters" +``` + ### Validation TODO @@ -97,7 +115,7 @@ Reference to a Linked Document or Documents. This is the primary hierarchical reference to a related document. This is an Array of the format: - `[[DocumentID, DocumentVer, DocumentHash],...]` + `[[DocumentID, DocumentVer, DocumentHash],...]` * `DocumentID` is the [UUIDv7][RFC9562-V7] ID of the Document being referenced. * `DocumentVer` is the [UUIDv7][RFC9562-V7] Version of the Document being referenced. @@ -140,7 +158,7 @@ States: * `final` : All collaborators must publish a `final` status for the proposal to be `final`. * `draft` : Reverses the previous `final` state for a signer. * `hide` : Requests the proposal be hidden (not final, but a hidden draft). - `hide` is only actioned if sent by the author, for a collaborator its synonymous with `draft`. + `hide` is only actioned if sent by the author, for a collaborator its synonymous with `draft`. Schema : @@ -202,7 +220,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-04-03 | +| Modified | 2025-04-04 | | 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 031a99d43a..4886c1c58b 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 @@ -12,6 +12,23 @@ linked to a brand/campaign or category via the template used by the proposal. The payload of a proposal is controlled by its template. +```d2 layout="elk" +"Proposal Template": { + shape: sql_table + "content type": application/schema+json + "type [0]": 0ce8ab38-9258-4fbc-a62e-7faa6e58318f + "type [1]": 7808d2ba-d511-40af-84e8-c0d1625fdfdc + "id": UUIDv7 + "ver": UUIDv7 + "template": Proposal Meta Template (Optional) + "category_id": Category Parameters (Optional) + +} + +"Proposal Template"."template"->"Proposal Meta Template": Optional +"Proposal Template"."category_id"->"Category Parameters": Optional +``` + ### Validation TODO @@ -133,7 +150,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-04-03 | +| Modified | 2025-04-04 | | 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 9e67d78917..b088993e4f 100644 --- a/docs/src/architecture/08_concepts/signed_doc/metadata.md +++ b/docs/src/architecture/08_concepts/signed_doc/metadata.md @@ -308,7 +308,7 @@ optional for the referenced document. | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-04-03 | +| Modified | 2025-04-04 | | 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 506e94ef31..7444f19ecb 100644 --- a/docs/src/architecture/08_concepts/signed_doc/spec.md +++ b/docs/src/architecture/08_concepts/signed_doc/spec.md @@ -94,7 +94,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-04-03 | +| Modified | 2025-04-04 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/docs/src/architecture/08_concepts/signed_doc/types.md b/docs/src/architecture/08_concepts/signed_doc/types.md index 4860f055da..20ff6ba1db 100644 --- a/docs/src/architecture/08_concepts/signed_doc/types.md +++ b/docs/src/architecture/08_concepts/signed_doc/types.md @@ -49,7 +49,7 @@ All Defined Document Types | --- | --- | | License | This document is licensed under [CC-BY-4.0] | | Created | 2024-12-27 | -| Modified | 2025-04-03 | +| Modified | 2025-04-04 | | Authors | Alex Pozhylenkov | | | Steven Johnson | diff --git a/specs/gen_docs/gen_docs_page_md.py b/specs/gen_docs/gen_docs_page_md.py index 3bbb8aa4d2..71056eeece 100644 --- a/specs/gen_docs/gen_docs_page_md.py +++ b/specs/gen_docs/gen_docs_page_md.py @@ -93,16 +93,9 @@ def document_signers(name: str, doc_defs: dict) -> str: def gen_docs_page_md(name: str, doc_defs: dict) -> str: """ Generate an individual Documents Specification Page file from the definitions. - - TODO: Add this to insert an image (needs link escaping fixed) - - ```d2 layout=elk - {doc_d1} - ``` - """ - _doc_d2 = gen_doc_d2(name, doc_defs) + doc_d2 = gen_doc_d2(name, doc_defs, depth=1, stand_alone=True).strip() return f""" # {name} @@ -110,6 +103,10 @@ def gen_docs_page_md(name: str, doc_defs: dict) -> str: {doc_defs["docs"][name].get("description", "TODO")} +```d2 layout="elk" +{doc_d2} +``` + ### Validation {doc_defs["docs"][name].get("validation", "TODO")} diff --git a/specs/gen_docs/gen_docs_relationship_diagram_d2.py b/specs/gen_docs/gen_docs_relationship_diagram_d2.py index ffc8823628..6f32c59937 100644 --- a/specs/gen_docs/gen_docs_relationship_diagram_d2.py +++ b/specs/gen_docs/gen_docs_relationship_diagram_d2.py @@ -1,4 +1,5 @@ # Generate the spec.md file +# from common import doc_ref_link, insert_copyright from common import insert_copyright doc_config = """ @@ -19,7 +20,7 @@ """ -def gen_doc_d2(doc: str, doc_defs: dict) -> str: +def gen_doc_d2(doc: str, doc_defs: dict, depth=0, stand_alone=False) -> str: """ Generate an individual d2 table for an individual document. """ @@ -43,17 +44,21 @@ def gen_doc_d2(doc: str, doc_defs: dict) -> str: if doc_metadata[meta]["required"] == "optional": metadata_rows += f' "{meta}": {ref_doc} (Optional)\n' if ref_doc == doc: - ref_links += f'"{doc}"."{meta}"->"{doc_metadata[meta]["type"]}": <{meta}> Optional\n' + ref_links += ( + f'"{doc}"."{meta}"->"{ref_doc}": <{meta}> Optional\n' + ) else: - ref_links += f'"{doc}"."{meta}"->"{doc_metadata[meta]["type"]}": Optional\n' + ref_links += f'"{doc}"."{meta}"->"{ref_doc}": Optional\n' else: metadata_rows += f' "{meta}": {ref_doc}\n' if ref_doc == doc: - ref_links += f'"{doc}"."{meta}"->"{doc_metadata[meta]["type"]}": <{meta}>n' + ref_links += f'"{doc}"."{meta}"->"{ref_doc}": <{meta}>n' else: - ref_links += ( - f'"{doc}"."{meta}"->"{doc_metadata[meta]["type"]}"\n' - ) + ref_links += f'"{doc}"."{meta}"->"{ref_doc}"\n' + # if stand_alone: + # if ref_doc != doc: + # ref_links += f'"{ref_doc}".shape=document\n' + # ref_links += f'"{ref_doc}".link={doc_ref_link(ref_doc, depth)}\n' else: metadata_rows += f' "{meta}": {doc_metadata[meta]["format"]}\n' diff --git a/specs/gen_docs/generate_docs.py b/specs/gen_docs/generate_docs.py index 4ce0e5cfeb..f4aff5e0f2 100755 --- a/specs/gen_docs/generate_docs.py +++ b/specs/gen_docs/generate_docs.py @@ -107,6 +107,35 @@ def add_metadata_links(file_data: str, doc_data: dict, depth: int = 0) -> str: return file_data +def code_block_aware_re_subn( + linkNameRegex, replacement, file_data: str +) -> tuple[str, int]: + """ + Do a multiline regex replacement, but ignore anything inside a code block. + """ + lines = file_data.splitlines() + new_file_data = "" + cnt = 0 + in_code_block = False + for line in lines: + if line.strip().startswith("```"): + in_code_block = not in_code_block + + if in_code_block: + this_cnt = 0 + else: + (line, this_cnt) = re.subn( + linkNameRegex, + replacement, + line, + flags=re.IGNORECASE, + ) + cnt += this_cnt + new_file_data += line + "\n" + + return (new_file_data, cnt) + + def add_reference_links(file_data, doc_data) -> str: """ Add Markdown reference links to the document. @@ -127,21 +156,19 @@ def add_reference_links(file_data, doc_data) -> str: linkNameRegex = f"(^|\\s)({escLinkName})(\\.|\\s|$)" if linkName in linkAka: replacement = f"\\1[\\2][{linkAka[linkName]}]\\3" - (file_data, cnt) = re.subn( + (file_data, cnt) = code_block_aware_re_subn( linkNameRegex, replacement, file_data, - flags=re.IGNORECASE | re.MULTILINE, ) if cnt > 0: actualLinksUsed[linkAka[linkName]] = links[linkAka[linkName]] else: replacement = r"\1[\2]\3" - (file_data, cnt) = re.subn( + (file_data, cnt) = code_block_aware_re_subn( linkNameRegex, replacement, file_data, - flags=re.IGNORECASE | re.MULTILINE, ) if cnt > 0: actualLinksUsed[linkName] = links[linkName]