{
  "type": "object",
  "required": [
    "id",
    "name",
    "version",
    "author",
    "apiVersion",
    "entry",
    "capabilities"
  ],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9-]*(?:\\.[a-z0-9-]+)+$",
      "maxLength": 128,
      "description": "Reverse-DNS identifier, such as org.example.translate."
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 64
    },
    "version": {
      "type": "string",
      "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-[0-9A-Za-z.-]+)?$",
      "description": "Semantic version."
    },
    "description": {
      "type": "string",
      "maxLength": 300
    },
    "author": {
      "type": "object",
      "required": [
        "name"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "url": {
          "type": "string",
          "pattern": "^https://",
          "maxLength": 300
        }
      },
      "additionalProperties": false
    },
    "apiVersion": {
      "type": "string",
      "pattern": "^[\\^~]?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
      "description": "The SDK versions the extension works with: exact, ^ or ~."
    },
    "entry": {
      "type": "string",
      "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))[A-Za-z0-9._/-]+\\.m?js$",
      "maxLength": 200
    },
    "capabilities": {
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "string",
            "const": "chat:read-active"
          },
          {
            "type": "string",
            "const": "chat:read-unread-summary"
          },
          {
            "type": "string",
            "const": "composer:insert-draft"
          },
          {
            "type": "string",
            "const": "composer:read-draft"
          },
          {
            "type": "string",
            "const": "notifications:show"
          },
          {
            "type": "string",
            "const": "storage:local"
          },
          {
            "type": "string",
            "const": "secrets:own"
          },
          {
            "type": "string",
            "const": "local-network"
          },
          {
            "type": "string",
            "const": "assistant:bar"
          },
          {
            "type": "string",
            "const": "calls:record"
          }
        ]
      },
      "uniqueItems": true
    },
    "network": {
      "type": "object",
      "required": [
        "hosts"
      ],
      "properties": {
        "hosts": {
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$"
          },
          "uniqueItems": true,
          "maxItems": 32,
          "description": "HTTPS hosts the extension may reach; nothing else is allowed."
        }
      },
      "additionalProperties": false
    },
    "contributes": {
      "type": "object",
      "properties": {
        "commands": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "title"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9-]*$",
                "maxLength": 64
              },
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64
              },
              "shortcut": {
                "type": "string",
                "maxLength": 64,
                "pattern": "^[A-Za-z0-9+`=\\[\\];',./\\\\-]+$",
                "description": "Suggested keys, in Electron's accelerator syntax, such as `CmdOrCtrl+Shift+R`. YapYap uses them only when they clash with none of its own shortcuts or an earlier extension's."
              }
            },
            "additionalProperties": false,
            "description": "An action the user can run from YapYap."
          },
          "maxItems": 32
        },
        "composerActions": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "title",
              "command"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64
              },
              "command": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9-]*$",
                "maxLength": 64
              }
            },
            "additionalProperties": false
          },
          "maxItems": 8
        },
        "contextMenu": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "title",
              "command",
              "on"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64
              },
              "command": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9-]*$",
                "maxLength": 64
              },
              "on": {
                "anyOf": [
                  {
                    "type": "string",
                    "const": "message"
                  },
                  {
                    "type": "string",
                    "const": "chat"
                  }
                ]
              }
            },
            "additionalProperties": false
          },
          "maxItems": 16
        },
        "settings": {
          "type": "object",
          "patternProperties": {
            "^.*$": {}
          },
          "description": "A JSON Schema for the extension settings form YapYap renders."
        },
        "panel": {
          "type": "object",
          "required": [
            "title",
            "entry"
          ],
          "properties": {
            "title": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "entry": {
              "type": "string",
              "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))[A-Za-z0-9._/-]+\\.m?js$",
              "maxLength": 200
            }
          },
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    },
    "signature": {
      "type": "object",
      "required": [
        "publicKey",
        "algorithm",
        "value"
      ],
      "properties": {
        "publicKey": {
          "type": "string",
          "pattern": "^[A-Za-z0-9+/]+={0,2}$",
          "description": "Base64 SPKI DER."
        },
        "algorithm": {
          "type": "string",
          "const": "ed25519"
        },
        "value": {
          "type": "string",
          "pattern": "^[A-Za-z0-9+/]+={0,2}$"
        }
      },
      "additionalProperties": false
    }
  },
  "$id": "https://yapyap.guita.org/schema/manifest.schema.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "YapYap extension manifest",
  "additionalProperties": false
}
