Skip to content
Merged
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
177 changes: 177 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# 为 Prayu 贡献 / Contributing to Prayu

感谢你参与 Prayu。这个仓库把“可恢复、可审计、默认关闭高权限能力”视为产品合同,而不只是实现细节。请优先提交范围清晰、可以独立验证的纵向切片;涉及执行权、凭证、网络、持久化或信任边界的改动,应先把威胁模型和失败语义写清楚。

Thank you for contributing to Prayu. Resumability, auditability, and fail-closed authority are product contracts here. Prefer small, independently verifiable vertical slices. Changes involving execution, credentials, networking, persistence, or trust boundaries need an explicit threat model and failure semantics.

## 开始之前 / Before you start

1. 阅读 [架构说明](docs/architecture.md)、[项目状态](docs/PROJECT_STATUS.md) 和与改动最接近的 [ADR](docs/adr/)。长期任务还应核对 [任务书](docs/TASK_BOOK.md) 与 [项目记忆](docs/PROJECT_MEMORY.md),避免重复已完成的切片或把历史计划当成当前能力。
2. 对行为变化先开 Issue 或 Draft PR,说明用户目标、信任边界、最小验收条件和明确不在范围内的事项。新增控制平面、授权路径、数据库状态机或跨语言所有权时,先新增 ADR;沿用既有决策的小修复可以在 PR 中引用相关 ADR。
3. 不要把公开百分比、历史测试记录或 `release_ready` 文案当成验证结果。PR 只声明你在当前提交上实际运行过的检查。

## 开发环境 / Development environment

仓库和 CI 当前固定以下主版本:

| 工具 | 版本 | 来源与用途 |
|---|---:|---|
| Go | 1.25 | [`go.mod`](go.mod);唯一控制平面、CLI、TUI、HTTP API 与持久化 |
| Node.js | 24 | [CI](.github/workflows/ci.yml);`web/` 下的 React/Vite 控制台 |
| Rust | 1.97.1 | [`analyzers/rust-toolchain.toml`](analyzers/rust-toolchain.toml);确定性 Analyzer 夹具 |

建议另外安装 Git 和 rustup。普通 Go/Web 开发不要求 Docker、真实 Provider 或 API key;[`configs/models.yaml`](configs/models.yaml) 默认使用 Mock Provider。

首次检出后,按你要修改的表面准备依赖:

```bash
# Go control plane
go mod verify

# React/Vite console
cd web
npm ci
cd ..

# Rust analyzer fixtures
rustup toolchain install 1.97.1 --profile minimal --component rustfmt --component clippy
rustup target add wasm32-wasip1 --toolchain 1.97.1
```

### Windows Desktop

桌面开发和便携构建必须在 Windows 10/11 上进行,并安装 Microsoft Edge WebView2 Evergreen Runtime `94.0.992.31` 或更新版本。还需要上表中的 Go 1.25、Node.js 24 和 PowerShell;Rust 只在修改或完整验证 Analyzer 路径时需要。应用会在打开 SQLite 前检查 WebView2,缺失或过旧时失败关闭,不会自行下载或安装。

```powershell
# 在仓库根目录构建未签名的本地测试包
./scripts/build-desktop.ps1

# 发布候选验证会连续构建并比较 SHA-256
./scripts/build-desktop.ps1 -VerifyReproducible
```

产物位于忽略的 `build/desktop/`。它不是已签名发行版;自动检查通过也不能替代待完成的 Windows 10/WebView2/显示缩放人工矩阵。更多边界见 [Desktop Plan](docs/DESKTOP_PLAN.md) 和包内使用的 [本地测试说明](packaging/windows/LOCAL-TEST-GUIDE.txt)。

## 设计与实现原则 / Design and implementation principles

### 提交一个纵向切片

一个功能切片通常应同时覆盖:

1. Go 领域合同和状态转换;
2. SQLite 约束、迁移与恢复/重放语义(如有持久状态);
3. Policy、Scope、Approval、Budget、Capability 和执行租约中适用的门禁;
4. CLI、HTTP/OpenAPI、Web 或 Desktop 中真正需要的最小产品入口;
5. 正常、拒绝、取消、超时、不确定提交和重启恢复测试;
6. 对应 ADR、使用说明和项目状态更新。

不要只在 React 中模拟 Go 状态,也不要让 Rust、浏览器或桌面原生绑定形成第二套控制平面。允许的方向始终是 `TypeScript -> Go -> Rust/Docker/LLM`;授权、凭证、持久化和工作区权限由 Go 拥有。

### 保持安全不变量

- 默认失败关闭。配置档位、界面选项或模型输出都不能自行授予执行、网络、文件写入或安装权限。
- 把仓库内容、模型文本、Tool 输出、外部 Skill、Analyzer 结果和网络内容视为不可信证据,而不是指令或验证事实。
- 高权限动作继续经过独立的 Scope、Policy、人工确认、预算、Capability、幂等/恰好一次与租约检查;不能通过新增旁路“临时”绕过。
- 用户可见状态必须来自持久事实。模型声称“完成”不能替代 Finding、Evidence、Verification、Receipt 或测试结果。
- 新的 mutation 必须定义重放键、冲突、取消、崩溃和恢复行为。对外 DTO 不暴露 lease/fencing identity、operation key/digest、原始 Tool 参数或私有生命周期。
- 变更执行权限、信任边界、跨语言所有权、对外协议或不可逆迁移时,提交新的顺序编号 ADR,并写清备选方案、拒绝路径和剩余未授权能力。

数据库迁移必须只向前、可在现有数据库上重放,并同时在 Go 与 SQLite 层保留关键不变量。不要手工改写用户数据库,也不要通过迁移猜测过去不存在的授权事实。

## OpenAPI 与生成文件 / OpenAPI and generated files

Go DTO 和显式路由目录是 API 的唯一来源。修改 HTTP 路由或 DTO 后,从仓库根目录重新生成并提交这两个受测快照:

```bash
go run ./cmd/cyberagent api openapi --output docs/openapi.json
cd web
npm run generate:api
cd ..
```

不要手工编辑 `docs/openapi.json` 或 `web/src/api/schema.d.ts`。`npm run check:api` 会重新生成 TypeScript 类型并在存在漂移时失败。生成的 DTO 仍须排除凭证、Workspace 绝对根路径、Artifact/Session 私有正文、模型原始输出、Tool 参数以及 lease/fencing 标识。

## 验证 / Validation

先运行与改动最接近的聚焦检查,再在提交前扩大范围。以下命令均来自当前仓库脚本或 CI;不要在 PR 中勾选未实际运行的项目。

### 聚焦检查

```bash
# Go:以下为 HTTP/OpenAPI 改动的示例;换成实际受影响包
go test -count=1 ./internal/httpapi
go test -count=1 ./internal/httpapi -run '^TestOpenAPIDocumentIsDeterministicCapabilitySeparatedAndSecretFree$'

# Web
cd web
npm test -- src/api/client.test.ts
npm run typecheck

# Rust analyzer
cd analyzers
cargo fmt --all -- --check
cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
```

如改动影响并发、恢复、状态机或跨进程边界,应对受影响 Go 包增加 `go test -race -count=1 ...`。如改动影响 Desktop,至少运行 CI 使用的安全 tag 边界:

```powershell
go test -tags "desktop,wv2runtime.error" -count=1 ./cmd/cyberagent-desktop ./internal/desktop ./internal/webui
```

### 提交前检查

对跨层功能或准备合并的改动,运行适用的完整检查:

```bash
# Go
go mod verify
go test -timeout 20m -count=1 ./...
go vet ./...

# Web
cd web
npm ci
npm run check:api
npm test
npm run build

# Rust
cd analyzers
cargo fmt --all -- --check
cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
cargo build --locked --bin cyberagent-analyzer-fixture
cargo +1.97.1 build --locked --target wasm32-wasip1 --package cyberagent-analyzer-fixture --release
```

完整 `go test -race -timeout 20m -count=1 ./...`、`staticcheck ./...`、`govulncheck ./...`、依赖审计和 Windows 可复现构建适合权限/持久化/并发边界、累计发布门或维护者要求的改动。它们可能较慢或需要额外工具;如果本机无法运行,请在 PR 中明确列为“未运行”并依赖相应 CI/维护者门禁,不要把缺失工具写成通过。

最后运行:

```bash
git diff --check
git status --short
```

确认生成文件已提交、没有意外构建产物,且所有测试结果都对应当前提交。

## 数据、凭证与测试隔离 / Data, secrets, and test isolation

- 绝不要提交 API key、Bearer/control token、Cookie、凭证截图、`.env`、Provider 原始响应或真实模型 Prompt/Tool payload。
- 不要提交 `CYBERAGENT_HOME` 中的数据、`.cyberagent-workbench/`、`cyberagent.db`、SQLite/WAL 文件、`build/`、`web/dist/`、`node_modules/` 或 Rust `target/`。
- 手工/集成测试应使用独立临时目录或专用 `CYBERAGENT_HOME`,并默认使用 Mock Provider。不要在测试中扫描公网、产生攻击流量、启动未授权 Docker/LocalRunner,或读取系统凭证。
- Fixture 应最小化、确定、去标识化。日志、错误、Artifact 和快照必须经过现有脱敏边界;不要为了测试方便降低上限或把私有正文写入公开投影。

如果误提交了秘密,请立即停止推送并轮换凭证;仅从 Git 历史删除并不能撤销已经泄露的值。不要在公开 Issue 中粘贴可利用细节、可用凭证或敏感主机数据;如果尚无私密报告渠道,只提供最小、脱敏的影响说明,并请求维护者建立私密沟通。

## 提交与 PR / Commits and pull requests

- 从最新 `main` 创建主题分支,每个 PR 保持一个可审阅的目标;不要夹带格式化、依赖升级或历史状态重写。
- 使用简短、祈使语气的提交标题。正文解释行为、边界或迁移理由,而不是逐文件复述 diff。
- 完整填写 [PR 模板](.github/PULL_REQUEST_TEMPLATE.md):说明改了什么、为什么现在需要、用户/开发者影响、实际验证和未运行的检查。
- 行为或进度变化时更新相应使用文档、ADR 和当前状态,但不要重写历史 ADR/Progress 记录来伪造连续性。
- 明确列出安全审计结果:是否新增权限、网络、进程、文件写入、凭证、持久化或外部输入;如果答案是否,也应说明如何保持现有不变量。

小而完整的 PR 比跨越多个信任边界的大改写更容易验证和恢复。遇到不确定的授权设计时,请先提交 ADR 或 Draft PR 讨论。
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
> **仓库命名 / Repository naming**:当前产品名与界面品牌统一为 **Prayu**。为避免既有活动记录、收藏、外部链接和协作入口受到影响,GitHub 仓库名称与地址暂时保留为 [`Qiyuanqiii/CTF-CyberAgent-Workbench`](https://github.com/Qiyuanqiii/CTF-CyberAgent-Workbench)。这个历史 slug 只是稳定定位符,不是第二个产品名;本阶段不会重命名仓库、Go module、CLI 或数据目录。<br>
> **Prayu** is the product and interface name. The GitHub repository slug and URL remain unchanged for link and activity continuity. The legacy slug is a stable locator, not a second product identity; this phase does not rename the repository, Go module, CLI, or data directory.

参与开发前请阅读 [贡献指南](CONTRIBUTING.md)。Before contributing, please read the [contribution guide](CONTRIBUTING.md).

## 完成度口径 / Progress Metrics

项目从 schema v49 起同时使用两项工程指标,避免把“架构已经搭好”误解为“产品已经完整可用”。这些百分比是基于当前任务书和可验证工作流的工程估算,不是性能基准。
Expand Down