{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://canonmsg.com/schemas/canon.verb-wire.v1.json",
  "title": "Canon Verb Wire v1",
  "description": "The remote wire contract for agent verbs: authenticated envelope + json-or-mls body. The semantic intent contract (canon.verbs.v1) is local; this is what crosses the network.",
  "type": "object",
  "required": [
    "wire",
    "verb",
    "envelope",
    "body"
  ],
  "additionalProperties": false,
  "properties": {
    "wire": {
      "const": "canon.verb-wire.v1"
    },
    "verb": {
      "enum": [
        "send_to",
        "request_input",
        "request_approval",
        "check_approval",
        "send_card",
        "request_card",
        "share_contact",
        "react",
        "forward",
        "create_group",
        "add_member",
        "remove_member",
        "leave_conversation",
        "list_contacts",
        "list_conversations",
        "no_reply"
      ]
    },
    "envelope": {
      "$ref": "#/$defs/envelope"
    },
    "body": {
      "$ref": "#/$defs/body"
    }
  },
  "$defs": {
    "body": {
      "description": "The verb body: plaintext JSON for temporary/plaintext conversations, MLS ciphertext for encrypted ones. In json mode the server may read value to execute legacy behavior; in mls mode it is opaque.",
      "oneOf": [
        {
          "type": "object",
          "required": [
            "encoding",
            "value"
          ],
          "additionalProperties": false,
          "properties": {
            "encoding": {
              "const": "json"
            },
            "value": {
              "type": "object"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "encoding",
            "epoch",
            "ciphertext",
            "aadHash"
          ],
          "additionalProperties": false,
          "properties": {
            "encoding": {
              "const": "mls"
            },
            "epoch": {
              "type": "integer",
              "minimum": 0
            },
            "ciphertext": {
              "type": "string",
              "minLength": 1
            },
            "aadHash": {
              "type": "string",
              "minLength": 1,
              "description": "Hash binding the envelope (AAD) to the ciphertext."
            }
          }
        }
      ]
    },
    "envelope": {
      "type": "object",
      "description": "Authenticated public envelope: routing/policy metadata only, never content. Per-verb field discipline: VERB_WIRE_ENVELOPE_FIELDS.",
      "additionalProperties": false,
      "properties": {
        "conversationId": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_.:-]{1,160}$"
        },
        "targetUserId": {
          "type": "string",
          "minLength": 1
        },
        "canonContactId": {
          "type": "string",
          "minLength": 1
        },
        "sourceConversationId": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_.:-]{1,160}$"
        },
        "contactUserId": {
          "type": "string",
          "minLength": 1
        },
        "requestId": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_.:-]{1,160}$"
        },
        "responseUserId": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_.:-]{1,160}$"
        },
        "expiresAt": {
          "type": "integer",
          "minimum": 0
        },
        "mode": {
          "enum": [
            "blocking",
            "detached"
          ]
        },
        "kind": {
          "enum": [
            "clarify",
            "sudo",
            "secret"
          ]
        },
        "sensitive": {
          "type": "boolean"
        },
        "allowSessionRule": {
          "type": "boolean"
        },
        "riskLevel": {
          "enum": [
            "normal",
            "destructive"
          ]
        },
        "risk": {
          "enum": [
            "low",
            "normal",
            "high",
            "destructive"
          ]
        },
        "category": {
          "enum": [
            "command",
            "file",
            "network",
            "browser",
            "mcp",
            "plugin",
            "canon",
            "tool"
          ]
        },
        "sessionSelection": {
          "oneOf": [
            {
              "type": "object",
              "required": [
                "mode"
              ],
              "additionalProperties": false,
              "properties": {
                "mode": {
                  "enum": [
                    "new",
                    "continue_latest",
                    "continue_or_create"
                  ]
                }
              }
            },
            {
              "type": "object",
              "required": [
                "mode",
                "conversationId"
              ],
              "additionalProperties": false,
              "properties": {
                "mode": {
                  "const": "specific"
                },
                "conversationId": {
                  "type": "string",
                  "pattern": "^[A-Za-z0-9_.:-]{1,160}$"
                }
              }
            }
          ]
        },
        "idempotencyKey": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_.:-]{1,160}$",
          "not": {
            "pattern": "^(\\.{1,2}|__.*__)$"
          }
        },
        "messageId": {
          "type": "string",
          "minLength": 1
        },
        "replyTo": {
          "type": "string"
        },
        "replyToPosition": {
          "type": "integer"
        },
        "mentions": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Plaintext by decision D3 (routing + mention-piercing pushes)."
        },
        "memberIds": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "minItems": 1,
          "description": "Group-membership routing ids (create_group). Plaintext like mentions (D3 rationale) but a distinct field — membership operations must not overload the mention slot."
        },
        "turn": {
          "$ref": "#/$defs/turn"
        },
        "native": {
          "type": "object",
          "description": "Content-free runtime correlation ids. Commands, paths, prompts, summaries, and model labels are not permitted in this public envelope.",
          "maxProperties": 24,
          "additionalProperties": false,
          "properties": {
            "runtime": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "method": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_][A-Za-z0-9_./:\\-]{0,255}$",
              "maxLength": 256
            },
            "requestId": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "provider": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "origin": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "surface": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "threadId": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "turnId": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "runId": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "itemId": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "toolCallId": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "approvalId": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "pluginId": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "sessionKey": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "nodeId": {
              "type": "string",
              "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
              "maxLength": 256
            },
            "handles": {
              "type": "object",
              "maxProperties": 16,
              "propertyNames": {
                "pattern": "^[A-Za-z0-9_.:-]{1,80}$"
              },
              "additionalProperties": {
                "type": "string",
                "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
                "maxLength": 256
              }
            }
          }
        },
        "runtimeId": {
          "type": "string",
          "maxLength": 128
        },
        "limit": {
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "turn": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "turnId": {
          "type": [
            "string",
            "null"
          ]
        },
        "turnSemantics": {
          "enum": [
            "progress",
            "turn_complete",
            "control"
          ]
        },
        "deliveryIntent": {
          "enum": [
            "queue",
            "interrupt",
            "interleave",
            "stop"
          ]
        },
        "replyBehavior": {
          "enum": [
            "allow_auto_reply",
            "suppress_auto_reply"
          ]
        }
      }
    },
    "accepted": {
      "type": "object",
      "required": [
        "status",
        "requestId"
      ],
      "additionalProperties": true,
      "properties": {
        "status": {
          "const": "accepted"
        },
        "requestId": {
          "type": "string"
        },
        "expiresAt": {
          "type": "integer"
        },
        "messageId": {
          "type": "string"
        },
        "responseUserId": {
          "type": "string"
        },
        "interactive": {
          "type": "boolean"
        }
      }
    },
    "response": {
      "type": "object",
      "required": [
        "wire",
        "verb",
        "result"
      ],
      "additionalProperties": true,
      "properties": {
        "wire": {
          "const": "canon.verb-wire.v1"
        },
        "verb": {
          "enum": [
            "send_to",
            "request_input",
            "request_approval",
            "check_approval",
            "send_card",
            "request_card",
            "share_contact",
            "react",
            "forward",
            "create_group",
            "add_member",
            "remove_member",
            "leave_conversation",
            "list_contacts",
            "list_conversations",
            "no_reply"
          ]
        },
        "result": {
          "$ref": "#/$defs/body"
        }
      }
    }
  }
}
