CampaignMetadata
Canonical JSON document anchored on-chain by FrontierRegistry campaign.metadataHash.
A document of this kind carries a schema field matching xny://schemas/campaign-metadata/<major>.<minor> — the version is part of the URI, and it is the only place a document's version is recorded.
Canonical JSON document anchored on-chain by FrontierRegistry campaign.metadataHash. The exact bytes uploaded to metadataUri define the hash — see Metadata Hash Rules in docs/architecture/protocol-v2-design.md §6.1.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
schema | string | yes | Per-kind versioned schema identifier. Format: xny://schemas/campaign-metadata/<major.minor>. This is the single source of truth for document version; do not use schema_version. |
kind | string | yes | Document kind discriminator. Always 'campaign-metadata' for this schema. |
publisher | string | yes | DID of the entity that published this document. Pseudonymous identifier written to the permanent Arweave layer. DID-to-identity mapping exists only in an off-chain deletable layer (GDPR note: deletion right does not cover this field). |
published_at | string | yes | RFC 3339 / ISO 8601 UTC timestamp of document publication. |
tags | object | yes | Free-form key-value metadata tags for indexing and filtering. Bounded to 32 entries with keys up to 64 characters — conservative structural limits to keep the anchored document small, not a semantic constraint on tag content. Values are permanently written to Arweave alongside the rest of this document: do not put personal data in a tag (see CONVENTIONS.md's GDPR Note). |
campaign_id | string | yes | Off-chain identifier (snowflake). On-chain bytes32 = keccak256(utf8 of this string). |
frontier_id | string | yes | Parent frontier identifier (matches FrontierMetadata.frontier_id). |
owner_did_id | string | yes | uint128 DID id, serialised as decimal string. |
name | string | yes | Human-readable campaign name. Permanently written to Arweave — do not put personal data in it (see CONVENTIONS.md's GDPR Note). |
brief | string | yes | Free-text campaign summary. Permanently written to Arweave — do not put personal data in it (see CONVENTIONS.md's GDPR Note). |
compensation_model | fixed | bounty | hybrid | royalty | yes | |
budget_usd | number | yes | |
privacy_tier | open | shielded | guarded | sealed | yes | |
qualification | object | yes | |
royalty_split | — | yes | Required object when compensation_model is 'hybrid' or 'royalty' (enforced by the allOf below); null otherwise. |
tutorials | array of object | yes | |
public_brief_md | — | — | Free-text, publicly-visible markdown brief for this campaign; null if not set. Permanently written to Arweave — do not put personal data in it (see CONVENTIONS.md's GDPR Note). |
masked_brief | — | — | Free-text brief with sensitive/identifying details redacted for display to unqualified contributors; null if not set. Permanently written to Arweave — do not put personal data in it (see CONVENTIONS.md's GDPR Note). |
Example
2 rejection cases are kept alongside the schema in docs/schemas/examples/, exercised by validate_schemas.py.
Last updated