|
| 1 | +--- |
| 2 | +Title: Parameters Hierarchy and Pub/Sub Discovery |
| 3 | +Authors: |
| 4 | + - Steven Johnson <[email protected]> |
| 5 | +Created: 2025-11-05 |
| 6 | +order: 1 |
| 7 | +--- |
| 8 | + |
| 9 | +## Abstract |
| 10 | + |
| 11 | +Explains how Brand, Campaign, Category, and Contest Parameters relate, |
| 12 | +and how clients discover and validate them in a decentralized pub/sub network |
| 13 | +using signed documents and content-addressed references. |
| 14 | + |
| 15 | +## Overview |
| 16 | + |
| 17 | +Parameters control the behavior, timelines, and branding for the system at different scopes: |
| 18 | + |
| 19 | +* [Brand Parameters](../docs/brand_parameters.md): global root for a brand. |
| 20 | +* [Campaign Parameters](../docs/campaign_parameters.md): defined under a brand. |
| 21 | +* [Category Parameters](../docs/category_parameters.md): defined under a campaign. |
| 22 | +* [Contest Parameters](../docs/contest_parameters.md): defined under a brand, campaign, or category. |
| 23 | + |
| 24 | +Each parameters document is a signed document that: |
| 25 | + |
| 26 | +* Uses [COSE Sign][RFC9052-CoseSign] with a Catalyst ID `kid`. |
| 27 | + See: [COSE Header Parameters](../spec.md#content-type). |
| 28 | +* Is content-addressed via a `document_ref` locator (CBOR Tag 42 `cid`). |
| 29 | + See: [Document Reference](../metadata.md#document-reference). |
| 30 | +* Links through `metadata.parameters` to its parent in the hierarchy. |
| 31 | + See: [Parameters metadata](../metadata.md#parameters). |
| 32 | +* Is validated by its referenced template. |
| 33 | + See: [Contest Parameters Form Template](../docs/contest_parameters_form_template.md) and related templates. |
| 34 | + |
| 35 | +## Relationships |
| 36 | + |
| 37 | +* Brand → Campaign → Category form a strict chain via [`metadata.parameters`](../metadata.md#parameters). |
| 38 | +* Contest Parameters link to one of the system-scoped parameters (brand/campaign/category) via |
| 39 | + [`metadata.parameters`](../metadata.md#parameters) and are thus “anchored” to that chain. |
| 40 | +* Templates can be defined at any of these levels, provided their own |
| 41 | + [`parameters`](../metadata.md#parameters) link transitive-up to the same brand root. |
| 42 | + |
| 43 | +```mermaid |
| 44 | +erDiagram |
| 45 | + BRAND_PARAMETERS ||--o{ CAMPAIGN_PARAMETERS : parameters |
| 46 | + CAMPAIGN_PARAMETERS ||--o{ CATEGORY_PARAMETERS : parameters |
| 47 | + BRAND_PARAMETERS ||--o{ CONTEST_PARAMETERS : anchors |
| 48 | + CAMPAIGN_PARAMETERS ||--o{ CONTEST_PARAMETERS : anchors |
| 49 | + CATEGORY_PARAMETERS ||--o{ CONTEST_PARAMETERS : anchors |
| 50 | +
|
| 51 | + BRAND_PARAMETERS { |
| 52 | + uuidv7 id |
| 53 | + uuidv7 ver |
| 54 | + } |
| 55 | + CAMPAIGN_PARAMETERS { |
| 56 | + uuidv7 id |
| 57 | + uuidv7 ver |
| 58 | + ref brand_parameters |
| 59 | + } |
| 60 | + CATEGORY_PARAMETERS { |
| 61 | + uuidv7 id |
| 62 | + uuidv7 ver |
| 63 | + ref campaign_parameters |
| 64 | + } |
| 65 | + CONTEST_PARAMETERS { |
| 66 | + uuidv7 id |
| 67 | + uuidv7 ver |
| 68 | + ref brand_or_campaign_or_category |
| 69 | + } |
| 70 | +``` |
| 71 | + |
| 72 | +## Document Identity and Versioning |
| 73 | + |
| 74 | +* [`id`](../metadata.md#id) and [`ver`](../metadata.md#ver) are [UUIDv7][RFC9562-V7] values; |
| 75 | +* [`id`](../metadata.md#id) is created once; |
| 76 | +* [`ver`](../metadata.md#ver) increases over time as new versions of the same parameters document are issued. |
| 77 | + |
| 78 | +For example a Brand has ONE Parameters [`id`](../metadata.md#id), but that document may have |
| 79 | +multiple versions over time as [`ver`](../metadata.md#ver) increases. |
| 80 | +This defines that specific brand identity while allowing updates to its parameters. |
| 81 | + |
| 82 | +Whereas Campaign, Category, and Contest Parameters each have their own |
| 83 | +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver), |
| 84 | +that is specific to that parameters document. |
| 85 | +Such that a Brand may have multiple old or concurrent Campaigns, each with their own |
| 86 | +[`id`](../metadata.md#id) and [`ver`](../metadata.md#ver), etc. |
| 87 | + |
| 88 | +## Pub/Sub Discovery Model |
| 89 | + |
| 90 | +Documents are published in bound topics. |
| 91 | +Each Topic collects a subset of documents based on their anchoring parameters document, and optionally their type. |
| 92 | + |
| 93 | +### Global Root |
| 94 | + |
| 95 | +The root of discovery is known as the Global root. |
| 96 | +The pub/sub system assumes that valid documents once published will be retained indefinitely. |
| 97 | +In order to prevent buildup and bloat the Global root will rotate through time. |
| 98 | +It is formed of the path: |
| 99 | +`catalyst/signed-docs/<start>/<end>` |
| 100 | +Where `<start>` and `<end>` are Unix Epoch Timestamps (UTC). |
| 101 | + |
| 102 | +* `<start>` is aligned to the UTC Calendar start of the current year, i.e. (01-01-XX 00:00:00). |
| 103 | +* `<end>` is aligned to the UTC Calendar start of the second consecutive year, i.e. (01-01-XX+2 00:00:00). |
| 104 | + |
| 105 | +Only ACTIVE `Brand` Parameters and associated Template documents are published to the Global root topic. |
| 106 | +Because `<start>` is incremented every year, there is a natural rotation of the Global root, |
| 107 | +and a 1-year overlap between two consecutive Global roots. |
| 108 | +This means that ACTIVE Brand documents may be co-published in two consecutive Global root topics |
| 109 | +for a period of up to one year. |
| 110 | + |
| 111 | +This creates a natural sliding window which allows old, |
| 112 | +unused or revoked Brand documents to age out of the system over time. |
| 113 | + |
| 114 | +The **ONLY** Documents which may be validly published to the Global root topic are `Brand` Parameters documents, |
| 115 | +which are signed by the appropriate Administration Key. |
| 116 | + |
| 117 | +Any other document type, or documents signed by other keys, |
| 118 | +published to the Global root topic must be rejected by subscribers. |
| 119 | + |
| 120 | +#### Example |
| 121 | + |
| 122 | +A Global Root that starts on January 1st, 2025 and ends on January 1st, 2027 would have the path: |
| 123 | +`catalyst/signed-docs/1735689600/1798761600` |
| 124 | + |
| 125 | +### Sub Document Topics |
| 126 | + |
| 127 | +Beneath the Global Root exists a hierarchy of topics for each anchoring parameters document, |
| 128 | +and optionally by document type. |
| 129 | + |
| 130 | +The general format of these topics is: |
| 131 | +`catalyst/signed-docs/<doc-id>[/<doc-type>]` |
| 132 | +Where: |
| 133 | + |
| 134 | +* `<doc-id>` is the [`id`](../metadata.md#id) of the anchoring parameters document. |
| 135 | + * For Campaign Parameters, this is the Brand's [`id`](../metadata.md#id). |
| 136 | + * For Category Parameters, this is the Campaign's [`id`](../metadata.md#id). |
| 137 | + * For Contest Parameters, this is the Brand's, Campaign's, or Category's [`id`](../metadata.md#id) as appropriate. |
| 138 | + * Note this is ONLY the [`id`](../metadata.md#id) value, NOT the [`ver`](../metadata.md#ver) this means that all |
| 139 | + versions of documents anchored to that parameters document are published to the same topic. |
| 140 | +* `<doc-type>` is optional, and if present only documents of that [UUIDv4][RFC9562-V4] type may be published to the topic. |
| 141 | + |
| 142 | +Discovery Happens by subscribing to the Global root topic to find ACTIVE Brand Parameters documents. |
| 143 | +Once discovered, the subscriber can then subscribe to an appropriate brands' topic, |
| 144 | +which allows discovery of all Campaign or Contest Parameters or any other document type anchored to that brand. |
| 145 | +From there, the subscriber can continue down the hierarchy by subscribing to Campaign topics to find |
| 146 | +Category or Contest Parameters documents anchored to that campaign, and so on. |
| 147 | + |
| 148 | +Producers publish COSE_Sign blobs plus their `document_ref` (CID) on these topics. |
| 149 | + |
| 150 | +Consumers: |
| 151 | + |
| 152 | +1. Verify signature (`kid`), content type, and deterministic CBOR/JSON as applicable. |
| 153 | +2. Verify [`type`](../metadata.md#type), [`id`](../metadata.md#id), [`ver`](../metadata.md#ver), |
| 154 | + and that `ver ≥ id` (UUIDv7 ordering). |
| 155 | +3. Verify [`template`](../metadata.md#template) exists and the payload validates against that template. |
| 156 | +4. Verify [`parameters`](../metadata.md#parameters) links to the correct parent in the chain and is |
| 157 | + consistent transitively up to the brand. |
| 158 | +5. Verify the Document is published to the correct Topic according to its anchoring parameters document and type. |
| 159 | +6. Apply [`revocations`](../metadata.md#revocations) and prefer the latest valid |
| 160 | + [`ver`](../metadata.md#ver) for each [`id`](../metadata.md#id). |
| 161 | +7. Optionally follow [`chain`](../metadata.md#chain) for lineage and completeness. |
| 162 | + |
| 163 | +#### Global Root and Sub-document Topics Hierarchy (Mermaid) |
| 164 | + |
| 165 | +```mermaid |
| 166 | +--- |
| 167 | +config: |
| 168 | + flowchart: |
| 169 | + htmlLabels: false |
| 170 | +--- |
| 171 | +flowchart TD |
| 172 | + %% Styles |
| 173 | + classDef topic fill:#e8f2ff,stroke:#1d71b8,color:#0b2b4b,border-radius:6px |
| 174 | + classDef doc fill:#f7f7f7,stroke:#888,border-radius:6px |
| 175 | +
|
| 176 | + id@{ shape: notch-rect, label: "Document IDs |
| 177 | + *B*=**019a52a2-9b9c-7c7e-90bf-ab025ed5451f** |
| 178 | + *C*=**019a52a8-058e-7e50-92e4-e097da29cef5** |
| 179 | + *K*=**019a52a8-058e-7e50-92e4-e097da29cef5** |
| 180 | + *V1*=**019a52a8-058e-7e50-92e4-e097da29cef5** |
| 181 | + *V2*=**019a52a8-058e-7e50-92e4-e097da29cef5** |
| 182 | + " } |
| 183 | +
|
| 184 | + %% Global Root window |
| 185 | + GR@{ shape: docs, label: "catalyst/signed-docs/<start>/<end> |
| 186 | + (**Global Root**)" } |
| 187 | + class GR topic |
| 188 | +
|
| 189 | + %% Discover active Brand Parameters from Global Root |
| 190 | + B@{ shape: tag-doc, label: "Brand Parameters (id=*B*)" } |
| 191 | + class B doc |
| 192 | + GR --Discover--> B |
| 193 | +
|
| 194 | + %% Brand-anchored topic (all docs anchored to B; optional filtering by doc-type) |
| 195 | + TB@{ shape: docs, label: "catalyst/signed-docs/*B* |
| 196 | + (**Brand Parameter Anchored Documents**)" } |
| 197 | + class TB topic |
| 198 | + B --Subscribe--> TB |
| 199 | +
|
| 200 | + %% Discover active Campaign Parameters under Brand |
| 201 | + C@{ shape: tag-doc, label: "Campaign Parameters (id=*C*)" } |
| 202 | + class C doc |
| 203 | + TB --Discover--> C |
| 204 | +
|
| 205 | +
|
| 206 | + %% Campaign under Brand B |
| 207 | + TCB@{ shape: docs, label: "catalyst/signed-docs/*C* |
| 208 | + (**Campaign Parameter Anchored Documents**)" } |
| 209 | + class TCB topic |
| 210 | + C --Subscribe--> TCB |
| 211 | +
|
| 212 | + %% Discover active Categories under Campaign |
| 213 | + K@{ shape: tag-doc, label: "Category Parameters (id=*K*)" } |
| 214 | + class K doc |
| 215 | + TCB --Discover--> K |
| 216 | +
|
| 217 | + %% Category under Campaign |
| 218 | + KC@{ shape: docs, label: "catalyst/signed-docs/*K* |
| 219 | + (**Category Parameter Anchored Documents**)" } |
| 220 | + class KC topic |
| 221 | + K --Subscribe--> KC |
| 222 | +
|
| 223 | + %% Discover active Contests under Campaign |
| 224 | + CT1@{ shape: tag-doc, label: "Contest Parameters (id=*V1*)" } |
| 225 | + class CT1 doc |
| 226 | + TCB --Discover--> CT1 |
| 227 | +
|
| 228 | + %% Contest under Campaign |
| 229 | + CTv1@{ shape: docs, label: "catalyst/signed-docs/*V1* |
| 230 | + (**Contest Anchored Documents - Campaign**)" } |
| 231 | + CT1 --Subscribe--> CTv1 |
| 232 | + class CTv1 topic |
| 233 | +
|
| 234 | + %% Discover active Contests under Campaign |
| 235 | + CT2@{ shape: tag-doc, label: "Contest Parameters (id=*V2*)" } |
| 236 | + class CT2 doc |
| 237 | + KC --Discover--> CT2 |
| 238 | +
|
| 239 | + %% Contest under Category |
| 240 | + CTv2@{ shape: docs, label: "catalyst/signed-docs/*V1* |
| 241 | + (**Contest Anchored Documents - Category**)" } |
| 242 | + CT2 --Subscribe--> CTv2 |
| 243 | + class CTv2 topic |
| 244 | +
|
| 245 | + %% Note |
| 246 | + note@{ shape: flag, label: "Anchoring uses the parent parameters *id*. |
| 247 | + All versions (*ver*) share the same topic for a given *id*." } |
| 248 | + TB -.- note``` |
| 249 | +``` |
| 250 | + |
| 251 | +##### Discovery Steps |
| 252 | + |
| 253 | +1. Bootstrap by subscribing to the Global Root window: `catalyst/signed-docs/<start>/<end>` to discover ACTIVE Brand Parameters. |
| 254 | +2. For each discovered Brand, subscribe to the brand-anchored topic: |
| 255 | + * All docs: `catalyst/signed-docs/B` |
| 256 | +3. For each discovered Campaign or Contest, subscribe to: |
| 257 | + * (Campaign Parameters) @ `catalyst/signed-docs/C` |
| 258 | + * (Contest Parameters) @ `catalyst/signed-docs/V` |
| 259 | +4. For each discovered Category or Contest, subscribe to: |
| 260 | + * (Category Parameters) @ `catalyst/signed-docs/K` |
| 261 | + * (Contest Parameters) @ `catalyst/signed-docs/V1` |
| 262 | +5. For each discovered Contest, subscribe to: |
| 263 | + * (Contest Parameters) @ `catalyst/signed-docs/V2` |
| 264 | + |
| 265 | +**Note:** *Contest Parameters may be anchored directly to B, C, or K — subscribe to the corresponding topics as shown above.* |
| 266 | + |
| 267 | +### Content Addressing |
| 268 | + |
| 269 | +* Every `document_ref` includes a [CBOR][RFC8949] encoded CID for location in content-addressed storage. |
| 270 | + See: [CBOR][RFC8949] Tag 42 and [IPFS CID][IPFS-CID]. |
| 271 | +* The locator does not guarantee availability; |
| 272 | + it guarantees identity. |
| 273 | +* Pub/sub disseminates the bytes; content-addressed stores provide retrieval by CID. |
| 274 | + |
| 275 | +## Validation Summary per Parameters Level |
| 276 | + |
| 277 | +* Brand Parameters: root; template required; [`parameters`](../metadata.md#parameters) is excluded at this level. |
| 278 | +* Campaign Parameters: must link [`parameters`](../metadata.md#parameters) to a Brand Parameters document; |
| 279 | + template required. |
| 280 | +* Category Parameters: must link [`parameters`](../metadata.md#parameters) to a Campaign Parameters document; |
| 281 | + template required. |
| 282 | +* Contest Parameters: must link [`parameters`](../metadata.md#parameters) to one of |
| 283 | + Brand/Campaign/Category Parameters for the same chain; template required. |
| 284 | + |
| 285 | +See the per-document pages for full rules and examples: |
| 286 | + |
| 287 | +* [Brand](../docs/brand_parameters.md) |
| 288 | +* [Campaign](../docs/campaign_parameters.md) |
| 289 | +* [Category](../docs/category_parameters.md) |
| 290 | +* [Contest](../docs/contest_parameters.md) |
| 291 | + |
| 292 | +## Operational Notes |
| 293 | + |
| 294 | +* **Consistency:** reject documents whose [`parameters`](../metadata.md#parameters) do not align transitively to the same |
| 295 | + brand root as the referencing items (templates, child parameters). |
| 296 | +* **Freshness:** prefer the highest valid [`ver`](../metadata.md#ver) per [`id`](../metadata.md#id); |
| 297 | + handle [`revocations`](../metadata.md#revocations) strictly. |
| 298 | +* **Indexes:** index by `(type, id, ver)` and by `(parameters-anchor, type)` to accelerate discovery. |
| 299 | + |
| 300 | +[RFC9052-CoseSign]: https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si |
| 301 | +[IPFS-CID]: https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid |
| 302 | +[RFC9562-V4]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-4 |
| 303 | +[RFC9562-V7]: https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7 |
| 304 | +[RFC8949]: https://www.rfc-editor.org/rfc/rfc8949.html |
0 commit comments