插件能碰到的一切都来自 ctx,而 ctx 由宿主按你声明的权限逐字段构造:没声明的能力,ctx 上就没有那个字段
(ctx.calendar === undefined),不是「存在但调用报错」。安装对话框会把权限翻译成人话、按风险标色展示给用户。
| 权限 | ctx 上多出来的 | 风险 | 用户看到的说明 |
|---|---|---|---|
context.read:courses |
ctx.courses.list/get |
中 | 读取你的课程列表 |
context.read:assignments |
ctx.assignments.list/get |
中 | 读取作业标题、截止时间和完成状态 |
context.read:grades |
作业上的 points / grade 有值 |
高 | 读取作业分值和成绩 |
context.read:files |
ctx.materials.search |
中 | 检索课程资料 |
calendar.read |
ctx.calendar.list/owned/ready |
中 | 读取你的日历日程 |
calendar.write |
ctx.calendar.create/update/remove 可用 |
中 | 在日历里新建日程,并修改或删除它自己建的日程 |
storage |
ctx.storage |
低 | 在你的账号里保存它自己的数据(跨设备同步) |
storage.device |
ctx.deviceStorage |
低 | 在这台电脑上保存它自己的数据(不上传) |
network:user-granted |
ctx.net.fetchText |
高(有 networkHosts 时为中) | 访问任意 / 这些网站 |
files.open |
ctx.files.openText |
低 | 打开你在对话框里选择的文件 |
files.save |
ctx.files.saveText |
低 | 把文件保存到你选择的位置 |
ui.panel |
ctx.ui.openPanel;插件可以有面板 |
低 | 在标签页里显示自己的面板 |
模式:同一个权限,不同的命令拿到的能力不同
| 调用 | ctx 模式 | 能做什么 |
|---|---|---|
read 命令的 run、所有命令的 describe |
read |
只读:存储的 put/remove、日历的 create/update/remove 存在但调用即抛错;没有 net、files、ui |
navigate 命令的 run |
navigate |
只读 + ui.openPanel |
write 命令的 run 与 undo |
write |
全部声明过的能力 |
所以:describe 里不要写任何东西(它在用户确认之前运行,只该读数据、算出确认卡片上的人话);
需要联网 / 打开文件的动作必须是 write 命令。
最小权限
- 只读课程名就别要作业;只要作业截止时间就别要成绩(
context.read:grades是高风险)。 - 数据只在这台电脑上有意义(例如凭据、订阅地址)用
storage.device,需要跨设备才用storage。 - 联网务必写
networkHosts:安装对话框里「访问任意网址」是红色的,很多用户会因此不装。 - 需要打开 / 保存文件时用
files.*,不要让用户把内容粘贴进聊天。
永远拿不到的东西
登录态、JWT、Supabase 客户端、window.electronAPI、应用的 DOM / localStorage / IndexedDB、别的插件的存储、
用户的聊天记录与笔记正文、系统文件(除用户在对话框里亲手选的那一个)。插件代码运行在 opaque origin 的沙箱里,
这些在技术上就碰不到,不只是「约定不碰」。详见 安全模型。