Repository navigation
Conversation
- 新增 src-tauri plugin_host 模块:包存储布局(app_local_data_dir/plugins 与 plugin-state,bundled 从资源目录只读加载)、启动扫描(经 plugins.declarative.validate 携带 hostCapabilities,拒绝包隔离并展示原因)、 启动计划解析(packaged 入口拒绝 reparse point 与路径逃逸,runtime/ systemCommand 走 PATH 与 LITHE_<TOOL>_PATH 约定) - 共享 fixtures 验收:invalid-manifests.json 全部 154 个用例在 Windows 二进制 内断言同一稳定错误码;合法样例按契约模式与 v0 能力门控模式分别断言 - 前端:resolve-editor-lsp-launch 在 Worker 扩展无服务器时回落契约插件启动; bootstrap 增加 declarative plugins 扫描步骤 - Note 转正为 implemented 并记录 M1 落地形状与 M2-M4 切分;矩阵 declarative-plugin-contract Windows 状态随代码更新为 partial(pending)
- plugin_host/install.rs:ZIP/目录→私有快照(拒绝 reparse point、路径逃逸、 超限文件与恶意 ZIP 条目)→plugins.marketplace.installReview 全量审查→ 确认时摘要比对拒绝快照调包→staging 复验后激活;卸载、回滚、启用/停用 - launch.rs:runtime 启动按 versionArguments 探测实际版本,低于 minimumVersion 拒绝启动;版本 token 解析容忍 v 前缀、引号与 go/java 输出 - 设置新增一级页"声明式插件(契约 v1)":安装审查卡(未认证发布者提示、 权限与完整程序声明展开)、启用/停用/卸载/回滚,与 Worker 扩展分开列出; en-US 与 zh-CN 全套文案 - install_extension_from_url 等 Worker 非语言市场命令注册为显式占位错误 (extensionStore.notAvailable),调用方得到可诊断失败而非命令不存在 - 矩阵 plugin-marketplace/plugin-extension-management/declarative-plugin-contract Windows 证据与 notes 随代码更新;Note 增补 M2 记录
|
M2 已追加到本 PR(commit 见最新推送): 新增功能点
验证
|
- 能力声明提升:languageServers [1,2]、settings [1,2],settings-v2 fixture 由能力门控改为接受 - plugin_host/settings.rs:全局值(plugin-settings/<id>.json,默认值遗忘规则) 与项目覆盖(工作区 .lithe/plugin-settings.json,空项清理、损坏拒写)双层 存储;resolveSettings / storeSetting / workspaceConfiguration 三个命令; launch 请求现携带已存设置 - plugin_host/run_plans.rs:runPlan/testPlan 命令,展开 Core 模板后走共享 run 链路(resolveRunLaunch → startRunProcess),进程归属复用 Worker 扩展 的 ExtensionProcessOwner - 设置编辑 UI:按声明 scope/effect 渲染控件,显示值来源徽标,immediate 效果经 workspaceConfiguration 下推;show/hide 折叠进插件行 - Plugins/win/Official/PhpSupportContract:契约版 PHP bundled 包(API 2, launch kind runtime),随安装器资源分发;端到端测试覆盖 validate、 runPlan、testPlan、resolveSettings。Worker 版 PHP 保留:其 composer scripts 动态运行动作在契约 v1 无等价能力,删除会造成功能退化,完整 迁移推迟(Note 已记录) - 矩阵 declarative-plugin-settings Windows partial、declarative-plugin-contract 证据与 notes 更新;Note 增补 M3 记录
|
M3 已追加到本 PR: 新增功能点
验证
剩余
|
- plugin_host/web.rs:lithe-plugin:// 自定义 scheme 只服务启用包内普通文件 (拒 reparse point、路径逃逸、超 16MiB、非白名单扩展名),响应带 CSP(default-src 'none'、拒 eval 与联网、frame-ancestors 'none')、 nosniff、no-store、CORP - window.lithe 桥 v0:document-start 注入冻结桥;context、 ui.getState/setState(宿主持有状态,64KiB 上限)、workspace.openFile、 事件泵;build.*/functions.* 在 Windows 构建系统能力接入前返回 plugin.web.unknownMethod - 页面生命周期命令:open(去重聚焦)/close;禁用卸载清状态 (forget_plugin_state) - 能力声明 ui 提升为 [1,2],web-panel fixture 转为被接受(门控测试同步) - 管理区块新增 Web 工具窗口列表(打开/关闭),en-US/zh-CN 文案 - 矩阵 plugin-web-tool-windows Windows partial、declarative-plugin-contract evidence/notes 更新;Note 增补 M4 记录
|
M4 已追加到本 PR——全部四个里程碑完成: 新增功能点
验证
里程碑总结(M1–M4 全部完成)Windows 声明式插件宿主已覆盖契约 v1 的:包存储与信任审批、启动扫描与隔离、语言服务器启动(packaged/runtime/systemCommand + 版本探测)、磁盘导入全链路、声明式设置(含项目覆盖与 immediate 下推)、运行/测试计划、Web 工具窗口。矩阵上 Windows 的 declarative-plugin-contract / plugin-marketplace / plugin-extension-management / declarative-plugin-settings / plugin-web-tool-windows 全部为 partial(pending),差实机验收。遗留边界已记录在 Note:publisher 签名延后、Worker 版 PHP 保留(composer 动态动作无契约等价能力)、build.* 桥与构建系统能力、多仓库源市场。 |
|
实机验收结果(Release 构建): 构建验证
实机运行验证
环境备注(本机问题,不影响 CI/其他开发者)
状态
|
Lithe Review结论: ⛔ 有阻塞 Findings
Scope Check
Suggestions
Summary两项 P1 分别涉及插件权限隔离和声明式 LSP 的必然启动失败,需在合并前修复。其余 P2 为非阻塞建议。当前测试主要证明契约校验、存储辅助函数和模拟映射,不能证明新增产品链路可用。 Verification
|
xiaoyumuxi
left a comment
There was a problem hiding this comment.
跨 PR 审查:Windows 声明式插件宿主(head 2d9860a6)
结论:建议先处理安全隔离,再合并。 本轮是静态代码审查;尚未在 Windows WebView2 上执行恶意插件验证。
- [P1] 插件 WebView 可能继承过宽的 Tauri 权限。
windows/tauri/src-tauri/capabilities/main.json:5仍是"windows": ["*"],并允许文件读写、删除、通用 HTTP 等权限;plugin_host/web.rs:118-126新建的plugin-web-*是 Tauri WebviewWindow,页面脚本又可使用内部 IPC。仅冻结window.lithe、使用 CSP,并不足以证明不能直接调用其他已注册的 Tauri 命令。请将主窗口与插件窗口 capability 按 label/来源隔离,只赋予插件专用最小权限;补充从真实插件页调用未授权 fs/http/宿主命令应被拒绝的测试。 - [P1/P2] 桥接身份由请求方自行传入,缺少与调用窗口的绑定。
plugin_host/web.rs:253-283的declarative_plugins_web_bridge_request接受客户端传来的plugin_id/window_id,直接用作状态 key 或触发workspace.openFile事件,未核对WebviewWindow.label、当前插件是否启用及该页面是否属于此插件。请从可信窗口上下文解析身份,做插件/窗口/工作区鉴权,添加跨插件伪造参数的拒绝回归。 - [P2] 停用/卸载的页面生命周期与窗口标识未完全收敛。
install.rs:152-194只变更安装记录并 rescan,未同步关闭当前已打开的插件 WebView;web.rs:99-105,133-143按裸window_id查找和构造 window label,不含plugin_id,不同插件同名窗口可能互相干扰。建议 native 宿主统一跟踪并关闭所属窗口、进程和状态,标识使用组合 key。 - [P2] 目录导入缺少 ZIP 分支已有的总量和数量限制。
install.rs:349-404的copy_tree_bounded只限制单文件大小与递归深度,没有限制累计字节数及条目数;导入大目录可耗尽应用数据盘。请与 ZIP 分支共享限额计数器,并在失败时清理 snapshot。 - [P2] 版本更新激活并非完全原子。
install.rs:298-309删除现有version_directory后才 rename staging;rename 失败可能让原安装记录指向已被删除的版本。建议使用备份/交换和失败恢复,新增受文件占用影响的测试。
以上问题与本 PR 新增宿主的安全、生命周期和安装职责直接相关;正常 Release 启动验收不能替代恶意插件权限测试。
P1(两项): - 插件 WebView 脱离主窗口通配 capability:main.json 收窄为 main/workspace-*, 新增 plugin-web capability(core:event 最小集,无 fs/http/shell/dialog); 桥身份改由调用 webview label 反解(bridge_identity),核对插件启用、 窗口声明与归属,伪造参数/跨插件/非插件窗口一律 plugin.web.forbidden - launch 解包 Core 响应信封后再解析(outcome["plan"]),新增走真实 Core 命令的回归测试(此前单测绕过了信封导致该路径必然失败) P2: - 设置编辑器按 ID 从宿主 catalog 取完整 manifest(新增 declarative_plugins_manifest 命令),resolve/workspaceConfiguration 不再 传 ID 占位清单;加载与解析错误保持可见 - 运行入口接通:新增 declarative_plugins_language_owner 归属查询,run 动作发现接入 useRunActionDiscovery(source: declarative),运行菜单 直接分发;删除会漂移的前端目录缓存 - 停用/卸载/回滚前关闭插件全部 Web 窗口并清状态;scheme 文件服务只服务 enabled 包 - workspace.openFile 接前端监听(plugin-web-open-file.ts):限工作区根内 路径,走 handleFileSelect(带 line/column) - 版本探测宿主只跑 versionArguments,判断委托 Core checkRuntimeVersion(共享 runtime-versions 语义),删除自建解析器
|
Review 意见已全部处理(commit e7130f9): P1 两项
P2 五项
验证
|
|
CI 失败诊断与处置: 上一轮 CI 的两个失败均与本 PR 代码无关:
处置:分支此前落后 preview 3 个提交(#1331 push target、#1411 Agent parity、#1427 自然排序),已合并 origin/preview(df2b8b6c,无内容冲突)。合并后本地验证:src-tauri 全量 326 passed、 另说明:工作树曾出现一批带冲突标记的残留文件,经核查是 2026-08-16 一份旧 stash( |
|
第二轮 CI 结果与处置: 上一轮 CI 的两个失败已消失(合并 preview 后
以上三个失败点没有一个是本 PR 代码路径:我们的 delta 在 merge ref 中只有 |
|
@lithe review |
Lithe Review结论: ⛔ 有阻塞 Findings
Scope Check
Suggestions
SummaryCore 复用和 Windows 宿主分层整体符合仓库边界,但新增插件 WebView 仍可触达不受限的应用命令,构成合并阻塞的安全问题。其余问题会影响文件打开、运行时设置、进程清理和 test plan 的端到端可用性;安装激活和契约文档也需要补齐。 Verification
|
|
@lithe review |
P0: - invoke_handler 包装插件页门控:label 为 plugin-web-* 的调用只允许 declarative_plugins_web_bridge_request(改为直调的普通函数,消费原始 Invoke,绕过宏推断问题),其余应用命令(run_start_process 等进程/文件/ HTTP 面)一律 resolver.reject——插件页面无法再通过原始 Tauri IPC 调用 宿主命令 - generate_handler 宏在非直接实参位置无法推断 R:用 Box<InvokeHandler<Wry>> 在绑定处钉定(本地最小复现 crate 验证) P2: - initializePluginWebOpenFileListener 真正接入 bootstrap(此前只有定义) - immediate 设置:编辑器取 Core 展开的 configuration 后经 lsp.updateWorkspaceConfiguration 下推到运行中的 LSP 会话 - 停用/卸载时 Rust 发 declarative-plugin-lifecycle 事件,前端进程 owner 停止该插件全部声明式运行会话 - test plan 产品入口:declares_tests 标记进入 catalog,运行菜单的声明式 动作按插件测试模板走 testPlan(v1 传当前文件供项目标记判定) - 同版本重装激活失败时备份/恢复原版本目录,不再出现安装记录指向缺失 字节的隔离状态(新增恢复路径测试) P3: - 共享契约 README 更新 Windows ui: [1,2] 状态与桥 v0 方法范围
|
第三轮 review 意见已全部处理(commit a3c4dca): P0:插件 WebView 调用未授权应用命令
P2 五项
P3
验证
|
|
@lithe review |
Lithe Review结论: ⛔ 有阻塞 Findings
Scope Check
Suggestions
Summary命令未注册是合并前必须修复的 P1。其余 P2 为非阻塞修改建议。分层与 Core 复用方向符合仓库边界,但现有辅助函数和契约测试不足以证明产品入口、设置传递及资源清理完整可用。 Verification
|
|
@lithe review |
改动说明
按 Agent Note(本 PR 内同增)落地 Windows 声明式插件宿主第一个里程碑。Windows 从此可以加载契约 v1(
shared/contracts/plugins/v1)格式的语言插件包,与 macOS / Lithe Store 同格式;现有 Worker 扩展模型不受影响。功能点
Rust 宿主(
windows/tauri/src-tauri/src/plugin_host/,新增模块)store.rs:包存储布局。已安装包在app_local_data_dir()/plugins/<pluginID>/<version>/+installation.json(记录缺失/损坏/版本不匹配的包一律隔离,不静默加载);bundled 包从资源目录OfficialPlugins只读加载,多版本取最高;数字感知的版本比较(1.10 > 1.9、prerelease 排在正式版前);插件状态目录与稳定的工作区哈希。scan.rs:启动扫描。每个包的plugin.json经lithe_core::execute_json走plugins.declarative.validate,payload 携带宿主能力声明hostCapabilities = {languages:[1], languageServers:[1], serverProcess:[1]}——声明了更高能力(settings 2 / ui 2 / buildSystems)的包由 Core 以plugin.api.unsupported自动拒绝,宿主零额外逻辑;拒绝的包隔离并向前端暴露稳定错误码。launch.rs:启动计划解析。调plugins.declarative.languageServerLaunchPlan把声明展开成进程命令行:packaged入口必须是包内普通文件(拒绝 reparse point/符号链接与规范化路径逃逸);runtime/systemCommand经 PATH 探测(复用 language_tools 的查找),导出 macOS 同款LITHE_<TOOL>_PATH并把 packaged runtime 目录前置到PATH。语言服务器进程本身仍由共享 Core 的lsp.startServer拉起,会话所有权不分裂。tests.rs:共享 fixtures 全量验收——invalid-manifests.json全部 154 个用例在 Windows 二进制内断言同一稳定错误码(矩阵与 macOS Note 定义的接入验收线);合法样例分"纯契约"与"v0 能力门控"两种模式断言。前端
features/plugins/declarative-plugin-launch.ts:宿主 API 薄封装(rescan / state / launch)。features/editor/lsp/resolve-editor-lsp-launch.ts:Worker 扩展清单没有对应服务器时,回落到契约插件启动(契约插件排在 Worker 之后,已由 Worker 声明的语言保持现状直到 M3 包迁移)。features/bootstrap/bootstrap-async.ts:bootstrap 增加 "declarative plugins" 扫描步骤。declarative_plugins_rescan/declarative_plugins_state/declarative_plugins_language_launch。文档与矩阵
declarative-plugin-contract.jsonWindows:evidence 换成 Windows 实现文件 + fixtures,状态 missing→partial(pending),notes 记录已实现与未实现边界。明确未做(后续里程碑)
minimumVersion探测、管理界面、install_extension_from_url死链处置。验证
cargo test plugin_host:12/12(含 154 个 fixture 用例);src-tauri 全量cargo test:308 passed, 0 failedbun test resolve-editor-lsp-launch.test.ts:5/5;workspace-git-bootstrap.test.ts:5/5;bun run typecheck通过node scripts/verify-agent-notes.mjs(130 篇)、generate-platform-feature-matrix.mjs+verify-platform-feature-matrix.sh(188 能力点)、verify-windows-boundaries.sh均通过scripts/build-windows.ps1Release 构建随 ready 后完整 CI 补上);矩阵 verificationStatus 保持 pending,等实机验收