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

FieldTypeRequiredDescription
schemastringyesPer-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.
kindstringyesDocument kind discriminator. Always 'campaign-metadata' for this schema.
publisherstringyesDID 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_atstringyesRFC 3339 / ISO 8601 UTC timestamp of document publication.
tagsobjectyesFree-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_idstringyesOff-chain identifier (snowflake). On-chain bytes32 = keccak256(utf8 of this string).
frontier_idstringyesParent frontier identifier (matches FrontierMetadata.frontier_id).
owner_did_idstringyesuint128 DID id, serialised as decimal string.
namestringyesHuman-readable campaign name. Permanently written to Arweave — do not put personal data in it (see CONVENTIONS.md's GDPR Note).
briefstringyesFree-text campaign summary. Permanently written to Arweave — do not put personal data in it (see CONVENTIONS.md's GDPR Note).
compensation_modelfixed | bounty | hybrid | royaltyyes
budget_usdnumberyes
privacy_tieropen | shielded | guarded | sealedyes
qualificationobjectyes
royalty_split—yesRequired object when compensation_model is 'hybrid' or 'royalty' (enforced by the allOf below); null otherwise.
tutorialsarray of objectyes
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

{
  "schema": "xny://schemas/campaign-metadata/1.0",
  "kind": "campaign-metadata",
  "publisher": "did:xny:0xabcdef1234567890abcdef1234567890abcdef12",
  "published_at": "2026-06-08T10:00:00Z",
  "tags": {},
  "campaign_id": "c-open-annotation-002",
  "frontier_id": "f-life-sciences-2026",
  "owner_did_id": "1042",
  "name": "Open Annotation Sprint",
  "brief": "A no-requirements campaign open to any contributor, paid on a fixed schedule.",
  "compensation_model": "fixed",
  "budget_usd": 5000,
  "privacy_tier": "open",
  "qualification": {},
  "royalty_split": null,
  "tutorials": []
}

2 rejection cases are kept alongside the schema in docs/schemas/examples/, exercised by validate_schemas.py.

Last updated

On this page