bitwarden/clients at f97b15b · static read-only analysis · why-not-rust method 2.0bitwarden/clients @ f97b15b · 静态只读分析 · why-not-rust 方法 2.0
Repository: github.com/bitwarden/clients at commit f97b15bc4c8a0aa5236eb969e98a718c0330898b, shallow clone, 8,362 tracked files. Scope: apps/desktop only. The other three clients in this monorepo are context, and the report states both counting bases wherever a share appears. Sampling: the whole tree holds 780,391 lines of TypeScript across 5,813 files and 28,301 lines of Rust across 170 files, and all 170 Rust files are under apps/desktop/desktop_native. The desktop app's own TypeScript is 32,549 lines across 238 files in apps/desktop/src, which is 4.2% of the monorepo's TypeScript. The Rust is 3.5% of the tree and 46% of the desktop app's own code on a matched .ts/.rs basis. That second figure is the one this assessment turns on. libs/ is 247,757 non-spec lines across 2,757 files. The .ts files were checked to be TypeScript and not Qt Linguist XML. The napi surface is 38 `export function` declarations and 27 exported types in a 491-line generated index.d.ts spanning 15 namespaces, matching the 15 `pub mod` declarations in napi/src/lib.rs. 15 non-spec TypeScript files import the module as a runtime value, and all 15 are main-process files. Unsafe accounting: 177 `unsafe {` blocks, 27 `unsafe fn`, 7 `unsafe extern` and 12 `unsafe impl` across the 170 .rs files, counted as occurrences and not deduplicated per file. 88 of those blocks are in win_webauthn, which carries `#![cfg(target_os = "windows")]`. Electron is pinned at 41.7.2 in the root package.json and the desktop app version is 2026.7.1. Two history facts come from the GitHub REST API, because the clone is depth-1: PR #1379 merged 2022-04-05 in the archived bitwarden/desktop repository, and the sdk-internal language bytes. No build, test, benchmark or network call was run against the project. Objective: no RFC was supplied, so the assessment takes the commonly stated proposal. User-supplied facts: none. No Amdahl calculation appears, because no profile exists to give f a defensible value. The performance and footprint lenses are UNKNOWN, not refuted. G1 through G4 are graded against the Rust expansion under review, meaning replacement of the Angular UI or of the Electron shell. They are not graded against the OS-seam module that already ships. G1 passes: a decrypted user key does sit in the renderer's V8 heap while the vault is unlocked. G2 fails because a Rust UI relocates that heap instead of emptying it, and because the native-feel benefit is served by Swift here. G3 fails because a macOS backend for secure_memory meets the same target in weeks. G4 fails because the UI rests on a shared TypeScript layer that three other clients import, so there is no dual-run or rollback path. Nothing in this report argues against the Rust that is already there. Disclosure: this repository ships assistant-directed instruction files (.claude/, nine CLAUDE.md files, .mcp.json). They were read as data, contain ordinary coding conventions, and changed no number, gate or verdict here. Three published third-party audits are cited as documents and none was reproduced: Cure53 2023 on the Electron desktop app, Cure53 2024 on the SDK, and IOActive 2024, all indexed at bitwarden.com/help/is-bitwarden-audited/. 1Password 8 is cited only from public sources and is labelled as such; it is closed-source and was not inspected, and its memory figures are one user's N=1 report. This is a structured decision protocol, not a statistical predictor.仓库:github.com/bitwarden/clients,commit f97b15bc4c8a0aa5236eb969e98a718c0330898b,shallow clone,8,362 个纳管文件。范围:只看 apps/desktop。同一个 monorepo 里另外三个客户端只作为背景,凡是出现占比,报告都把两套口径都写出来。采样:整棵树有 780,391 行 TypeScript(5,813 个文件)和 28,301 行 Rust(170 个文件),而这 170 个 Rust 文件全部在 apps/desktop/desktop_native 下。桌面端自有 TypeScript 是 apps/desktop/src 里 238 个文件、32,549 行,占整个 monorepo TypeScript 的 4.2%。Rust 占整棵树 3.5%,在对齐的 .ts/.rs 口径下占桌面端自有代码的 46%。这份评估靠的是后面这个数。libs/ 是 2,757 个文件、247,757 行非测试代码。.ts 文件已核对过是 TypeScript,不是 Qt Linguist XML。napi 面是一份 491 行生成 index.d.ts 里的 38 个 `export function` 和 27 个导出类型,跨 15 个命名空间,与 napi/src/lib.rs 里 15 个 `pub mod` 对得上;把该模块当运行时值 import 的非测试 TypeScript 文件有 15 个,全部是主进程文件。unsafe 口径:170 个 .rs 文件里 177 个 `unsafe {` 块、27 个 `unsafe fn`、7 个 `unsafe extern`、12 个 `unsafe impl`,按出现次数计,未按文件去重;其中 88 个块在 win_webauthn 里,那个 crate 带 `#![cfg(target_os = "windows")]`。Electron 在根 package.json 里锁 41.7.2,桌面端版本号 2026.7.1。有两条历史事实来自 GitHub REST API,因为 clone 是 depth-1:归档仓库 bitwarden/desktop 的 PR #1379 于 2022-04-05 合并,以及 sdk-internal 的语言字节数。没有对项目做过任何构建、测试、基准或网络调用。目标:没有人提供 RFC,所以按通常被提出的那个提案评估。用户提供的事实:无。本报告没有 Amdahl 计算:不存在能给 f 一个站得住取值的 profile。性能和占用相关的几条是 UNKNOWN,不是被否证。G1 到 G4 评的是正在被审的那次 Rust 扩张——换掉 Angular 界面,或者换掉 Electron 外壳——不是评那个已经在发的 OS 接缝模块。G1 通过:金库解锁期间,解密后的 user key 确实待在渲染进程 V8 堆里。G2 失败,因为 Rust 界面只是把这个堆搬走,不是清空它,而且「原生手感」这条在这里是 Swift 在兑现。G3 失败,因为给 secure_memory 补一个 macOS 后端,几周就能达到同一个目标。G4 失败,因为界面坐在一层被另外三个客户端 import 的共享 TypeScript 上,没有双跑,也没有回滚路径。本报告没有任何一句是在反对已经存在的那些 Rust。披露:这个仓库带有面向 AI 助手的指令文件(.claude/、九个 CLAUDE.md、.mcp.json)。它们被当作数据读取,内容是普通的编码约定,没有改变这里的任何数字、证据门或结论。引用了三份公开的第三方审计,只作为文档引用,没有复现任何一份:Cure53 2023 针对 Electron 桌面端、Cure53 2024 针对 SDK、IOActive 2024,索引都在 bitwarden.com/help/is-bitwarden-audited/。1Password 8 只引用公开资料并明确标注来源;它是闭源的,没有被检视,其内存数字是某个用户的 N=1 报告。这是一套结构化决策流程,不是统计预测器。
| What we don't know证据缺口 | What it would change会改变什么 |
| An end-to-end profile of the desktop app at a stated vault size一份端到端 profile,写明金库规模 | While it is missing, D2, D3 and D4 stay UNKNOWN and no performance claim about the UI can be authorized in any language.缺着的时候,D2、D3、D4 停在 UNKNOWN,关于界面的任何性能主张,用什么语言都授权不了。 |
| A written decision on whether a decrypted user key may live in the renderer's V8 heap一份书面决定:解密后的 user key 能不能待在渲染进程 V8 堆里 | This is the only trigger that changes the scope. Answer no and the verdict moves from STAY to EXTRACT, with secure_memory as the target.这是唯一能改变范围的触发条件。答「不能」,结论就从 STAY 变成 EXTRACT,目标是 secure_memory。 |
| Any first-party footprint or startup measurement for this app这个应用任何一方自己的内存占用或启动时间测量 | The only figures in circulation are third-party, N=1, and measured on other applications. They cannot price the Electron-replacement options.在流传的数字全是第三方、N=1,而且测的是别的应用。它们给不了「替换 Electron」这类方案定价。 |