{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://cfapi.aog.cc/docs/devcenter/schemas/plugin-manifest.schema.json",
  "title": "cfapi.aog.cc plugin.json manifest",
  "description": "插件包根目录（或唯一顶层目录）内的 plugin.json。上传时 code 必须与 URL 查询参数 code / plugin_code 完全一致；未知附加字段会保留在原始清单中，但不要依赖未在此声明的字段产生运行时行为。",
  "type": "object",
  "required": ["code"],
  "properties": {
    "code": {
      "type": "string",
      "minLength": 1,
      "maxLength": 64,
      "pattern": "^[a-z0-9_]+$",
      "description": "插件唯一标识，仅小写 ASCII 字母、数字、下划线；必须与上传参数一致。"
    },
    "name": {
      "type": "string",
      "maxLength": 128,
      "description": "展示名称；省略时使用 code。"
    },
    "version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
      "description": "推荐 SemVer 三段式。市场提交时版本必须是 x.y.z，且严格高于该插件历史最高上架版本。"
    },
    "type": {
      "type": "string",
      "enum": ["local", "remote", "wasm", "sandbox", "disabled"],
      "default": "local",
      "description": "登记类型。local/remote 是当前外部开发者可实际交付的形态；wasm/sandbox 只是标签，执行还需独立的 active 沙箱配置。"
    },
    "base_url": {
      "type": "string",
      "maxLength": 512,
      "pattern": "^https?://[^\\s]+$",
      "description": "remote 类型必填，指向插件自己的 HTTP(S) 服务。非超级管理员提交时禁止内网、回环和元数据地址。local 应为空。"
    },
    "description": {
      "type": "string",
      "maxLength": 4096,
      "description": "面向使用者的能力说明，不要写部署凭据或内网信息。"
    },
    "entry": {
      "type": "string",
      "maxLength": 256,
      "description": "沙箱/运行时的相对入口文件。禁止绝对路径、盘符和 .. 目录穿越。注意：local 静态托管固定使用 index.html，entry 不会改变页面入口。"
    },
    "permissions": {
      "type": "array",
      "description": "声明的权限标识。常见写法是平台权限码（如 plugin.view）或 resource:action。注意：上传/安装路径不会对冒号做强制校验；/api/manifest/scan 的解析器更严格，要求 resource:action 或 *。权限声明本身不授予权限，实际访问仍由平台权限码、scope 与层级策略决定。",
      "items": {
        "type": "string",
        "pattern": "^(\\*|[A-Za-z0-9_.:-]+)$",
        "maxLength": 128
      },
      "default": []
    },
    "dependencies": {
      "type": "array",
      "description": "插件依赖声明。plugin 不能为空。",
      "items": {
        "type": "object",
        "required": ["plugin"],
        "properties": {
          "plugin": {
            "type": "string",
            "pattern": "^[a-z0-9_]+$"
          },
          "version": {
            "type": "string",
            "default": "*",
            "description": "依赖版本约束；省略时为 *。"
          },
          "optional": {
            "type": "boolean",
            "default": false
          }
        },
        "additionalProperties": false
      },
      "default": []
    },
    "requirements": {
      "type": "object",
      "description": "资源需求声明。缺省值来自服务端 Requirements::default，不代表可以在沙箱中无条件获得这些资源。",
      "properties": {
        "memory_mb": {
          "type": "integer",
          "minimum": 0
        },
        "cpu_shares": {
          "type": "integer",
          "minimum": 0
        },
        "disk_mb": {
          "type": "integer",
          "minimum": 0
        },
        "features": {
          "type": "array",
          "items": { "type": "string" }
        }
      },
      "additionalProperties": false,
      "default": {
        "memory_mb": 64,
        "cpu_shares": 100,
        "disk_mb": 10,
        "features": []
      }
    }
  },
  "additionalProperties": true,
  "examples": [
    {
      "code": "my_local_plugin",
      "name": "我的本地插件",
      "version": "1.0.0",
      "type": "local",
      "description": "静态页面由平台托管，固定入口为 index.html。"
    },
    {
      "code": "my_remote_plugin",
      "name": "我的远程插件",
      "version": "1.0.0",
      "type": "remote",
      "base_url": "https://plugin.example.com",
      "description": "平台把 /api/plugins/my_remote_plugin/proxy/** 转发到该服务。"
    }
  ]
}
