Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/gitoxide-helper-admission.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

name: Gitoxide helper admission

on:
pull_request:
paths:
- '.github/workflows/gitoxide-helper-admission.yml'
- 'native/gitoxide-helper/**'
push:
branches:
- main
paths:
- '.github/workflows/gitoxide-helper-admission.yml'
- 'native/gitoxide-helper/**'

permissions:
contents: read

concurrency:
group: gitoxide-helper-admission-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
steps:
- uses: actions/checkout@v4
- name: Check Rust formatting
working-directory: native/gitoxide-helper
run: cargo fmt --check
- name: Test the short-lived Gitoxide helper
working-directory: native/gitoxide-helper
run: cargo test --locked
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ docs/assets/
apps/desktop/tests/real-window-smoke/
deepseek.key

# Built only by the dedicated Gitoxide helper lane; normal workspace tests do not use Cargo.
/native/gitoxide-helper/target/

# Generated Computer Use executor binary; provenance metadata stays tracked.
apps/desktop/resources/bin/
# Rebuilt from experiments/windows-sandbox by scripts/package-windows-x64.mjs.
Expand Down
115 changes: 115 additions & 0 deletions docs/architecture/gitoxide-helper-artifact-authority-v1.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

# Gitoxide helper artifact authority v1

状态:stacked 验证切片;尚无正式 release issuer、Desktop/CLI/Runtime Host 生产消费者,必须保持
Draft。

## 1. 主要不变量

本切片只证明:

> 普通 caller 不能用自报的 executable path 或 SHA-256 获得 Gitoxide helper 调用资格;只有内部
> release owner 签发、与 owner token 绑定的 artifact claim,在 exact platform、architecture、
> protocol、size 与 SHA-256 校验通过后,才能转换为另一个指定 owner 可消费的 opaque invocation
> capability。artifact 在 admission 后变化时,调用前重验必须 fail closed。

它不证明平台签名、安装目录保护、helper spawn、repository observation、T1 admission、managed
workspace 或 crash recovery。

## 2. Owner 与 API 权限

```text
未来的 packaged-release owner
└─ issueGitoxideHelperReleaseArtifactClaimInternal(ownerToken, exact artifact identity)
↓ opaque release claim
artifact authority
└─ exact file/platform/protocol verification
↓ opaque invocation capability
未来的 invocation owner
└─ verifyGitoxideHelperArtifactForInvocationInternal(ownerToken, capability)
```

- claim 与 capability 的状态存放在模块私有 `WeakMap` 中;对象表面不包含 path、digest 或 size。
- claim 必须由相同的 release owner token 消费;capability 必须由签发时指定的 invocation owner token
消费。
- 相关 internal API 不从 `@maka/runtime-host/server` 导出。
- 旧的 caller-provided `{ executablePath, expectedSha256 }` 不能成为这条链的 authority。

当前没有 production release owner。`issueGitoxideHelperReleaseArtifactClaimInternal()` 只是未来受信
packaging owner 的接缝,不是签名信任根;在该 owner 落地前,本切片不能转 Ready。

## 3. 校验边界

一次 artifact 校验包含:

1. 输入 claim 的 protocol/platform/architecture/size/digest 形状检查;
2. 拒绝 claimed path 任意组件中的 symlink 或 Windows junction;
3. 打开 canonical regular file,并限制 helper artifact 最大为 256 MiB;
4. 在同一 handle 上进行 64 KiB 有界缓冲的 SHA-256 流式读取;
5. 比较读取前后 handle identity/size/timestamps;
6. 比较读取后 path identity 与已打开 handle;
7. 比较 exact byte count 与 digest。

admission 与每次 invocation resolve 都执行这套校验。它可以识别校验之前或校验期间的替换,不会把
相邻 manifest 当作自证信任根。

## 4. 原子性、失败状态与回滚

| 项目 | v1 合同 |
| --- | --- |
| owner | Runtime Host 内部 artifact authority |
| 原子性边界 | 单个打开 file handle 的一次 identity + streaming digest observation |
| durable state | 无;claim/capability 仅存在于进程内 |
| 非法/伪造 claim | `gitoxide_helper_release_claim_invalid` |
| 平台或架构不匹配 | `gitoxide_helper_release_claim_unsupported` |
| path/symlink/读取失败 | `gitoxide_helper_artifact_invalid` |
| size/digest/identity 漂移 | `gitoxide_helper_artifact_identity_mismatch` |
| 错误 owner/伪造 capability | `gitoxide_helper_invocation_capability_invalid` |
| rollback | 只读校验,无副作用,无需回滚 |

## 5. 明确不承诺的威胁模型

本切片没有声称抵抗拥有同一 OS 用户文件写权限的主动攻击者。特别是:

- 它尚未验证 macOS code signature、Windows Authenticode 或 Linux 发布清单的受信签名;
- 它尚未把 helper 放进由正式安装器保护的只读目录;
- 它尚未拥有 spawn,因此不声称消除了“最后一次 path 校验完成后、未来 spawn 开始前”的替换窗口。

下一切片在接入 spawn 前,必须由正式 packaged-release owner 提供信任根,并明确三平台安装目录与
签名能力。不能通过给本 API 再传一个裸 expected digest 来绕过这一门槛。

## 6. 平台能力矩阵

| 平台 | 当前持续验证 | 尚未承诺 |
| --- | --- | --- |
| Linux | regular-file identity、digest、symlink path rejection | package signature、protected install root、spawn identity |
| macOS | 同 Linux | code-sign verification、notarized artifact binding、spawn identity |
| Windows | regular-file identity、digest、junction path rejection | Authenticode binding、ACL-protected install root、spawn identity |

## 7. 后续切片

后续只能按下面顺序推进:

1. 发布/安装 owner 把受信 helper identity 绑定到 signed product artifact;
2. 短生命周期 invocation owner 消费 opaque capability 并运行 strict helper protocol;
3. repository observation 再转换为 T1 前的 opaque admission capability。

在第 1 项完成以前,不接 Desktop/CLI,也不恢复旧 Git CLI adapter。
102 changes: 102 additions & 0 deletions docs/architecture/gitoxide-short-lived-helper-admission-v1.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

# Gitoxide short-lived helper:repository admission v1

状态:验证切片;尚无 Desktop、CLI、Runtime Host 或 M2 生产消费者,只能保持 Draft。

## 1. 主要不变量

本切片只证明:

> 在选择 managed-workspace durable mode 或写入 T1 以前,Git backend owner 可以通过一个
> 短生命周期、隔离配置的 Gitoxide helper 观察 repository object format 和 exact HEAD identity;
> 只有 SHA-1 repository 返回 observation,SHA-256 与未知格式稳定 fail closed,且不得调用或
> 回退到系统 Git。

它不证明 source import、clone、fetch、worktree、candidate、projection、ref CAS、Write/Edit 或
resume。现有 dormant `GitWorkspaceService` 也没有切换到该 helper。

## 2. 为什么是 helper,不是常驻 broker

`maka-gitoxide-helper` 每次启动只执行以下协议:

```text
stdin: 一个最大 64 KiB 的 strict JSON request
Gitoxide isolated repository observation
stdout: 一个 JSON response
process exit
```

进程不监听 socket、不复用 repository handle、不保存 caller identity,也不拥有跨请求锁或可恢复
状态。因此它不是新的常驻 authority;durable ownership 仍必须由未来的 Storage/Runtime owner
通过 SQLite、artifact receipt 与 scoped capability 建立。

## 3. Owner、原子边界与失败状态

| 项目 | v1 合同 |
| --- | --- |
| operation owner | 单次 `maka-gitoxide-helper` 子进程 |
| 输入 | `inspect_repository` strict JSON,最大 64 KiB |
| 配置边界 | `gix::open::Options::isolated()` + `strict_config(true)` |
| 成功 | exit 0;SHA-1 + exact HEAD commit/tree OID |
| policy rejection | exit 2;`unsupported_object_format` |
| operational failure | exit 1;稳定 `helper_error.reason` |
| 原子性边界 | 单个 repository handle 的一次只读 observation;无跨介质事务 |
| rollback | 只读操作,不需要回滚 |

当前 response 中的 observation 不是不可伪造的进程外 capability。未来 Node/Runtime adapter 必须先
验证 helper binary/release identity、绑定 invocation input,并把 observation 转换为 owner-issued
opaque capability;不能让 caller 直接提交裸 OID 或 object format。

## 4. SHA-256 策略

Cargo 编译 `sha256` feature 只用于识别并给出稳定拒绝,不代表 Maka 已支持 SHA-256 repository。
v1 的 `supportedObjectFormats` 固定为 `["sha1"]`。未来支持必须显式升级 backend capability 与
协议测试,禁止静默 fallback。

## 5. 测试与工具链

- 普通 `npm test`、TypeScript workspace 测试和最终用户运行不要求 Rust 工具链。
- 修改 helper 时运行 `npm run test:gitoxide-helper`。
- `Cargo.lock` 是 source/build identity 的一部分并进入版本控制。
- 三平台独立 CI 构建同一源码并运行协议测试。
- 测试使用 Git CLI 预先构造真实 fixture;启动 helper 后清空 `PATH` 并注入恶意 Git config 环境。
如果 helper 尝试使用系统 Git 或 caller config,测试会失败。

## 6. 平台能力矩阵

| 平台 | 当前验证目标 | 尚未承诺 |
| --- | --- | --- |
| Linux | SHA-1 inspect;SHA-256 reject;无 system-Git fallback | packaging、sandbox、crash recovery |
| macOS | 同 Linux | signing、notarization、production packaging |
| Windows | 同 Linux | Authenticode、job owner、production packaging |

只有三个 CI lane 都建立证据后,才能把“当前验证目标”升级为持续平台承诺。

## 7. 下一切片

后续 stacked Draft 先建立 helper artifact claim → opaque invocation capability 的内部边界,并明确
正式 packaged-release trust root 尚未接入;详见
`gitoxide-helper-artifact-authority-v1.zh-CN.md`。再后续才把一次 repository observation 转换成
T1 前可消费的 opaque admission capability。source import、fresh projection 与 candidate ref CAS
继续分别验证,不能在 admission PR 中顺手恢复旧 Git CLI adapter。
Loading