claim/v4
packages/core/schema/claim-v4.schema.jsonOn this page
claim/v4 (11 Nov, board #97; Elco: types are data, claims with evidence, any value, several at once) is claim/v3 with one more verb, is_a: the account is of a type, in any word (a DAO, a multisig, a token, an exchange wallet), as a technical form, a role or a declared nature. Everything else is claim/v3's. One attributed, immutable statement about an account, a contract or a group. Named by the SHA-256 of its RFC 8785 canonical JSON, without id and proof. The rules a schema can't say are in validateClaim, and petal.mjs validate-data runs them: an inferred claim states its grounds, in qualifiers.grounds, one or more of funding_lineage, inbound_transfers, research, same_address, shared_signer and synchronised_behaviour, sorted and joined by commas, and about a person, inbound_transfers alone isn't grounds enough; and a person's name in its words is allowed only in that person's own project. See specs/002-system/contracts/claims.md. v2 added annotations: a name, a note and a link in words (named, noted, linked), a person's own word (stated), research as a ground, and a transaction, a proposal and a quote in the evidence. v3 types each piece of evidence and says who found it and when, and an open source's platform and an archived copy, so a claim discovered on the chain, inferred, or gathered from the open web keeps what it rests on. A name or a person in its words is kept in a person's own project only (people.ts).
Fields
| Field | Type or allowed values | Presence in its parent | Description |
|---|---|---|---|
petal |
"claim/v4" | Required | |
id |
string | Required | |
subject |
string | Required | Namespaced. refs.ts says which namespaces parse. No natural person. |
verb |
"holds" / "measured" / "delegates_to" / "owned_by" / "member_of" / "holds_role" / "voted" / "proposed" / "reviewed" / "paid" / "funded_by" / "signer_of" / "deployed" / "controls" / "declares_same_controller" / "shares_signer" / "moves_with" / "same_funder" / "same_address" / "labelled" / "requests_correction" / "challenges" / "responds" / "retracts" / "supersedes" / "confidence" / "named" / "noted" / "linked" / "is_a" | Required | A closed list per version. Each verb's definition is in verbs.ts and contracts/claims.md. |
object |
choice | Required | |
object (variant 1) |
string | Required | Namespaced. refs.ts says which namespaces parse. No natural person. |
object (variant 2) |
object | Required | |
object (variant 2).value |
string | Required | A number as a string, a closed tag, or, for named, noted and linked, words or a link. |
object (variant 2).unit |
string | Optional | |
qualifiers |
object | Optional | Checked per verb. Amounts are strings. |
qualifiers.* |
string | Optional | |
valid_from |
string | Optional | UTC with Z, so one moment has one spelling and one id. |
valid_to |
string | Optional | UTC with Z, so one moment has one spelling and one id. |
issued_at |
string | Required | UTC with Z, so one moment has one spelling and one id. |
as_of |
object | Optional | |
as_of.chain |
string | Required | |
as_of.block |
integer | Required | |
kind |
"observed" / "declared" / "stated" / "sourced" / "inferred" | Required | |
method |
string | Optional | Required if inferred: a rule or model, its version, and an optional hash of its parameters. |
evidence |
array | Required | |
evidence[] |
object | Required | |
evidence[].snapshot_sha256 |
string | Optional | |
evidence[].url |
string | Optional | |
evidence[].url_sha256 |
string | Optional | |
evidence[].retrieved_at |
string | Optional | UTC with Z, so one moment has one spelling and one id. |
evidence[].claim_id |
string | Optional | |
evidence[].note |
string | Optional | Short. In a published claim it must not name a person (people.ts). |
evidence[].tx |
string | Optional | The transaction it rests on, on its chain: <caip2>:<hash>. |
evidence[].proposal |
string | Optional | The proposal it rests on: proposal:<caip2>:<key>. |
evidence[].quote |
string | Optional | The source's own words, exactly as written. |
evidence[].type |
"snapshot" / "tx" / "proposal" / "page" / "post" / "claim" / "note" | Required | What this piece is: a reading by its hash, a transaction, a proposal, a web page, a post on a platform, another claim, or a note alone. It names the field that holds it. |
evidence[].found_by |
string | Required | Who found this piece: an account, a named tool or a named model. |
evidence[].found_at |
string | Required | When it was found. |
evidence[].platform |
string | Optional | Where a page or post lives, as a slug: x, github, discord, forum, telegram, farcaster. |
evidence[].archive_url |
string | Optional | An archived copy of the page or post (web.archive.org, archive.today), so it survives the page changing. |
by |
string | Required | Namespaced. refs.ts says which namespaces parse. No natural person. |
via |
string | Optional | Namespaced. refs.ts says which namespaces parse. No natural person. |
proof |
choice | Optional | Outside the hash: the same claim can carry different proofs. |
proof (variant 1) |
object | Optional | |
proof (variant 1).type |
"tx" | Required | |
proof (variant 1).hash |
string | Required | |
proof (variant 2) |
object | Optional | |
proof (variant 2).type |
"nep413" | Required | |
proof (variant 2).account_id |
string | Required | |
proof (variant 2).public_key |
string | Required | |
proof (variant 2).signature |
string | Required | |
proof (variant 2).message |
string | Required | |
proof (variant 2).nonce |
string | Required | |
proof (variant 2).recipient |
string | Required | |
proof (variant 3) |
object | Optional | |
proof (variant 3).type |
"nearai" | Required | |
proof (variant 3).model |
string | Required | |
proof (variant 3).completion_id |
string | Required | |
proof (variant 3).text |
string | Required | |
proof (variant 3).signature |
string | Required | |
proof (variant 3).signing_address |
string | Required | |
proof (variant 3).signing_algo |
"ecdsa" / "ed25519" | Required |
Examples
claim.v4.json
{
"petal": "claim/v4",
"subject": "eip155:100:0xf02fd4286917270cb94fbc13a0f4e1ed76f7e986",
"verb": "is_a",
"object": {
"value": "DAO"
},
"kind": "inferred",
"method": "marks/types@1",
"qualifiers": {
"grounds": "research"
},
"issued_at": "2026-11-11T17:00:00.000Z",
"by": "tool:petals-marks@1",
"evidence": [
{
"type": "note",
"note": "sharesToken() on eip155:100:0xf02fd4286917270cb94fbc13a0f4e1ed76f7e986 names 0x372fc5a6b0b12ae174f09f6fc849a83de6b503b6, the token it owns: a Moloch v3 (Baal) DAO",
"found_by": "tool:petals-marks@1",
"found_at": "2026-11-11T17:00:00.000Z"
}
],
"id": "ac87a0c9cfeb18f8f7f03114383620733d87d78130daf43bd948cbcc5af2b7a9"
}
Full schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:petal:schema:claim:v4",
"title": "Petal claim v4",
"description": "claim/v4 (11 Nov, board #97; Elco: types are data, claims with evidence, any value, several at once) is claim/v3 with one more verb, is_a: the account is of a type, in any word (a DAO, a multisig, a token, an exchange wallet), as a technical form, a role or a declared nature. Everything else is claim/v3's. One attributed, immutable statement about an account, a contract or a group. Named by the SHA-256 of its RFC 8785 canonical JSON, without id and proof. The rules a schema can't say are in validateClaim, and petal.mjs validate-data runs them: an inferred claim states its grounds, in qualifiers.grounds, one or more of funding_lineage, inbound_transfers, research, same_address, shared_signer and synchronised_behaviour, sorted and joined by commas, and about a person, inbound_transfers alone isn't grounds enough; and a person's name in its words is allowed only in that person's own project. See specs/002-system/contracts/claims.md. v2 added annotations: a name, a note and a link in words (named, noted, linked), a person's own word (stated), research as a ground, and a transaction, a proposal and a quote in the evidence. v3 types each piece of evidence and says who found it and when, and an open source's platform and an archived copy, so a claim discovered on the chain, inferred, or gathered from the open web keeps what it rests on. A name or a person in its words is kept in a person's own project only (people.ts).",
"type": "object",
"required": [
"petal",
"id",
"subject",
"verb",
"object",
"issued_at",
"kind",
"evidence",
"by"
],
"additionalProperties": false,
"properties": {
"petal": {
"const": "claim/v4"
},
"id": {
"$ref": "#/$defs/sha256"
},
"subject": {
"$ref": "#/$defs/entityRef"
},
"verb": {
"enum": [
"holds",
"measured",
"delegates_to",
"owned_by",
"member_of",
"holds_role",
"voted",
"proposed",
"reviewed",
"paid",
"funded_by",
"signer_of",
"deployed",
"controls",
"declares_same_controller",
"shares_signer",
"moves_with",
"same_funder",
"same_address",
"labelled",
"requests_correction",
"challenges",
"responds",
"retracts",
"supersedes",
"confidence",
"named",
"noted",
"linked",
"is_a"
],
"description": "A closed list per version. Each verb's definition is in verbs.ts and contracts/claims.md."
},
"object": {
"oneOf": [
{
"$ref": "#/$defs/entityRef"
},
{
"type": "object",
"required": [
"value"
],
"additionalProperties": false,
"properties": {
"value": {
"type": "string",
"minLength": 1,
"maxLength": 4000,
"description": "A number as a string, a closed tag, or, for named, noted and linked, words or a link."
},
"unit": {
"type": "string",
"minLength": 1,
"maxLength": 32
}
}
}
]
},
"qualifiers": {
"type": "object",
"additionalProperties": {
"type": "string",
"maxLength": 256
},
"description": "Checked per verb. Amounts are strings."
},
"valid_from": {
"$ref": "#/$defs/datetime"
},
"valid_to": {
"$ref": "#/$defs/datetime"
},
"issued_at": {
"$ref": "#/$defs/datetime"
},
"as_of": {
"type": "object",
"required": [
"chain",
"block"
],
"additionalProperties": false,
"properties": {
"chain": {
"type": "string",
"pattern": "^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$"
},
"block": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
}
},
"kind": {
"enum": [
"observed",
"declared",
"stated",
"sourced",
"inferred"
]
},
"method": {
"type": "string",
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9._/-]*@[a-zA-Z0-9][a-zA-Z0-9._/-]*(#[0-9a-f]{8,64})?$",
"description": "Required if inferred: a rule or model, its version, and an optional hash of its parameters."
},
"evidence": {
"type": "array",
"items": {
"$ref": "#/$defs/evidence"
}
},
"by": {
"$ref": "#/$defs/entityRef"
},
"via": {
"$ref": "#/$defs/entityRef"
},
"proof": {
"oneOf": [
{
"$ref": "#/$defs/txProof"
},
{
"$ref": "#/$defs/nep413Proof"
},
{
"$ref": "#/$defs/nearAiProof"
}
],
"description": "Outside the hash: the same claim can carry different proofs."
}
},
"if": {
"type": "object",
"properties": {
"kind": {
"const": "inferred"
}
},
"required": [
"kind"
]
},
"then": {
"type": "object",
"properties": {
"method": true
},
"required": [
"method"
]
},
"else": {
"not": {
"type": "object",
"properties": {
"method": true
},
"required": [
"method"
]
}
},
"$defs": {
"sha256": {
"type": "string",
"pattern": "^[0-9a-f]{64}$"
},
"datetime": {
"type": "string",
"format": "date-time",
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,9})?Z$",
"description": "UTC with Z, so one moment has one spelling and one id."
},
"entityRef": {
"type": "string",
"pattern": "^[a-z][a-z0-9-]*:[^\\s]+$",
"maxLength": 300,
"description": "Namespaced. refs.ts says which namespaces parse. No natural person."
},
"evidence": {
"type": "object",
"minProperties": 1,
"additionalProperties": false,
"properties": {
"snapshot_sha256": {
"$ref": "#/$defs/sha256"
},
"url": {
"type": "string",
"minLength": 1,
"maxLength": 2048
},
"url_sha256": {
"$ref": "#/$defs/sha256"
},
"retrieved_at": {
"$ref": "#/$defs/datetime"
},
"claim_id": {
"$ref": "#/$defs/sha256"
},
"note": {
"type": "string",
"minLength": 1,
"maxLength": 280,
"description": "Short. In a published claim it must not name a person (people.ts)."
},
"tx": {
"type": "string",
"pattern": "^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}:[0-9a-zA-Z]{16,128}$",
"description": "The transaction it rests on, on its chain: <caip2>:<hash>."
},
"proposal": {
"$ref": "#/$defs/entityRef",
"description": "The proposal it rests on: proposal:<caip2>:<key>."
},
"quote": {
"type": "string",
"minLength": 1,
"maxLength": 1000,
"description": "The source's own words, exactly as written."
},
"type": {
"enum": [
"snapshot",
"tx",
"proposal",
"page",
"post",
"claim",
"note"
],
"description": "What this piece is: a reading by its hash, a transaction, a proposal, a web page, a post on a platform, another claim, or a note alone. It names the field that holds it."
},
"found_by": {
"$ref": "#/$defs/entityRef",
"description": "Who found this piece: an account, a named tool or a named model."
},
"found_at": {
"$ref": "#/$defs/datetime",
"description": "When it was found."
},
"platform": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9._-]{0,31}$",
"description": "Where a page or post lives, as a slug: x, github, discord, forum, telegram, farcaster."
},
"archive_url": {
"type": "string",
"minLength": 1,
"maxLength": 2048,
"description": "An archived copy of the page or post (web.archive.org, archive.today), so it survives the page changing."
}
},
"required": [
"type",
"found_by",
"found_at"
]
},
"txProof": {
"type": "object",
"required": [
"type",
"hash"
],
"additionalProperties": false,
"properties": {
"type": {
"const": "tx"
},
"hash": {
"type": "string",
"minLength": 1
}
}
},
"nep413Proof": {
"type": "object",
"required": [
"type",
"account_id",
"public_key",
"signature",
"message",
"nonce",
"recipient"
],
"additionalProperties": false,
"properties": {
"type": {
"const": "nep413"
},
"account_id": {
"type": "string"
},
"public_key": {
"type": "string",
"pattern": "^ed25519:"
},
"signature": {
"type": "string"
},
"message": {
"type": "string"
},
"nonce": {
"type": "string"
},
"recipient": {
"type": "string"
}
}
},
"nearAiProof": {
"type": "object",
"required": [
"type",
"model",
"completion_id",
"text",
"signature",
"signing_address",
"signing_algo"
],
"additionalProperties": false,
"properties": {
"type": {
"const": "nearai"
},
"model": {
"type": "string"
},
"completion_id": {
"type": "string"
},
"text": {
"type": "string"
},
"signature": {
"type": "string"
},
"signing_address": {
"type": "string"
},
"signing_algo": {
"enum": [
"ecdsa",
"ed25519"
]
}
}
}
}
}