asdfghj1237890/qa-touchstone
GitHub: asdfghj1237890/qa-touchstone
一款基于 Tauri + React 构建的本地优先 API 质量保障桌面工具,提供 API 客户端、安全测试矩阵、性能测试与 AI 辅助功能,专为 CI 中的 API 安全测试场景设计。
Stars: 0 | Forks: 0
# QA Touchstone
[](https://github.com/asdfghj1237890/qa-touchstone/actions/workflows/ci.yml)
[](#license)
[](#architecture)
[](#architecture)
[](#architecture)
[](#development)
[](#development)
[](#k6-binary)
[](#local-data-and-secrets)
[繁體中文](README.zh-TW.md)
QA Touchstone 是一款 local-first 的桌面工具,专为 **CI 中的 API 安全测试** 而设计:
运行身份 × endpoint RBAC 矩阵、BOLA/IDOR 对象授权测试,
针对您的真实 API 进行速率限制滥用检查,通过 baseline diff 管理历次运行的安全发现,
并导出您的 pipeline 可用于卡点控制的 **SARIF / JUnit / HTML / JSON** 产物。围绕这一核心,它还提供了完整的辅助工作台 —— 一个兼容 Postman 的 API 客户端(支持 REST 和 GraphQL)、实时 collection 执行、后台 monitors、k6 性能测试、AI 辅助的测试生成与分流,以及可导出的 API 文档 —— 所有这些都集成在一个 Tauri 应用中。
## 截图
**一个 local-first、兼容 Postman 的 API QA 桌面工作区** —— API 客户端、
collection runner、安全矩阵、monitors、性能测试和可导出
文档,尽在一个应用中。

| 安全矩阵 (RBAC) | AI 测试生成 | API 客户端 |
| ----------------------------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------------- |
|  |  |  |
| **生成的 API 文档** | **性能 / 负载测试** | **实时 (WebSocket / SSE)** |
|  |  |  |
在 dev server 运行时,使用 `node scripts/capture-screenshots.mjs` 重新生成(通过 DevTools Protocol 驱动系统 Chrome;设置 `LOCALE=zh-TW` 可切换为中文 UI)。
## 当前范围
当前公开的范围仅限于 API 测试:
- 用于 local、staging、production 和自定义目标的通用 API 环境
- 通过 Tauri 桌面后端执行 local 请求
- 用于确定性测试和快速 UI 迭代的 browser/dev 回退路径
- 运行时数据和凭证存储在本地机器上
- 不包含特定于公司的服务、内部链接或过时的非 API 工作流文档
## 功能
- **API 客户端**:构建 HTTP 和 GraphQL 请求(带有 schema explorer),
切换环境,检查响应,查看调用历史,并将
响应和历史记录导出为 HTML、JSON 或 CSV 报告。
- **导入/导出**:导入 Postman v2.1 collection 和 OpenAPI/Swagger JSON;
将 collection 导出回 Postman JSON。
- **认证**:No Auth、Bearer Token、OAuth 2.0(authorization-code、
client-credentials 和 password grants)、API Key、Basic Auth 和 AWS SigV4。
- **变量和 cookies**:解析 global、collection、environment 和 local
变量以及动态值({{$timestamp}}、{{$guid}}、{{$randomInt}});
通过本地 cookie jar 重放匹配的 cookies。
- **Collection Runner**:运行选定的请求,遍历 CSV/JSON 数据,并
对实时响应进行断言评分。
- **安全测试**:运行身份 × endpoint RBAC 矩阵 —— 在多个身份下发送相同的已保存
请求 —— 具有逐个 cell 的允许/拒绝预期、
可配置的拒绝状态集,以及标记敏感数据
暴露和 schema drift 的响应预言机。该矩阵预言机是 body-aware 的:一个在频带内拒绝(`{"error":"Access denied"}`)的 200 响应会被归类为拒绝,而不是误报漏洞。
对象级授权 (BOLA/IDOR) 测试会在不同身份间交换
object id,具有自动检测的 id 位置、可重用的
跨租户预设,以及一个能抑制误报的
负对照组(id 回显仅在类似身份的 key 处才被计算,且对照组由独立的结构预言机进行评分)。速率限制/滥用测试在确认门控之后发射受限的请求突发,并根据在第一个 429 之前漏过的请求数量将保护级别评级为无 / 弱 / 强。
单次 **Run full security suite** 会将所有三个引擎作为一次记录在案的运行执行 ——
速率限制排在最后,因此其突发请求不会影响矩阵和 BOLA 的结果。
另外三个引擎 —— JSON-Schema/OpenAPI **conformance** 验证、输入 **fuzzing**(5xx、stack-trace-leak 和 reflected-payload 检测),以及自动推导的 **BFLA** (OWASP API5) 扫描 —— 作为纯的、完全经过单元测试的模块发布,报告层中已经包含了 SARIF 规则元数据;UI 集成是下一步计划。
- **AI 安全分流**:将整个扫描(矩阵 + object-authz + 速率限制)浓缩为一份简短、按优先级排序、分类的候选列表 —— 哪些应首先查看,哪些
看起来是真正的问题,哪些可能是误报 —— 仅供参考,
绝不改变底层的发现。
- **安全发现生命周期**:抑制误报,覆盖严重程度,并分配
owner/status/note,然后将每次运行与固定的 baseline 进行 diff —— 显示新增/遗留/已解决
徽章,以及一个新增高危/严重级别的计数器。
- **安全报告 / CI 产物**:将完成的套件运行导出为 JSON
产物、HTML 高管报告、JUnit XML(CI 测试检查)或 SARIF
(GitHub code scanning)—— 根据新增高危/严重发现进行卡点控制,对于离开本机的产物提供三种
脱敏级别:`strict` 完全省略证据,`redacted` 保留简短的掩码值,而 `evidence` 附加一个
保留结构的、**默认掩码**的请求/响应摘要,用于定位
每个发现,同时保证 token、cookie 和 PII 绝不泄露(除了发现本身外,每个叶子节点都被替换为类型 token)。证据摘要是按需生成的,仅在明确选择加入时才会持久化到运行记录中。SARIF 输出已为 code-scanning 准备就绪:规则包含名称、描述、`helpUri`、CWE/OWASP
标签,以及 GitHub 的 `security-severity` 分数,并且每个结果都包含一个
`physicalLocation`。
- **Monitors**:手动运行实时检查,或让已启用的 monitors 在
应用运行时按其配置的周期执行。
- **性能测试**:生成并运行 k6 性能、负载和压力
测试,带有实时指标、SLO 评分、历史记录和可导出报告。
- **AI 辅助**:从 BDD、OpenAPI、PRD 或
类似 PDF 的文本生成分类的测试用例;根据现有断言审查单个 API 响应;并
按需扫描响应以检测敏感数据暴露(PII、secrets、内部
或调试字段)。
- **可配置的 AI provider**:每个 AI 功能(测试生成、响应
审查、敏感数据扫描和安全分流)都在您选择的 provider 上运行 —— OpenAI,或自定义 / 自管理(企业内部部署)
兼容 OpenAI 的 endpoint —— 凭证保存在本地机器上。
AI 功能是可选的:未配置 provider 时,测试生成
回退到内置的启发式引擎,应用的其余部分完全
正常工作。(存在一个无密钥的内置 Claude provider,但仅当
UI 在 claude.ai Artifacts 沙盒内运行时才起作用 —— 它在**桌面构建版本中不可用**;Settings 页面会显示其实时可用性。)
- **AI 隐私模式**:所有 AI 调用都通过一个默认脱敏的单一出口节点。三种模式 —— `full context`、`redacted`(默认)和
`local only` —— 控制离开机器的内容。`redacted` 在发送前会在本地
掩码 URL(剥离 host)、body(保留结构 —— 值变为类型 token,保留
key)、header 和标识符(email、token、UUID、IP、Luhn 校验有效的卡号、
SSN),并将 OpenAPI 规范简化为路径形状(无真实
host,无示例值)。`local only` 会阻止云 provider,仅允许
自管理 endpoint(回环 / 私有 / 明确认证)。预览
会在发送前显示确切的 prompt,而 CI / 组织级锁定(环境变量
`QA_ALLOW_EXTERNAL_AI`)可以强制关闭外部 AI。
- **文档和代码生成**:生成 API 文档、独立 HTML 导出和请求
代码片段(cURL、Python、JavaScript、HTTPie)。
- **实时测试**:测试 WebSocket 和 Server-Sent Events 流。
- **双语、可主题化的 UI**:完整的英语和繁体中文(繁體中文)
界面,可在 Settings 中切换,带有可主题化的暗色 UI(多种强调
色调和密度选项)。
## 架构

- **Frontend**:React 19 + Vite,**100% TypeScript**(严格模式)。Workspace、
request/send 和 monitor 状态存在于有类型的 React context provider
(`src/qa/state/`)中;共享的 domain 类型在 `src/qa/types.ts` 中。
- **Desktop shell**:Tauri 2
- **Backend commands**:Rust —— 请求执行(reqwest + 手动重定向
跟随、AWS SigV4,以及一个阻止向云元数据地址发送签名请求的 SSRF 守卫)、k6 进程
runner、临时文件辅助程序、本地
配置/数据持久化、OS-keychain 密钥存储(`keyring`),以及
由原生保存对话框提供的文本文件保存命令。Renderer 的命令
接口是刻意保持最小的(无 shell,无任意网络访问),并且
禁用 TLS 验证需要 renderer 明确确认并受
审计日志记录。
- **Storage**:一个单一的带版本控制的层(`src/qa/storage.ts`),具有读取时
迁移功能,通过 Rust 后端将关键 workspace 数据镜像到磁盘;
cookie jar 执行完整的 Public Suffix List(`src/qa/psl.ts`)。
- **Performance engine**:k6,实体化到 `src-tauri/resources/` 中
- **Tests + checks**:Vitest + Testing Library 和 Rust 单元测试,在 CI 中
与 `tsc --noEmit`、ESLint、`npm audit` 和 `cargo audit` 一起作为卡点控制,并且
工作流 action 被固定到具体的 commit SHA。
## 项目状态
正在积极维护。Frontend 是完全严格的 TypeScript;每次 push 都会运行
ESLint、`tsc --noEmit`、Vitest 套件、`npm audit` 和 Rust 单元测试,并且
发布 pipeline 除非这些测试通过,否则拒绝构建安装程序。请参阅
[CHANGELOG.md](CHANGELOG.md) 了解各版本的历史记录(近期工作:
OS-keychain 凭证存储、强化的 RBAC/BOLA/rate-limit 预言机、三个
新安全引擎 —— conformance、fuzzing、BFLA —— 更丰富的 SARIF,以及
React 19 升级)。
## 要求
- Node.js 20 或更高版本(CI 在 22 上运行)
- npm
- 用于 Tauri 命令和桌面构建的 Rust 工具链
- k6 由下文描述的设置脚本处理
## 开发
## Headless CI Runner
.tar.gz`
- `qa-touchstone-ci-windows-x64.zip`
- 匹配的 `.sha256` 校验和文件
从包含 npm/action 包装器的发行版中,使用以下任一方式安装:
```
# npm package 版本号不包含前缀 "v"。
npx qa-touchstone-ci@ --version
```
或在 GitHub Actions 中:
```
- uses: asdfghj1237890/qa-touchstone/setup-ci@vX.Y.Z
with:
version: vX.Y.Z
```
两个包装器都会下载匹配的 GitHub Release 资产,验证其 `.sha256`
文件,缓存或安装二进制文件,然后运行下文记录的相同的 `qa-touchstone-ci`
可执行文件。对于锁定的 CI 环境,仍支持手动下载产物。发布
workflow 仅在存储库变量 `PUBLISH_NPM` 为 `true` 且 `NPM_TOKEN`
可用时才发布 npm 启动器。
CI 接口是下文的 `qa-touchstone-ci` 命令集。它刻意
比桌面应用小:CI 作业根据文件和
环境变量运行确定性的 API、安全和
性能检查,无需 Tauri UI 或
OS keychain。
| CI 能力 | Command | 需要网络 | Runner 上需要 k6 | 典型 CI 输出 |
| ---------------------------- | -------------- | ------------- | ------------------ | ---------------------------------------------- |
| 原始冒烟探测 | `ping` | 是 | 否 | 人类可读状态行 |
| Postman/OpenAPI 转换 | `import` | 否 | 否 | `qa.json` 脚手架 |
| 单个 API 请求 + 断言 | `send` | 是 | 否 | JSON 结果 |
| Collection/API 冒烟测试套件 | `run` | 是 | 否 | JSON + 可选 JUnit XML |
| k6 支持的性能检查 | `perf` | 是 | **是** | JSON + 可选 k6 摘要导出 |
| 安全扫描/报告门控 | `scan` | 是 | 否 | JSON, HTML, JUnit XML, SARIF, baseline 更新 |
| BOLA 配置候选助手 | `bola-suggest` | 否 | 否 | 人类可读或 JSON 候选列表 |
Headless CLI **不**捆绑 k6。API 检查、collection 运行、BOLA
建议、导入和安全扫描仅需 `qa-touchstone-ci`
二进制文件即可工作;`perf` 命令要求在 CI
runner 上已安装 `k6`,或使用 `--k6-bin` 显式传入。
桌面独有功能不属于 headless 产物:无交互式 UI、
无后台 monitor 调度器、无 OS keychain 存储、无捆绑的桌面 k6
资源,且无 AI 辅助的生成流程。在 CI 中,请将 secrets 存储在
runner 的 secret 管理器中,并在配置中以环境变量支持的
值引用它们,例如 `{ "env": "API_TOKEN" }`。
从本存储库在本地构建它:
```
cargo build --manifest-path src-tauri/Cargo.toml -p qa-touchstone-ci --release
./src-tauri/target/release/qa-touchstone-ci --version
```
最小的 CI 配置如下所示:
```
{
"version": 1,
"environments": [{ "name": "staging", "variables": { "baseUrl": "https://api.example.com" } }],
"identities": [
{ "id": "anon", "auth": { "type": "none" } },
{ "id": "api", "auth": { "type": "bearer", "token": { "env": "API_TOKEN" } } }
],
"requests": [
{
"id": "health",
"method": "GET",
"url": "{{baseUrl}}/health",
"assertions": [{ "type": "status", "op": "eq", "value": 200 }]
},
{
"id": "admin-users",
"method": "GET",
"url": "{{baseUrl}}/admin/users",
"privileged": true
}
],
"collections": [{ "id": "smoke", "requests": ["health"] }],
"security": {
"matrix": {
"endpoints": ["admin-users"],
"expect": { "admin-users": { "anon": "deny", "api": "allow" } }
}
}
}
```
逐步调用它:
```
# 在需要时将 Postman / OpenAPI JSON 转换为 qa.json。
qa-touchstone-ci import --input postman.json --base-url https://api.example.com --out qa.generated.json
# 发送单个请求并输出 machine-readable JSON。
API_TOKEN="$API_TOKEN" qa-touchstone-ci send \
--config qa.json \
--request health \
--identity api \
--env staging \
--json
# 运行 collection 并为 CI 测试结果生成 JUnit。
API_TOKEN="$API_TOKEN" qa-touchstone-ci run \
--config qa.json \
--collection smoke \
--identity api \
--env staging \
--junit reports/qa-run.xml \
--json > reports/qa-run.json
# 运行 k6 性能检查。需要 PATH 中存在 k6,或者传入 --k6-bin /path/to/k6。
k6 version
API_TOKEN="$API_TOKEN" qa-touchstone-ci perf \
--config qa.json \
--request health \
--identity api \
--env staging \
--stage 30s:5 \
--stage 1m:10 \
--summary-out reports/k6-summary.json \
--json > reports/k6-run.json
# 运行 security suite 并输出 CI artifacts。
API_TOKEN="$API_TOKEN" qa-touchstone-ci scan \
--config qa.json \
--env staging \
--json \
--out reports/security.json \
--html reports/security.html \
--junit reports/security-junit.xml \
--sarif reports/security.sarif \
--fail-on high
```
退出代码是稳定的:`0` 通过,`1` 运行时/网络错误,`2` 无效输入,
`3` 达到或超过 `--fail-on` 的安全发现,以及
`4` 断言失败或来自 `perf` 的非零 k6 结果。要将当前扫描采用为 baseline,请使用
`--baseline .qa/security-baseline.json --update-baseline` 运行 `scan`;后续扫描将与
该文件进行比较,并根据新的发现进行门控。
`perf --script-out` 会写入生成的 k6 脚本以供审查/调试。该
脚本可能包含 auth header 或 token,因此除非您的
secrets 策略允许,否则不要将其作为 CI 产物上传。正常的临时脚本会在
k6 退出后被删除。
在其他存储库中的 GitHub Actions 作业示例:
```
name: qa-touchstone
on:
pull_request:
push:
branches: [main]
jobs:
api-security:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
env:
QA_TOUCHSTONE_VERSION: v0.22.1
API_TOKEN: ${{ secrets.API_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Install QA Touchstone CLI
uses: asdfghj1237890/qa-touchstone/setup-ci@vX.Y.Z
with:
version: ${{ env.QA_TOUCHSTONE_VERSION }}
- name: Run API smoke collection
run: |
mkdir -p reports
qa-touchstone-ci run \
--config qa-touchstone.json \
--collection smoke \
--identity api \
--env staging \
--junit reports/qa-run.xml \
--json > reports/qa-run.json
- name: Verify k6 is available
run: k6 version
- name: Run k6 performance check
run: |
qa-touchstone-ci perf \
--config qa-touchstone.json \
--request health \
--identity api \
--env staging \
--stage 30s:5 \
--summary-out reports/k6-summary.json \
--json > reports/k6-run.json
- name: Run security scan
id: scan
run: |
set +e
qa-touchstone-ci scan \
--config qa-touchstone.json \
--env staging \
--json \
--out reports/security.json \
--html reports/security.html \
--junit reports/security-junit.xml \
--sarif reports/security.sarif \
--fail-on high
code=$?
echo "exit_code=$code" >> "$GITHUB_OUTPUT"
exit 0
- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: reports/security.sarif
- name: Upload QA artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: qa-touchstone-reports
path: reports/
- name: Fail on QA Touchstone gate
if: steps.scan.outputs.exit_code != '0'
run: exit ${{ steps.scan.outputs.exit_code }}
```
如果您的组织实施严格的
供应链控制,请在生产工作流中固定 action SHA。
## k6 二进制文件
` 时,请将该发行版的校验和添加到
`scripts/setup-k6.mjs` 中的 `CHECKSUMS` 表;如果
缺少校验和不匹配,release 构建将失败并关闭。
## 本地数据和 Secrets
## 打包说明
## License
ISC
常用命令
安装依赖: ``` npm install ``` 运行前端 dev server: ``` npm run dev ``` 以开发模式运行 Tauri 桌面应用: ``` npm run tauri:dev ``` 运行测试: ``` npm test ``` 类型检查、lint 和格式化: ``` npm run typecheck npm run lint npm run format ``` 构建前端: ``` npm run build ``` 构建桌面应用: ``` npm run tauri:build ```在没有桌面 UI 的情况下运行 QA Touchstone
`qa-touchstone-ci` 是一个独立的、专为 CI 系统设计的 headless runner。它不 链接 Tauri 或 OS keychain 层,因此它可以在普通的 GitHub Actions、 GitLab、Jenkins 或容器作业中运行。打标签的发布版本会将这些 CLI 资产与 桌面安装程序一起发布: - `qa-touchstone-ci-linux-x64.tar.gz` - `qa-touchstone-ci-macos-k6 设置和发行版验证
Performance 页面通过 k6 运行真实的负载测试。该二进制文件未被 提交,因为它体积庞大且特定于平台。 设置脚本将其具体化到 `src-tauri/resources/`: - **Dev**:如果 k6 已存在,`npm run setup:k6` 是一个空操作,否则它 会从 PATH 复制 `k6` 或下载固定的发行版本。 - **Release**:`npm run setup:k6:release` 下载与 OS/arch 匹配的官方 产物,验证存储在 `scripts/setup-k6.mjs` 中的 SHA256 校验和,并 在捆绑前确认 `k6 version`。 手动命令: ``` npm run setup:k6 npm run setup:k6:release ``` 当提升 `K6_VERSION=存储文件和 secret 处理
运行时配置存储在本地。常见的生成文件包括: - `config.json`,用于应用程序设置 - `postman_collections_cache.json`,用于缓存的 collection 元数据 - `user_data.json` —— 关键 workspace 数据的磁盘镜像(安全发现 生命周期、baseline、性能历史、monitors)。应用通过一个单一的带版本控制的存储层(`src/qa/storage.ts`)读取/写入这些数据,该存储层能够在 webview 缓存被清除后依然幸存,在读取时迁移较旧的数据结构,并在遇到写入失败时抛出提示而不是将其吞没。Secrets(LLM API 密钥)被刻意排除在镜像之外。 手动配置的 AWS secret 访问密钥不会存储在 `config.json` 中:它们存在于 OS keychain(Windows Credential Manager / macOS Keychain / Linux Secret Service)中,由 credential-profile id 作为 key 进行索引。读取时仍会考虑遗留的内联 secret,以便旧配置能继续工作。 LLM 设置存储在浏览器 localStorage 中。AI 隐私模式是 默认脱敏的:prompt 在本地被掩码,并在发送到所选 provider 之前在预览中显示;`local only` 模式将 AI 限制为自管理的 endpoint,而 CI / 组织级锁定(`QA_ALLOW_EXTERNAL_AI`)可以 完全禁用外部 AI。不要提交凭证、生成的缓存文件、 本地 token 或特定于机器的路径。 安全运行记录仅持久化一个精简的、经过脱敏的快照 —— 请求/响应 body 绝不会被存储。更丰富的脱敏证据产物保存在 当前会话的内存中,仅当您明确选择加入时才会写入保存的运行(或固定的 baseline)。macOS、Windows 和 Gatekeeper 说明
macOS 构建会在 `src-tauri/target/release/bundle/dmg/` 下生成一个 `.dmg`。Windows 构建会同时生成一个 NSIS 安装程序(`-x64-setup.exe`)和一个无需安装的便携版 ZIP(`-x64-portable.zip`), 其中包含可执行文件及其捆绑的 `resources/k6.exe`。运行 `npm run package:portable` 可在本地将该便携版 ZIP 组装到 `dist/` 中(步骤与 release workflow 相同)。macOS k6 二进制文件被捆绑在应用中的 `Contents/Resources/resources/k6` 处,因此无需系统安装 k6 即可进行性能测试。 当前的 macOS 构建未使用 Apple Developer ID 进行签名或公证。 首次启动时,Gatekeeper 可能会阻止它。通过右键单击该 应用并选择 **打开** 来绕过它一次,或者通过清除隔离来绕过: ``` xattr -dr com.apple.quarantine "/Applications/QA Touchstone.app" ``` 为了更广泛的分发,请对构建进行签名和公证。标签:API测试, GraphQL, React, Syscalls, Tauri, 可视化界面, 安全测试, 性能测试, 攻击性安全, 自动化攻击