docs: reject the landstrip evaluation for the win32 sandbox rung

User verdict: landstrip is not battle-tested — a days-old,
single-maintainer project (~48 GitHub stars at rejection), which a
security-invariant dependency cannot be. The note moves
proposed/feature -> rejected/feature with the verdict on the Status
line; the sandbox note's deferred-phases cross-link now records the
rejection instead of instructing an evaluation, and the NIH roll-up's
pointer follows. Supersedes this branch's earlier cross-link commit.
This commit is contained in:
Tianyi Cui
2026-07-27 00:55:32 +08:00
parent d0b87e8c0f
commit f520479663
9 changed files with 12 additions and 12 deletions

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-07-26-evaluate-landstrip-for-windows-sandbox-rung.md: 236139f9198f178d44cdf0867cbad2377a127359
2026-07-26-evaluate-landstrip-for-windows-sandbox-rung.zh.md: 3932f73a2bf147ce5088b5c42e85982c70cdb945

View File

@@ -0,0 +1,34 @@
# Agent Note: Evaluate landstrip before building a Windows sandbox launcher
Status: rejected — landstrip is not battle-tested (a days-old single-maintainer project, ~48 GitHub stars at rejection); a security-invariant dependency must have proven adoption, so the win32 rung keeps the in-house-launcher plan
English | [中文](2026-07-26-evaluate-landstrip-for-windows-sandbox-rung.zh.md)
## Problem
The [sandbox decision](../../implemented/feature/2026-07-06-sandbox.md) leaves `PLATFORM_CHAINS.win32` empty and plans to fill it with "a confinement runner from the AppContainer/restricted-token family, shipped from its own repository on the `node-addon-landlock-run` template" — an estimated ~1,500-line new repo (the landlock-run subtree is ~1,460 lines of C/TS/scripts/tests plus docs and CI) authored and maintained in-house.
Since that note was written, a maintained third-party runner has appeared: `@landstrip/landstrip` (npm, actively developed, Rust core with prebuilt per-platform `optionalDependencies`) covers Landlock + seccomp on Linux, Seatbelt on macOS, and AppContainer/restricted-user on Windows, with JSON/YAML policy input and a trap-fd denial-reporting channel. It is exec-wrapped like bwrap, so it fits the chain's `confine(argv)` shape without touching the Linux/macOS rungs.
## Proposal
When the Windows sandbox phase is picked up, evaluate wrapping landstrip's Windows backend as the `win32` chain runner before authoring an in-house AppContainer launcher repository. The evaluation must answer:
- **Probe synthesis.** landstrip has no `--probe`; the chain's functional-probe contract would have to be synthesized from a trap run.
- **Dialect mapping.** Denial and runner-failure stderr dialects, and fail-closed exit-code classification, need explicit mapping into the chain's vocabulary.
- **License.** The binaries are LGPL-2.1-or-later; distribution review is required before it enters the shipped closure.
- **Provenance.** The in-house launcher's value is byte-pinned native-CI provenance over a ~300-line reviewable C file; landstrip is a single-maintainer Rust binary set. For the *existing Linux rung* that trade is already settled — do not swap it ([sandbox note](../../implemented/feature/2026-07-06-sandbox.md) and the launcher's own migration away from a Rust dependency). For a rung we have not built, weighing third-party maintenance against a second in-house native repo is a genuinely open question.
## Alternatives considered
- **Build the in-house AppContainer launcher as planned.** Still the default if the evaluation fails on license, provenance, or probe fit; the cost is owning a second native security launcher repo indefinitely.
- **Swap the Linux Landlock rung to landstrip too.** Rejected outright: sandbox correctness is a security invariant, the current launcher's reviewability and provenance chain were chosen deliberately, and it already migrated away from a Rust dependency for exactly this reason.
## Acceptance criteria
- Before any Windows-rung implementation starts, an evaluation records the probe, dialect, license, and provenance answers, and the go/no-go is added to the sandbox note's deferred-phases plan.
## Risks
- Single-maintainer supply chain in a security-critical position — the reason this is an evaluation gate, not an adoption decision.
- The package is young; its API and packaging may churn before the Windows phase starts, so re-verify against the live registry then.

View File

@@ -0,0 +1,34 @@
# Agent Note: 在构建 Windows 沙箱启动器之前先评估 landstrip
Status: rejected — landstrip 未经实战检验(问世仅数天、单一维护者、驳回时 GitHub 星标约 48 个);安全不变式级的依赖必须有成熟的采用度,因此 win32 梯级维持自研启动器的原计划
[English](2026-07-26-evaluate-landstrip-for-windows-sandbox-rung.md) | 中文
## 问题
[沙箱决策](../../implemented/feature/2026-07-06-sandbox.md)将 `PLATFORM_CHAINS.win32` 留空并计划用「AppContainer/受限令牌restricted-token家族的一个约束运行器`node-addon-landlock-run` 模板从其独立仓库发布」来填充——一个估计约 1,500 行、需要自研编写并维护的新仓库landlock-run 子树约为 1,460 行 C/TS/脚本/测试,外加文档与 CI
自那份决策记录写成以来,出现了一个持续维护的第三方运行器:`@landstrip/landstrip`npm 包活跃开发中Rust 内核,附带按平台预构建的 `optionalDependencies`)覆盖 Linux 上的 Landlock + seccomp、macOS 上的 Seatbelt以及 Windows 上的 AppContainer/受限用户,支持 JSON/YAML 策略输入和基于 trap-fd 的拒绝上报通道。它与 bwrap 一样采用 exec 包装方式,因此无需触碰 Linux/macOS 梯级即可契合链的 `confine(argv)` 形态。
## 提案
当 Windows 沙箱阶段启动时,在动手编写自研 AppContainer 启动器仓库之前,先评估将 landstrip 的 Windows 后端包装为 `win32` 链运行器。评估必须回答:
- **探测合成。** landstrip 没有 `--probe`;链所要求的功能探测契约必须从一次 trap 运行中合成出来。
- **方言映射。** 拒绝与运行器失败两类 stderr 方言以及失败即关闭fail-closed的退出码分类都需要显式映射到链的词汇中。
- **许可证。** 其二进制文件采用 LGPL-2.1-or-later 许可;在进入随产品发布的依赖闭包之前需要先做分发审查。
- **溯源。** 自研启动器的价值在于对一个约 300 行、可审阅的 C 文件施以字节级锁定的原生 CI 溯源;而 landstrip 是单一维护者手中的一组 Rust 二进制文件。对*既有的 Linux 梯级*而言,这笔权衡早有定论——不要替换它(见[沙箱 Note](../../implemented/feature/2026-07-06-sandbox.md)以及该启动器自身摆脱 Rust 依赖的迁移)。而对一个我们尚未构建的梯级,在第三方维护与第二个自研原生仓库之间如何取舍,是一个真正悬而未决的问题。
## 曾考虑的替代方案
- **按原计划构建自研 AppContainer 启动器。** 若评估在许可证、溯源或探测契合度上不通过,这仍是默认选项;代价是要无限期持有第二个原生安全启动器仓库。
- **把 Linux Landlock 梯级也换成 landstrip。** 直接否决:沙箱正确性是安全不变量,当前启动器的可审阅性与溯源链是刻意选择的结果,而且它正是出于这一原因才迁移摆脱了 Rust 依赖。
## 验收标准
- 在任何 Windows 梯级实现开始之前,先有一份评估记录下探测、方言、许可证与溯源问题的答案,并把「做/不做」go/no-go的结论加入沙箱 Note 的延后阶段计划。
## 风险
- 处于安全关键位置的单一维护者供应链——这正是本提案定为一道评估门禁、而非采用决定的原因。
- 该包尚且年轻;在 Windows 阶段启动之前其 API 与打包方式可能反复变动,届时需对照线上注册表重新核验。

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-07-26-dependency-swaps-rejected-by-nih-audit.md: c988ca0c75e9c50686551f3be1971d736b971e2a
2026-07-26-dependency-swaps-rejected-by-nih-audit.zh.md: e85161cb2ee616d388aa2a9dd065c315c60cd44a
2026-07-26-dependency-swaps-rejected-by-nih-audit.md: 92ecfeef2deb7f6cca6e99b4e2de7571bc974548
2026-07-26-dependency-swaps-rejected-by-nih-audit.zh.md: 76f9c012e8986fc8b527cab263f875983bd72609

View File

@@ -67,7 +67,7 @@ Adopt the following dependency swaps. Rejected — per-item evidence below; a fu
- **`syncpack`/`manypkg` for `check-workspace-constraints.ts`**: they cover ~20 lines of range alignment; the load-bearing 200+ lines (computed `files` lists, cordis peer=dev pairing, hierarchy shape) are repo policy no generic engine expresses.
- **`remark-validate-links` for `verify-md-links.ts`**: the gate rides the repo's shared mdast toolchain; adopting remark-cli adds a second markdown stack to delete one small file.
- **`prebuildify`/`node-gyp-build` for the landlock launcher packaging**: inapplicable — those load `.node` addons via dlopen; the launcher ships a standalone exec'd static binary, and per-platform `optionalDependencies` *is* the ecosystem convention for binaries.
- **Replacing the Landlock launcher itself with `@landstrip/landstrip`**: fails the security-invariant test — the launcher is a ~300-line reviewable C file with byte-pinned provenance that already migrated away from a Rust dependency; a single-maintainer LGPL Rust binary set is a larger audit surface with weaker provenance. (The unbuilt Windows rung is a different question — see the [landstrip evaluation proposal](../../proposed/feature/2026-07-26-evaluate-landstrip-for-windows-sandbox-rung.md).)
- **Replacing the Landlock launcher itself with `@landstrip/landstrip`**: fails the security-invariant test — the launcher is a ~300-line reviewable C file with byte-pinned provenance that already migrated away from a Rust dependency; a single-maintainer LGPL Rust binary set is a larger audit surface with weaker provenance. (The unbuilt Windows rung was weighed separately and also [rejected](../feature/2026-07-26-evaluate-landstrip-for-windows-sandbox-rung.md) — landstrip is not battle-tested.)
- **`hatch-nodejs-version` for Python release versioning**: roughly LOC-neutral (a custom metadata hook replaces the regex), inverts the recorded decision that the dev sentinel never determines a release version, and puts a single-maintainer build plugin in the release supply chain.
- **YAML consolidation (`js-yaml` vs `yaml`)**: the repo carries both parsers, with the `!!js` tag defined three times on js-yaml (vendored include, app-boot, apps/cli) and twice on `yaml` (sdk-telemetry's `ScalarTag`, sdk-helper's comment-preserving Document editing). The direction is forced — js-yaml cannot replace `yaml` (sdk-helper needs the Document API) — but migrating the js-yaml sites cannot retire the library either (the vendored include pins it) and would put two parsers in charge of one dialect that must agree exactly, against the [personal-config note](../../implemented/feature/2026-07-20-dsh-cli-personal-config.md)'s deliberate load-only-copy parity. Deletable: ~2025 lines of duplicate tag definitions and two `@types/js-yaml` entries. The consolidation moment is a future include sync, not now.

View File

@@ -67,7 +67,7 @@ Status: rejected — 下列每一项替换在证据上都未达到净简化门
- **以 `syncpack`/`manypkg` 替换 `check-workspace-constraints.ts`**:它们只覆盖约 20 行的版本范围对齐;承重的 200+ 行(计算生成的 `files` 列表、cordis peer=dev 配对、层级形状)是仓库政策,没有通用引擎能表达。
- **以 `remark-validate-links` 替换 `verify-md-links.ts`**:该门禁搭载仓库共享的 mdast 工具链;采用 remark-cli 等于为删掉一个小文件而增加第二套 markdown 技术栈。
- **以 `prebuildify`/`node-gyp-build` 承担 landlock 启动器打包**:不适用——那些工具通过 dlopen 加载 `.node` addon这个启动器交付的是独立 exec 的静态二进制,而按平台划分的 `optionalDependencies` 恰恰*就是*二进制分发的生态惯例。
- **以 `@landstrip/landstrip` 替换 Landlock 启动器本身**:未通过安全不变式检验——启动器是一个约 300 行、可完整评审、来源逐字节锁定的 C 文件,且早已从一个 Rust 依赖迁移出来;单一维护者的 LGPL Rust 二进制集合是更大的审计面加更弱的来源保障。(尚未构建的 Windows 层级是另一个问题——见 [landstrip 评估提案](../../proposed/feature/2026-07-26-evaluate-landstrip-for-windows-sandbox-rung.md)。)
- **以 `@landstrip/landstrip` 替换 Landlock 启动器本身**:未通过安全不变式检验——启动器是一个约 300 行、可完整评审、来源逐字节锁定的 C 文件,且早已从一个 Rust 依赖迁移出来;单一维护者的 LGPL Rust 二进制集合是更大的审计面加更弱的来源保障。(尚未构建的 Windows 层级经单独权衡后同样被[驳回](../feature/2026-07-26-evaluate-landstrip-for-windows-sandbox-rung.md)——landstrip 未经实战检验。)
- **以 `hatch-nodejs-version` 承担 Python 发布版本号**:代码行数大致持平(一个自定义 metadata 钩子换掉那个正则却反转了「dev 哨兵值绝不决定发布版本」这条记录在案的决策,还把一个单一维护者的构建插件放进发布供应链。
- **YAML 归一(`js-yaml``yaml`**:仓库同时携带两个解析器,`!!js` 标签在 js-yaml 上定义了三次vendor 收录的 include、app-boot、apps/cli`yaml` 上定义了两次sdk-telemetry 的 `ScalarTag`、sdk-helper 的保留注释式 Document 编辑。方向是被迫的——js-yaml 无法取代 `yaml`sdk-helper 需要 Document API——但迁移 js-yaml 各调用点也退休不了这个库vendor 收录的 include 锁定了它),还会让两个解析器共管一种必须完全一致的方言,违背[个人配置决策](../../implemented/feature/2026-07-20-dsh-cli-personal-config.md)刻意的「仅加载副本」对等性。可删除的:约 2025 行重复标签定义和两条 `@types/js-yaml` 条目。归一的时机是未来某次 include 同步,不是现在。