anarlog 桌面端通知插件权限体系详解:基于 Tauri ACL 的 show_notification 与 clear_notifications 访问控制

发布时间:2026/9/17 0:22:11
anarlog 桌面端通知插件权限体系详解:基于 Tauri ACL 的 show_notification 与 clear_notifications 访问控制 anarlog 桌面端通知插件权限体系详解基于 Tauri ACL 的 show_notification 与 clear_notifications 访问控制【免费下载链接】anarlogOpen source Granola AI Alternative项目地址: https://gitcode.com/GitHub_Trending/hy/anarloganarlog 桌面应用开源 Granola 类 AI 替代品通过tauri-plugin-notification插件统一管理系统通知的展示与清理。本文以插件自动生成的权限参考文档 plugins/notification/permissions/autogenerated/reference.md 为骨架逐条解读默认权限集与 4 个命令级权限标识符并结合插件源码、权限定义文件和底层通知实现讲清楚权限如何定义、命令如何被保护、宿主应用如何按需授权这条完整链路。读完本文你将能独立看懂任意 Tauri 插件的权限参考表并能为 anarlog 的桌面端按业务场景配置最小化通知权限。一、权限参考文档是什么自动生成的 ACL 说明书在 Tauri 的权限ACLAccess Control List体系中每个插件都会维护一组权限标识符identifier宿主应用通过 capability 文件决定哪些前端窗口可以调用哪些命令。reference.md正是这一机制的自动生成说明书——它位于 plugins/notification/permissions/autogenerated/reference.md与同目录下的 commands/show_notification.toml、commands/clear_notifications.toml 一样均由构建工具根据插件声明的命令集合自动产出文件头部明确标注# Automatically generated - DO NOT EDIT!人工修改会在下次生成时被覆盖。文档结构非常规整包含两个部分Default Permission插件默认授予的权限集合即宿主应用不额外配置时前端默认能调用的命令Permission Table插件全部权限标识符及其语义说明包括允许与拒绝两个方向。这份文档的价值在于它是审计插件暴露了哪些能力、默认开放了什么、如何收紧的第一手索引。任何想为 anarlog 桌面端定制通知行为比如禁止清理通知、只允许展示的开发者都应从这张表出发。二、默认权限集两个命令默认全部开放reference.md的 Default Permission 小节说明插件默认权限集包含allow-show-notificationallow-clear-notifications也就是说宿主应用在未做任何权限裁剪的情况下前端可以同时调用展示通知与清理通知两个命令。这一默认配置的来源是 plugins/notification/permissions/default.toml[default] description Default permissions for the plugin permissions [ allow-show-notification, allow-clear-notifications, ]从 schema 看permissions/schemas/schema.json 规定了一个权限文件可以包含default默认权限集、set具名权限组和permission内联权限三类结构default下的permissions数组逐项列出默认开放的权限标识符。对照 src/lib.rs 中PLUGIN_NAME常量notification这些权限在宿主应用中将以notification:allow-show-notification、notification:allow-clear-notifications的完整命名空间形式被引用。设计考量通知是桌面 AI 助手如 anarlog 的会话提醒、日程提醒、麦克风检测提醒的核心交互通道默认全量开放可以保证插件开箱即用真正需要收紧的场景如企业托管部署、只读模式则由宿主应用通过 capability 显式配置。三、权限表逐条解读四个标识符的精确语义reference.md的 Permission Table 共列出 4 个权限标识符正好对应两个命令的允许/拒绝双向控制标识符语义notification:allow-clear-notifications启用clear_notifications命令无需任何预配置作用域notification:deny-clear-notifications拒绝clear_notifications命令无需任何预配置作用域notification:allow-show-notification启用show_notification命令无需任何预配置作用域notification:deny-show-notification拒绝show_notification命令无需任何预配置作用域每个标识符背后都是一份独立的 TOML 定义。以 commands/show_notification.toml 为例# Automatically generated - DO NOT EDIT! $schema ../../schemas/schema.json [[permission]] identifier allow-show-notification description Enables the show_notification command without any pre-configured scope. commands.allow [show_notification] [[permission]] identifier deny-show-notification description Denies the show_notification command without any pre-configured scope. commands.deny [show_notification]commands/clear_notifications.toml 结构完全一致只是命令名换成了clear_notifications。需要注意几个关键点commands.allow/commands.deny是 Tauri 权限的核心机制allow把命令加入白名单deny加入黑名单ACL 判定时黑名单优先级高于白名单without any pre-configured scope表示这些权限不涉及作用域scope参数属于全或无的命令级控制不细粒度到文件路径、URL 等资源层面deny-系列权限的价值当某个 capability 需要允许大部分能力但排除特定命令时可以用deny-做减法例如只展示通知但不允许前端批量清理通知。四、被保护的两个命令从权限标识符到真实实现权限表保护的命令并非空壳它们在 plugins/notification/src/commands.rs 中有完整实现且经由tauri_specta收集注册见 src/lib.rs 中的collect_commands![commands::show_notification, commands::clear_notifications]从而自动生成前端 TypeScript 绑定与权限元数据。4.1 show_notification展示一条系统通知#[tauri::command] #[specta::specta] pub(crate) async fn show_notificationR: tauri::Runtime( app: tauri::AppHandleR, v: anlg_notification::Notification, ) - Result(), String { let source match v.source { Some(anlg_notification::NotificationSource::CalendarEvent { .. }) calendar_event, Some(anlg_notification::NotificationSource::Session { .. }) session, Some(anlg_notification::NotificationSource::MicDetected { .. }) mic_detected, None unknown, }; let is_persistent v.is_persistent(); let has_options v .options .as_ref() .is_some_and(|options| !options.is_empty()); app.notification().show(v).map_err(|e| e.to_string())?; app.analytics().event_fire_and_forget( AnalyticsPayload::builder(notification_shown) .with(source_type, source) .with(is_persistent, is_persistent) .with(has_options, has_options) .build(), ); Ok(()) }从源码可以读出几个实现细节参数v: anlg_notification::Notification是跨 crate 共享的通知数据结构来自anlg-notificationcrate其legacyfeature 在 Cargo.toml 中被启用通过 serde/specta 序列化后可直接由前端传入通知来源source被归一化为三类枚举CalendarEvent日程事件、Session会话、MicDetected麦克风检测对应 anarlog 的核心业务场景——自动记录会议、会话摘要、语音检测提醒无来源时归为unknown展示成功后异步上报埋点notification_shown附带source_type、is_persistent、has_options三个维度用于统计各类通知的展示量与持久化/可选项占比真正落盘的动作是app.notification().show(v)它来自 src/ext.rs 中NotificationPluginExttrait 提供的Notification门面内部委托给底层anlg_notification::show(v)完成跨平台系统通知渲染。4.2 clear_notifications清空当前通知#[tauri::command] #[specta::specta] pub(crate) async fn clear_notificationsR: tauri::Runtime( app: tauri::AppHandleR, ) - Result(), String { app.notification().clear().map_err(|e| e.to_string()) }该命令无参数直接调用 src/ext.rs 中的Notification::clear()底层对应anlg_notification::clear()。有趣的是插件在 src/lib.rs 的on_event钩子中还有一个自动清理逻辑当主窗口tauri_plugin_windows::AppWindow::Main重新获得焦点时会自动调用app.notification().clear()清空通知栏失败时仅记录tracing::warn!(%error, failed_to_clear_notifications)而不中断流程。这说明clear_notifications既可以被前端显式调用也是窗口聚焦时的自动行为。五、权限之外命令背后的通知事件与生命周期理解权限表之后值得再看一眼这些命令服务的事件体系以便在宿主应用中正确消费通知交互结果。插件通过 src/events.rs 声明了 6 种NotificationEventserde tag 序列化事件类型触发时机notification_confirm折叠态通知被确认notification_accept展开态通知被接受notification_dismiss通知被手动关闭notification_timeout通知超时自动消失notification_option_selected通知中的某个选项被选中携带selected_indexnotification_footer_action通知底部操作被点击这些事件由 src/handler.rs 通过anlg_notification::setup_*_handler系列回调注册回调触发时会同时做三件事唤起主窗口app.windows().show(AppWindow::Main)、向前端emit对应事件、向 analytics 上报notification_actioned/notification_dismissed/notification_timed_out等埋点。从更深一层看底层 crate crates/notification/src/lib.rs 用BoundedTimedMap实现了通知上下文管理去重窗口 1 分钟DEDUPE_WINDOW、上下文 TTL 10 分钟CONTEXT_TTL、最近通知与上下文各自最多保留 256 条MAX_RECENT_NOTIFICATIONS/MAX_NOTIFICATION_CONTEXTS通知未显式指定图标时会依据NotificationSource::default_icon()自动补齐默认图标在启用legacyfeature 时按平台分发到anlg_notification_macos/anlg_notification_linux/anlg_notification_windows实现。这些细节解释了为什么show_notification命令接收的是一个结构丰富的Notification对象而非简单的标题正文。六、宿主应用如何引用这些权限在 Tauri 的 ACL 约定中宿主应用通过 capability 文件通常位于src-tauri/capabilities/*.json为指定窗口/WebView 授予权限权限标识符格式为插件名:权限名。对本插件而言常用组合包括{ identifier: main-capability, windows: [main], permissions: [ core:default, notification:allow-show-notification, notification:allow-clear-notifications ] }若只想展示通知、禁止前端清理通知可改为仅引用notification:allow-show-notification配合notification:deny-clear-notifications做显式双保险若希望完全禁用插件能力则两者都不引用即可。由于reference.md及对应 TOML 是自动生成的权威来源在修改权限前应以当前仓库中的 reference.md 为准避免引用已废弃的标识符。七、从源码结构看权限的生成与消费闭环将整条链路串联起来可以清晰地看到权限体系在 anarlog 通知插件中的完整闭环命令声明src/commands.rs 用#[tauri::command]#[specta::specta]声明show_notification、clear_notifications插件注册src/lib.rs 通过tauri_specta::Builder的collect_commands!收集命令、collect_events!收集事件并以ErrorHandlingMode::Result统一错误处理权限文件生成构建工具依据命令集自动产出 permissions/autogenerated/reference.md 与两个命令 TOML同时结合手写的 permissions/default.toml 形成默认权限前端绑定js/index.ts 直接export * from ./bindings.gen而bindings.gen.ts由 src/lib.rs 中的export_types测试用例通过 specta 生成并自动追加// ts-nocheck宿主授权与执行宿主 capability 按标识符授权 → 前端调用绑定函数 → ACL 校验通过 → 命令执行 → 底层 crates/notification 完成跨平台展示与去重 → 用户交互经 handler.rs 回传事件与埋点。八、小结reference.md虽只有一张权限表却是理解 anarlog 通知插件安全边界的入口默认开放的两个权限保证了开箱即用四个allow/deny标识符提供了命令级的精细控制而背后的命令实现、事件体系与底层通知引擎则让这份权限表具备了真实的业务承载。无论是安全审计、能力裁剪还是深入理解 Tauri 插件 ACL 机制这张表及其对应源码都是值得反复对照的权威依据。【免费下载链接】anarlogOpen source Granola AI Alternative项目地址: https://gitcode.com/GitHub_Trending/hy/anarlog创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考