{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://ember.local/schemas/applet-manifest-v2.json",
  "title": "Ember applet manifest v2",
  "type": "object",
  "additionalProperties": false,
  "required": ["manifestVersion", "id", "name", "version", "entry", "capabilities"],
  "properties": {
    "$schema": { "type": "string" },
    "manifestVersion": { "const": 2 },
    "id": { "type": "string", "maxLength": 100, "pattern": "^[a-z][a-z0-9]*(\\.[a-z][a-z0-9-]*)+$" },
    "name": { "type": "string", "minLength": 1, "maxLength": 40 },
    "description": { "type": "string", "maxLength": 180, "default": "" },
    "version": { "type": "string", "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-[0-9A-Za-z.-]+)?$" },
    "entry": { "type": "string", "pattern": "^[^/\\\\].*\\.html$" },
    "accent": { "type": "string", "pattern": "^#[0-9A-Fa-f]{6}$", "default": "#6f7667" },
    "icon": { "enum": ["applet", "notes", "focus", "weather", "calendar"], "default": "applet" },
    "permissions": { "type": "array", "maxItems": 0 },
    "capabilities": { "$ref": "#/$defs/capabilities" },
    "settings": { "type": "array", "maxItems": 24, "items": { "$ref": "#/$defs/setting" } },
    "backend": { "$ref": "#/$defs/backend" },
    "window": { "$ref": "#/$defs/window" }
  },
  "$defs": {
    "setting": {
      "type": "object", "additionalProperties": false,
      "required": ["key", "label", "type", "default"],
      "properties": {
        "key": { "type": "string", "pattern": "^[a-z0-9-]{1,64}$" },
        "label": { "type": "string", "minLength": 1, "maxLength": 60 },
        "description": { "type": "string", "maxLength": 160, "default": "" },
        "type": { "enum": ["boolean", "string", "select"] },
        "options": { "type": "array", "minItems": 1, "maxItems": 12, "uniqueItems": true, "items": { "type": "string", "minLength": 1, "maxLength": 80 } },
        "default": {}
      }
    },
    "empty": { "type": "object", "additionalProperties": false },
    "origin": { "type": "string", "pattern": "^https://(?:\\*\\.)?[A-Za-z0-9.-]+(?::[0-9]+)?$" },
    "wssOrigin": { "type": "string", "pattern": "^wss://(?:\\*\\.)?[A-Za-z0-9.-]+(?::[0-9]+)?$" },
    "window": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "width": { "type": "number", "minimum": 320, "maximum": 1920, "default": 900 },
        "height": { "type": "number", "minimum": 240, "maximum": 1200, "default": 650 },
        "minWidth": { "type": "number", "minimum": 240, "default": 480 },
        "minHeight": { "type": "number", "minimum": 180, "default": 360 }
      }
    },
    "backend": {
      "type": "object",
      "additionalProperties": false,
      "required": ["runtime", "entry"],
      "properties": {
        "runtime": { "const": "wasiComponent" },
        "entry": { "type": "string", "pattern": "^[^/\\\\].*\\.wasm$" },
        "interfaceVersion": { "const": 1, "default": 1 },
        "lifecycle": { "enum": ["onDemand", "whileOpen", "background"], "default": "whileOpen" },
        "memoryMiB": { "type": "integer", "minimum": 16, "maximum": 256, "default": 64 }
      }
    },
    "httpGrant": {
      "type": "object",
      "additionalProperties": false,
      "required": ["origin"],
      "properties": {
        "origin": { "$ref": "#/$defs/origin" },
        "methods": { "type": "array", "minItems": 1, "uniqueItems": true, "default": ["GET"], "items": { "enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"] } },
        "requestHeaders": { "type": "array", "uniqueItems": true, "items": { "type": "string", "pattern": "^[A-Za-z0-9-]+$" } }
      }
    },
    "requestProfile": {
      "type": "object",
      "additionalProperties": false,
      "required": ["origins"],
      "properties": {
        "origins": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/origin" } },
        "headers": { "type": "object", "maxProperties": 8, "propertyNames": { "enum": ["Origin", "origin", "Referer", "referer", "User-Agent", "user-agent"] }, "additionalProperties": { "type": "string", "maxLength": 512 } },
        "userAgent": { "type": "string", "maxLength": 512 }
      }
    },
    "credentialSlot": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "label", "targets", "placement"],
      "properties": {
        "name": { "type": "string", "pattern": "^[a-z0-9-]{1,64}$" },
        "label": { "type": "string", "minLength": 1, "maxLength": 60 },
        "targets": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/origin" } },
        "placement": {
          "oneOf": [
            {
              "type": "object",
              "additionalProperties": false,
              "required": ["type", "name", "format"],
              "properties": {
                "type": { "const": "header" },
                "name": { "type": "string", "pattern": "^[A-Za-z0-9-]+$" },
                "format": { "type": "string", "maxLength": 256, "pattern": "\\{secret\\}" }
              }
            },
            {
              "type": "object",
              "additionalProperties": false,
              "required": ["type", "name"],
              "properties": {
                "type": { "enum": ["form", "query"] },
                "name": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9._~-]+$" }
              }
            }
          ]
        }
      }
    },
    "extensionGrant": {
      "type": "object", "additionalProperties": false,
      "required": ["id", "namespace", "methods"],
      "properties": {
        "id": { "type": "string", "pattern": "^[a-z][a-z0-9]*(\\.[a-z][a-z0-9-]*)+$" },
        "namespace": { "type": "string", "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$" },
        "methods": { "type": "array", "minItems": 1, "maxItems": 64, "uniqueItems": true, "items": { "type": "string", "pattern": "^[a-z][a-zA-Z0-9_]*$" } }
      }
    },
    "capabilities": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "storage": { "$ref": "#/$defs/empty" },
        "network": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "requests": { "type": "array", "maxItems": 64, "items": { "$ref": "#/$defs/httpGrant" } },
            "browserFetch": { "type": "array", "maxItems": 64, "items": { "$ref": "#/$defs/origin" } },
            "websockets": { "type": "array", "maxItems": 64, "items": { "$ref": "#/$defs/wssOrigin" } },
            "images": { "type": "array", "maxItems": 64, "items": { "$ref": "#/$defs/origin" } },
            "media": { "type": "array", "maxItems": 64, "items": { "$ref": "#/$defs/origin" } },
            "requestProfiles": { "type": "object", "maxProperties": 16, "additionalProperties": { "$ref": "#/$defs/requestProfile" } }
          }
        },
        "credentials": {
          "type": "object",
          "additionalProperties": false,
          "properties": { "slots": { "type": "array", "maxItems": 32, "items": { "$ref": "#/$defs/credentialSlot" } } }
        },
        "externalNavigation": {
          "type": "object",
          "additionalProperties": false,
          "properties": { "origins": { "type": "array", "maxItems": 32, "items": { "$ref": "#/$defs/origin" } } }
        },
        "auth": { "$ref": "#/$defs/empty" },
        "window": {
          "type": "object",
          "additionalProperties": false,
          "properties": { "fullscreen": { "type": "boolean", "default": false } }
        },
        "workers": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "dedicated": { "type": "boolean", "default": false },
            "blob": { "type": "boolean", "default": false }
          }
        },
        "background": { "$ref": "#/$defs/empty" },
        "terminal": { "$ref": "#/$defs/empty" },
        "extensions": { "type": "array", "maxItems": 32, "items": { "$ref": "#/$defs/extensionGrant" } }
      }
    }
  }
}
