桌面应用跨平台【免费下载链接】nativeToolkit for building native desktop apps项目地址https://gitcode.com/gh_mirrors/ze/native点击查看免费下载导读本文是 Native SDK一个用于构建原生桌面应用的跨平台工具包中「桥接Bridge、安全与原生能力」的完整技术指南讲解 JavaScript 前端如何通过window.zero.invoke()调用原生 Zig 代码以及桥接命令、内置命令、权限、窗口、子 WebView、对话框、导航策略与外部链接如何在一个默认拒绝default-deny的安全模型下协同工作。读完本文你将能注册并暴露自己的原生桥接命令、按命令与来源origin精确配置安全策略、从 JavaScript 启用窗口/分层 WebView/原生对话框等内置能力并掌握全部错误码与限制写出安全且可维护的混合应用。本文以 skill-data/core/references/bridge-security-native-capabilities.md 为核心骨架并结合仓库源码src/bridge/root.zig、src/security/root.zig、src/runtime/builtin_bridge.zig 等与类型声明packages/native-sdk/native-sdk.d.ts进行源码级佐证。Bridge 架构JavaScript 如何调用原生 Zig在 Native SDK 中JavaScript 通过一个统一的异步调用入口访问原生能力const result await window.zero.invoke(native.ping, { source: webview });window.zero.invoke(command, payload)是前端与原生世界的唯一信道command是已注册的桥接命令名payload是任意 JSON 值。该调用会打包为一个请求包进入运行时Runtime由运行时统一完成解析、检查、路由与响应。运行时处理一次调用遵循固定的 5 步流程解析 JSON 请求拆出id、command与原始payload三个字段。强制消息大小限制超限请求直接以payload_too_large拒绝。检查来源origin与权限命令策略要求来源匹配、权限齐备否则拒绝。查找已注册的处理器handler在注册表中按命令名查找找不到返回unknown_command。执行处理器并返回 JSON 响应处理器结果经 JSON 合法性校验后封包返回。这五步在源码中一一对应 src/bridge/root.zig 的Dispatcher.dispatch()先做max_message_bytes检查再parseRequest()随后policy.allows()做策略校验接着registry.find()查处理器最后执行handler.invoke_fn并用writeSuccessResponse包装结果src/bridge/root.zig#L142-L164。关键安全前提是桥接命令默认拒绝default-deny一个命令必须同时满足已在 Zig 中注册与被策略允许两个条件二者缺一不可。即便代码里注册了处理器策略未放行时调用方仍会收到permission_denied。Handler 模式在 Zig 中注册桥接命令应用侧在 Zig 中编写处理器函数签名固定为接收context、invocation与输出缓冲区fn ping(context: *anyopaque, invocation: native_sdk.bridge.Invocation, output: []u8) anyerror![]const u8 { _ invocation; const self: *App ptrCast(alignCast(context)); self.ping_count 1; return std.fmt.bufPrint(output, {{\message\:\pong\,\count\:{d}}}, .{self.ping_count}); }要点context指向应用状态本例中借它自增ping_count通过ptrCast(alignCast(context))还原为*Appoutput是运行时提供的结果缓冲区处理器必须把合法 JSON写进去并返回切片invocation携带请求详情request与source其中source.origin是调用来源不需要时用_ invocation忽略。接着用 Dispatcher 模式把处理器与策略组装起来fn bridge(self: *App) native_sdk.BridgeDispatcher { self.handlers .{.{ .name native.ping, .context self, .invoke_fn ping }}; return .{ .policy .{ .enabled true, .commands policies }, .registry .{ .handlers self.handlers }, }; }其中policies是需要单独定义的命令策略数组见下文安全策略。Dispatcher在源码中是policy registry async_registry的组合src/bridge/root.zig还支持异步处理器AsyncHandler通过AsyncResponder.success/fail延迟应答适合耗时操作。返回用户可控字符串时务必转义否则会产生注入无效 JSON乃至响应走私风险。正确写法是return native_sdk.bridge.writeJsonStringValue(output, user_name);writeJsonStringValue会把字符串写成合法 JSON 字符串字面量含引号、反斜杠转义。仓库测试src/bridge/root.zig#L408-L421验证了这一点未经转义的hello user会被判定为非法 JSON 并以handler_failed拒绝writeSuccessResponse内部先做json.isValidValue校验非法即降级为错误响应。消息大小限制桥接信道对每条消息都有硬性上限超出即拒绝项限制请求消息request message16 KiB响应response16 KiB处理器结果handler result12 KiB请求 ID64 字节命令名command name128 字节需要说明的是skill 文档给出的 16 KiB 是编写桥接代码时应遵循的安全默认值运行时底层还定义了更宽的物理上限——src/bridge/root.zig 中max_message_bytes、max_response_bytes、max_result_bytes均为 1 MiBmax_id_bytes 64、max_command_bytes 128命令名与 ID 上限与文档一致。parseRequest与validId/validCommand会分别校验 ID 与命令名的字符集禁止控制字符、引号、反斜杠、空格与/见 src/bridge/root.zig。大数据传输建议不要把大数据硬塞进单条桥接响应。正确做法是将大数据写入原生文件/资源通过桥接只传递引用路径、ID或采用分块chunking模式将数据切分为多条小消息分批传输避免把整个文件内容、大型图片或日志塞进一个invoke返回值。安全策略默认拒绝精确放行核心默认值Native SDK 的安全模型以最小权限为出发点以下是默认行为未配置即拒绝不授予任何权限除非在权限列表中显式列出拒绝所有桥接命令除非策略允许该命令阻止导航除非目标 origin 在导航允许列表中拒绝外部链接除非显式配置始终拒绝对话框内置命令除非在builtin_bridge中显式列出。Manifest 配置示例桥接命令与安全策略既可写在应用清单app.json/app.zon也可在运行时的策略对象中直接配置。以下为清单ZON 语法示例.permissions .{ window }, .capabilities .{ webview, js_bridge }, .bridge .{ .commands .{ .{ .name native.ping, .origins .{ zero://app } }, }, }, .security .{ .navigation .{ .allowed_origins .{ zero://app, http://127.0.0.1:5173 }, .external_links .{ .action deny }, }, },逐项解读permissions应用级权限例如window、filesystem、clipboard、notifications等完整常量见 src/security/root.zigpermission_window、permission_command、permission_view、permission_dialog、permission_filesystem、permission_clipboard、permission_network、permission_notifications、permission_credentialscapabilities声明应用启用的能力域例如webviewWebView 层、js_bridgeJS 桥接、native_views、gpu_surfaces等完整枚举见 packages/native-sdk/schemas/app.schema.jsonbridge.commands命令级策略每条含name、可选的permissions与originssecurity.navigation.allowed_origins主框架导航允许的 origin本地应用内容常用zero://app开发服务器常用http://127.0.0.1:5173security.navigation.external_links外部链接策略action可选deny或open_system_browsersrc/security/root.zig 定义了ExternalLinkAction与ExternalLinkPolicyallowsExternalUrl支持精确 URL 与带*前缀通配且通配必须包含合法 scheme 与路径前缀防止example.com.evil绕过见 src/security/root.zig。Origin 与权限的判定逻辑策略判定在源码中由Policy.allows()完成src/bridge/root.zigenabled为 false 直接拒绝未在commands中找到命令名则拒绝策略要求的每个权限都必须在运行时权限集中security.hasPermissions要求全部满足见 src/security/root.zig——注意若策略本身配置了permissions列表会与运行时权限取交集校验origin 校验origins为空表示任意来源否则逐条精确匹配*放行一切。实践原则优先使用精确 origin而非*。*只应留给不暴露任何原生状态的命令且仅当项目已经明确接受该风险时使用。这与 skill-data/core/SKILL.md 中偏好精确的安全策略变更而非宽泛放行的总体准则一致。内置命令窗口、分层 WebView 与对话框除应用自定义命令外Native SDK 自带一批内置桥接命令覆盖窗口、分层 WebView 与对话框。它们与应用自定义命令分开控制必须通过builtin_bridge显式启用。窗口命令Windownative-sdk.window.listnative-sdk.window.createnative-sdk.window.focusnative-sdk.window.close分层 WebView 命令Layered WebViewnative-sdk.webview.createnative-sdk.webview.listnative-sdk.webview.setFramenative-sdk.webview.navigatenative-sdk.webview.setZoomnative-sdk.webview.setLayernative-sdk.webview.close对话框命令Dialognative-sdk.dialog.openFilenative-sdk.dialog.saveFilenative-sdk.dialog.showMessage这些命令的底层分发实现在 src/runtime/builtin_bridge.zigdispatchWindowBridgeCommand窗口四命令、dispatchWebViewBridgeCommandWebView 七命令且原生-only 构建会以WebViewLayerNotBuilt教学式错误回应而非误导性的 not-found见 src/runtime/builtin_bridge.zig、dispatchDialogBridgeCommand对话框三命令分别路由到对应的 JSON 解析与平台服务调用。显式启用内置命令const app_permissions [_][]const u8{native_sdk.security.permission_window}; .security .{ .permissions app_permissions, .navigation .{ .allowed_origins .{ zero://app } }, }, .builtin_bridge .{ .enabled true, .commands .{ .{ .name native-sdk.window.create, .permissions .{ window }, .origins .{ zero://app } }, .{ .name native-sdk.webview.create, .permissions .{ window }, .origins .{ zero://app } }, .{ .name native-sdk.dialog.openFile, .origins .{ zero://app } }, }, },配置要点builtin_bridge.enabled true是总开关每条commands条目仍要单独列出命令名、所需权限与允许的 origin窗口/子 WebView 类命令通常要求window权限当应用配置了权限列表时见 src/runtime/builtin_bridge.zig 的allowsBuiltinBridgeCommand对话框命令始终默认拒绝必须显式列出js_window_api true会额外暴露window.zero.windows.*与window.zero.webviews.*这两个便捷 API但它不会绕过 origin 或权限检查——所有调用仍走同一套策略判定。从 JavaScript 管理窗口启用js_window_api与相应builtin_bridge策略后前端可以直接创建、枚举、聚焦与关闭原生窗口const win await window.zero.windows.create({ label: tools, title: Tools, width: 420, height: 320, }); const all await window.zero.windows.list(); await window.zero.windows.focus(win.id); await window.zero.windows.close(win.id);create返回的win.id是窗口句柄windows.list()返回所有窗口信息。窗口的创建参数在 packages/native-sdk/native-sdk.d.ts 中有完整类型定义除label/title/width/height/x/y外还支持restoreState默认true、titlebarstandard/hidden_inset/hidden_inset_tall/chromeless、transparent、alwaysOnTop、clickThrough、activateOnShow与可选的url初始源。窗口选择的底层实现支持按id或按label解析resolveWindowSelector见 src/runtime/builtin_bridge.zig。窗口状态持久化依赖稳定的 label请为窗口使用有意义的标签如main、settings、tools、preview这样窗口的几何状态、显示/隐藏策略才能在重启后稳定恢复restore_state。分层 WebViewsLayered WebViews子 WebView 是叠放在原生窗口内部的原生 WebView适合做预览面板、浏览器风格标签页、辅助工具栏等。前端创建与操控示例const preview await window.zero.webviews.create({ label: preview, url: https://example.com, frame: { x: 24, y: 24, width: 480, height: 320 }, layer: 10, bridge: false, }); await preview.setZoom(1.25); await preview.setLayer(20); await preview.close();create的完整选项见 packages/native-sdk/native-sdk.d.tslabel默认webview、windowId父窗口 id默认即调用方窗口、url其 origin 必须通过运行时导航策略、frame相对父窗口的逻辑坐标、layer原生 z 序越大越靠上、transparent尽力透明背景与bridge是否注入window.zero。返回的句柄带有setFrame/navigate/setZoom/setLayer/close方法packages/native-sdk/native-sdk.d.tssetZoom的合法范围为0.25到5.0源码中越界返回InvalidWebViewOptions见 src/runtime/builtin_bridge.zig。分层 WebView 规则WebView 的 URL 必须通过导航策略其 origin 须在security.navigation.allowed_origins内源码在createWebViewFromJson中通过validateWebViewUrl校验src/runtime/builtin_bridge.zig命令只作用于调用方所在的原生窗口windowId默认解析为调用窗口传入时必须一致main标签保留给启动 WebView子 WebView 不得使用validateChildWebViewLabel会拒绝main见 src/runtime/validation.zigmain也不能被navigate/close操作子 WebView只有以bridge: true创建时才接收window.zero——默认false这防止了不受信任内容获得原生能力后端缺口如平台不支持某操作应以invalid_request拒绝而不是静默成功。对话框原生文件选择与消息框对话框属于高风险原生能力必须显式配置builtin_bridge策略后才能调用。三个内置命令对应三种场景const files await window.zero.invoke(native-sdk.dialog.openFile, { title: Select a file, defaultPath: /home, allowMultiple: true, allowDirectories: false, }); const path await window.zero.invoke(native-sdk.dialog.saveFile, { title: Save as, defaultName: untitled.txt, }); const result await window.zero.invoke(native-sdk.dialog.showMessage, { style: warning, title: Confirm, message: Delete this item?, primaryButton: Delete, secondaryButton: Cancel, });参数说明openFiletitle、defaultPath起始目录、allowMultiple多选、allowDirectories是否允许选目录与可选的filters文件类型过滤saveFiletitle、defaultName默认文件名与defaultPathshowMessagestyle如warning、title、message、primaryButton/secondaryButton按钮文本。这些选项在进入平台层前都会经过严格校验字段长度上限、禁止空字符等见 src/runtime/validation.zig 的validateOpenDialogOptions/validateSaveDialogOptions/validateMessageDialogOptions对话框命令本身则由dispatchDialogBridgeCommand路由到系统服务src/runtime/builtin_bridge.zig。安全准则只对可信的应用 UI 使用原生对话框绝不要向远程或不受信任的 origin 暴露任意的文件系统访问能力。错误处理统一错误码所有桥接调用失败时Promise 都会 reject错误对象带error.code与error.message错误码触发场景invalid_request输入畸形、不支持的操作、导航 URL 被拒、目标缺失、重复/保留标签unknown_command没有注册对应处理器permission_deniedorigin 或权限检查失败handler_failed处理器返回错误或返回了非法 JSONpayload_too_large请求超过大小限制internal_error运行时意外故障错误码枚举定义于 src/bridge/root.zig对应的 TypeScript 类型为NativeSdkErrorCodepackages/native-sdk/native-sdk.d.ts。注意判定的优先级策略拒绝先于命令未注册——源码测试dispatcher reports permission denial before unknown command明确验证了未启用策略的native.ping返回permission_denied而非unknown_commandsrc/bridge/root.zig。前端代码必须始终处理错误try { await window.zero.invoke(native.save, payload); } catch (error) { console.error(error.code, error.message); }不要只处理成功路径尤其是用户可控输入或来自远程页面的调用务必捕获并区分permission_denied策略问题与invalid_request参数问题以便定位。源码佐证与验证手段桥接核心src/bridge/root.zig 包含Dispatcher、Policy、Registry、parseRequest、响应序列化与全套单元测试请求解析、畸形/超限拒绝、策略与 origin 校验、非法结果 JSON 拒绝等是理解整条链路的权威入口安全策略src/security/root.zig 定义权限常量、NavigationPolicy、ExternalLinkPolicy与hasPermission/allowsOrigin/allowsExternalUrl判定函数及测试内置命令分发src/runtime/builtin_bridge.zig 是 window/webview/view/dialog/os/credentials/clipboard/command 各内置命令的 JSON 解析与平台服务桥接层输入校验src/runtime/validation.zig 覆盖命令名、标签、对话框选项、通知、凭据等字段的长度与字符校验JS 类型契约packages/native-sdk/native-sdk.d.ts 提供window.zero相关 API 的完整 TypeScript 定义NativeSdkWindowInfo、NativeSdkWebViewHandle、NativeSdkInvokeError等清单 Schemapackages/native-sdk/schemas/app.schema.json 定义了app.json中bridge、security、permissions、capabilities、windows等字段的合法取值与默认值。综合来看Native SDK 的桥接体系以解析 → 限流 → 鉴权 → 路由 → 执行 → 校验响应的流水线为基础以默认拒绝、精确放行为安全内核应用自定义命令与内置命令窗口、WebView、对话框共用同一套 origin/permission 校验只是启用入口不同。遵循本文的配置示例与大小、标签、origin 约束即可在获得原生窗口、分层 WebView 与原生对话框能力的同时守住前端与原生边界的安全底线。赞分享桌面应用跨平台【免费下载链接】nativeToolkit for building native desktop apps项目地址https://gitcode.com/gh_mirrors/ze/native点击查看免费下载相关推荐Native SDK安全架构完全指南权限、能力与桥接策略的桌面应用加固清单Native SDK安全架构完全指南权限、能力与桥接策略的桌面应用加固清单 Native SDKze/native是一个用原生引擎绘制界面、不依赖浏览器和桌面应用跨平台Native SDK Canvas Preview用 Zig 在单窗口内同时托管原生 Canvas 与平台 Webview 的实战指南Native SDK Canvas Preview用 Zig 在单窗口内同时托管原生 Canvas 与平台 Webview 的实战指南 导读 本指南围绕 ex桌面应用跨平台Native SDK Capabilities 示例全解析在受信任 WebView 中安全调用 macOS 系统能力Native SDK Capabilities 示例全解析在受信任 WebView 中安全调用 macOS 系统能力 本指南以仓库中 examples/cap桌面应用跨平台上一篇preact-render-to-string性能优化5个技巧让你的渲染速度提升300%下一篇Coordinators实战教程构建一个简单的井字棋游戏创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考