20. JSON Schema
Formal JSON Schema definitions for core frame types — the schemas are the contract, and
any implementation (the reference included) conforms to them. Implementations SHOULD
validate frames against these schemas.
additionalProperties is true
by design: §8 requires unrecognised fields to be silently ignored, so a schema
SHOULD not reject a forward-compatible extension. The single-page
downloadable specification
carries the full rendered spec. Machine-readable schema files are
published
in the protocol repository — handshake, CMB (including the §15.8 tether
attestation), the cmb frame, and the cmb-fetch pair — and the reference implementation’s
suite validates its real wire objects against them, so it cannot drift from this contract.
The published schema set above is the final normative set; frame types without a published
schema are validated against their §7 definitions.
Two scope notes. These are the wire schemas: receiver-local fields
(source, originTimestamp,
storedAt, confidence,
provenance) are set on receipt and never cross the wire, so
they are not listed. And the CMB schema describes the decrypted form: under end-to-end
encryption (§18.2.1) a CMB in transit carries fields as
ciphertext plus _e2e.nonce, and the object schema below applies
after decryption. Each field also carries a vector embedding;
it is advisory and encoder-specific (§18.7) — not part of the content address
(§8.2.1), and a receiver recomputes it locally rather than trusting the sender’s. Optional
application-level fields (meta, payload)
MAY also be present and are permitted by additionalProperties.
20.1 Handshake Frame Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["type", "nodeId", "name", "version", "publicKey"],
"additionalProperties": true,
"properties": {
"type": { "const": "handshake" },
"nodeId": { "type": "string", "format": "uuid" },
"name": { "type": "string", "minLength": 1, "maxLength": 64 },
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
"publicKey": { "type": "string", "description": "base64url raw Ed25519 identity key (32 bytes); verifies this node's CMB signatures (§18.3.1)" },
"e2ePublicKey": { "type": "string", "description": "base64 X25519 key for end-to-end field encryption (§18.2.1)" },
"group": { "type": "string", "description": "The node's mesh group; the §5.8 isolation boundary. Absent ⇒ 'default' (§5.2)." },
"lifecycleRole": { "enum": ["participant", "validator", "anchor"], "description": "Senders SHOULD include it (§5.2); receivers treat absence as participant. Self-declared: an elevated role is honored only with a signed role-grant (§6.6)." },
"extensions": { "type": "array", "items": { "type": "string" } }
}
} 20.2 CMB Schema
The cmb object within a cmb frame:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["key", "createdBy", "createdAt", "fields"],
"additionalProperties": true,
"properties": {
"key": { "type": "string", "description": "Content address (§8.2.1): normative scheme cmb1- + full-width SHA-256 over the canonical serialization; legacy cmb- (SHA-256/128, pipe-joined) MUST still be verified during migration." },
"createdBy": { "type": "string", "description": "The author identifier (nodeId or agent name); bound by the signature (§18.3.1)" },
"createdAt": { "type": "integer", "description": "Unix ms timestamp of creation — the author's own; bound by the signature (§18.3.1)" },
"sig": { "type": "string", "description": "base64url Ed25519 signature over the §18.3.1 payload. SHOULD be present; a receiver holding the author's key MUST verify it." },
"sigAlg": { "const": "ed25519", "description": "Signature algorithm; a verifier MUST pin this rather than trust the field (§18.3.1)." },
"group": { "type": "string", "description": "cmb1- only: the group this CMB was authored for — audience binding (§18.3.1). Absent on legacy cmb-." },
"to": { "type": "string", "description": "cmb1- only: directed recipient nodeId; empty or absent for a broadcast (§18.3.1)." },
"_e2e": { "type": "object", "description": "Present only when the CMB is E2E-encrypted in transit (§18.2.1): then 'fields' is ciphertext, not the object below.", "properties": { "nonce": { "type": "string" } } },
"fields": {
"type": "object",
"required": ["focus", "issue", "intent", "motivation", "commitment", "perspective", "mood"],
"properties": {
"focus": { "type": "object", "required": ["text"], "properties": { "text": { "type": "string" }, "vector": { "type": "array", "items": { "type": "number" } } } },
"issue": { "type": "object", "required": ["text"], "properties": { "text": { "type": "string" }, "vector": { "type": "array", "items": { "type": "number" } } } },
"intent": { "type": "object", "required": ["text"], "properties": { "text": { "type": "string" }, "vector": { "type": "array", "items": { "type": "number" } } } },
"motivation": { "type": "object", "required": ["text"], "properties": { "text": { "type": "string" }, "vector": { "type": "array", "items": { "type": "number" } } } },
"commitment": { "type": "object", "required": ["text"], "properties": { "text": { "type": "string" }, "vector": { "type": "array", "items": { "type": "number" } } } },
"perspective": { "type": "object", "required": ["text"], "properties": { "text": { "type": "string" }, "vector": { "type": "array", "items": { "type": "number" } } } },
"mood": {
"type": "object",
"required": ["text"],
"properties": {
"text": { "type": "string", "description": "Mood keyword (MUST)" },
"valence": { "type": "number", "minimum": -1, "maximum": 1, "description": "RECOMMENDED when agent has reliable circumplex data" },
"arousal": { "type": "number", "minimum": -1, "maximum": 1, "description": "RECOMMENDED when agent has reliable circumplex data" },
"vector": { "type": "array", "items": { "type": "number" } }
}
}
}
},
"lineage": {
"type": ["object", "null"],
"description": "null on a root/origin CMB (no parents)",
"properties": {
"parents": { "type": "array", "items": { "type": "string" }, "description": "Direct parent CMB keys" },
"ancestors": { "type": "array", "items": { "type": "string" }, "description": "Full ancestor chain" },
"method": { "type": "string", "description": "Fusion method (e.g. SVAF-v2)" }
}
}
}
} Complete cmb frame with CMB:
{
"type": "cmb",
"timestamp": 1774326000000,
"cmb": {
"key": "cmb-b2c3d4e5f6a7b8c9",
"createdBy": "music-agent",
"createdAt": 1774326000000,
"fields": {
"focus": { "text": "user coding for 3 hours, energy declining" },
"issue": { "text": "sedentary since morning, skipping lunch" },
"intent": { "text": "recommend movement break before fatigue worsens" },
"motivation": { "text": "3 agents reported declining energy in last hour" },
"commitment": { "text": "fitness monitoring active, 10min stretch queued" },
"perspective": { "text": "fitness agent, afternoon session, home office" },
"mood": { "text": "concerned, low energy", "valence": -0.3, "arousal": -0.4 }
},
"lineage": {
"parents": ["cmb-a1b2c3d4e5f6"],
"ancestors": ["cmb-a1b2c3d4e5f6"],
"method": "SVAF-v2"
}
}
}
This example shows the legacy unsigned form (cmb- key, no
sig); §8.2.1 and §18.3.1 define the
current cmb1-/signed form.