Skip to content

fix(tauri): restore IPC capabilities — plugin:* IPC was silently ACL-denied - #13

Closed
Haaaiawd wants to merge 3 commits into
masterfrom
fix/tauri2-capabilities
Closed

Haaaiawd wants to merge 3 commits into
masterfrom
fix/tauri2-capabilities

Conversation

@Haaaiawd

@Haaaiawd Haaaiawd commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Summary

  • 根因(修正 brief 的一层):__TAURI__ 在 2.0.x 其实注入了(withGlobalTauri: true 控制注入,与 capabilities 无关)。真正死掉的是 plugin:* 命令:仓库没有任何 capabilities/ 文件 → Tauri 2 的 ACL 把 plugin:event|listen、plugin:window|hide/set_position 全部拒绝,而 app command 直通 → 界面正常、提示词正常、轮盘永远聋掉。Rust 照样 show() 出 320px 透明 always-on-top 窗口——比"没反应"更糟,它还会吞点击。
  • capabilities/default.json:单 capability 覆盖 main + wheel-panel,只授 JS 层真实调用的面(拆分理由与完整映射见 .loom/design/task-brief-capabilities-fix.md TASK-009 节)。
  • 降级不再静默:probeIpcEnvironment() 区分 no-bridge/acl-denied(实探 event.listen),boot 时失败 → 主窗口顶部持久双语 banner;轮盘 init 失败 → 窗口内可见错误卡(不再是隐形覆盖层)。window.__PK_IPC_ENV__ 留存探针结果供诊断引用。
  • CI 防线三层:scripts/check_capabilities.mjs(frontend job,纯 Node 校验窗口覆盖 + 权限 identifier 对照 acl-manifests.json + 解析出必需 allow 集)、main.rs 里的 cargo test 断言、release.yml 构建后验证 gen/schemas/capabilities.json 非空且覆盖两窗。
  • 录制器症状归因说明:apply_settings/check_hotkeys 是 app command,不走 ACL——提交被拒是 commitHotkey 看到注册非 ok 后的回滚(真实注册失败被正确表面化)。capabilities 与此无关;若升级后仍复现,请用「链路诊断」按钮发回 JSON。
  • v1→v2 迁移核查:withGlobalTauri 保留(JS 直接用全局对象);security.csp: null 合法(无 CSP,本地应用可接受);#[tauri::command]+generate_handler! 仍是正确机制;named pipe(ipc_listener.rs/inject_pipe_client.rs)是应用自有 IPC,不需要 capability;未发现其他 v1 残留。

Test plan

  • python tests/e2e/no_tauri_e2e.py — 13/13(新增无-mock 用例:no-bridge + acl-denied × 主窗/轮盘)
  • python tests/e2e/hotkey_status_e2e.py — 10/10
  • python tests/e2e/hotkey_recorder_e2e.py — 22/22
  • node scripts/check_capabilities.mjs — 正向通过;去掉 wheel-panel 或 mutating 权限 → 正确失败
  • CI: cargo check / clippy / cargo test(本机无 cargo 未编译——测试仅读 JSON 文件,风险极低)

不合并,等真机验证轮盘热键。

Generated with Devin

haa added 3 commits October 7, 2026 05:51
…denied (LOOM TASK-009)

2.0.1/2.0.2 shipped zero capability files, so Tauri 2's ACL rejected every
plugin:* call (event.listen, window.hide, window.set_position) while app
commands still answered — the UI looked healthy and the wheel was deaf.
All e2e mocked window.__TAURI__, so nothing caught it.

- capabilities/default.json covers main + wheel-panel with the exact
  surface the JS layer calls (core:default + allow-set-position + allow-hide)
- probeIpcEnvironment() distinguishes no-bridge vs acl-denied; boot shows a
  persistent bilingual banner instead of a transient toast; the wheel window
  renders a visible error card instead of an invisible always-on-top overlay
- guards: scripts/check_capabilities.mjs in frontend CI, a cargo test in
  main.rs, release.yml verifies the resolved capabilities are non-empty
- new e2e tests/e2e/no_tauri_e2e.py runs with NO __TAURI__ mock
Haaaiawd pushed a commit that referenced this pull request Oct 7, 2026
@Haaaiawd

Haaaiawd commented Oct 7, 2026

Copy link
Copy Markdown
Owner Author

已通过 squash 合并入 master(commit 330e7c4),PR 忘记关闭,非废弃。

@Haaaiawd Haaaiawd closed this Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant