feat(dev-variables): 项目开发变量与测试账户补给(V1–V11) #23
@ -6,7 +6,7 @@ description: >
|
||||
项目自身保留业务规则、测试、部署声明与交付决策。炼境本身亦被纳入其中,
|
||||
形成可自我进化的开发智能闭环。
|
||||
iteration: 1
|
||||
updated: 2026-09-26
|
||||
updated: 2026-09-28
|
||||
agent_button_carrier: tauri
|
||||
|
||||
|
||||
@ -502,9 +502,9 @@ modules:
|
||||
name: 项目开发变量补给
|
||||
area: infra
|
||||
status: in_progress
|
||||
progress: 86
|
||||
updated: 2026-09-26
|
||||
note: "V1–V6 合成验收通过;V7 真实 Codex 工具调用被客户端 approval policy=never 拒绝,待用户决定受控审批试点;桌面 UI 人眼终验待做。仅非生产开发用途,运行时 env 注入后置。"
|
||||
progress: 91
|
||||
updated: 2026-09-28
|
||||
note: "V1–V6、V8–V11 合成验收通过;V7 真实 Codex 工具调用仍被客户端 approval policy=never 拒绝。真实桌面 UI 和跨会话便利性待终验;仅非生产开发用途,运行时 env 注入后置。"
|
||||
position: [3250, 950]
|
||||
|
||||
edges:
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
id: project-dev-variables
|
||||
name: 项目开发变量补给
|
||||
status: in_progress
|
||||
progress: 86
|
||||
progress: 91
|
||||
---
|
||||
|
||||
## 设计决策:人填写、Agent 按项目取值(2026-09-26)
|
||||
@ -110,3 +110,77 @@ progress: 86
|
||||
- acceptance: "agent_verify: [真实 Codex CLI + 合成数据] 跨会话登记→填写→读取→撤销后再读失败,项目目录无新 .env 或 token;[CLI] cargo test、pnpm typecheck、git diff --check 均 exit 0。human_verify: 不使用真实生产账号、不触发真实 PR/部署/数据库写入,确认日常开发摩擦是否下降。"
|
||||
- blocked_reason: 真实 Codex CLI 三次隔离合成试点均在调用 `register_project_dev_variable` 时被客户端审批策略拒绝(`MCP tool call requires approval, but approval policy is never`),服务端未收到登记请求;未尝试绕过审批。需用户决定是否允许一次受控、可审批的真实客户端试点。
|
||||
- pending: 真实 Codex CLI 调新工具完成整条业务链、正式打包版、桌面 UI 人眼便利性终验;V1 的真实 Codex 认证初始化与 V6 的真实 scoped HTTP 业务链已分别验证,不把组合证据冒充本卡端到端完成。
|
||||
|
||||
## 设计决策:测试账户一次填写与跨会话复用(2026-09-28)
|
||||
|
||||
### 背景
|
||||
|
||||
单个开发变量虽已能登记、填写和读取,但测试登录通常同时需要账号与密码。让 Agent 分别登记两个变量、让用户分别填写,仍有重复操作和半配置状态;本迭代把常见测试账户做成一个有语义的需求卡,不扩展到生产凭证或任意表单生成器。
|
||||
|
||||
### 方案选择
|
||||
|
||||
| 方案 | 取舍 |
|
||||
| --- | --- |
|
||||
| 两个独立变量由 UI 猜测配对 | 无迁移,但没有可靠的同一需求身份,保存时可能只写成功一个字段;不选 |
|
||||
| **在现有开发变量记录上增加 `test_account` 类型,账号/密码作为一份受保护值原子保存** | 复用现有项目边界、Windows Credential Manager 与撤销路径,增加少量非秘密元数据;选定 |
|
||||
| 新建通用表单/凭证库 | 能支持任意字段,却扩大明文出口与维护面;本轮不做 |
|
||||
|
||||
### 系统边界与受影响文件
|
||||
|
||||
- `src-tauri/src/db.rs`:旧表兼容迁移,新增类型、目标系统和环境元数据;旧记录保持 `scalar`。
|
||||
- `src-tauri/src/commands/dev_variables.rs`:需求登记幂等;账号/密码按一份结构化值写入同一受保护引用,读写和撤销沿用项目校验;普通标量 API 不读取或覆盖测试账户记录。
|
||||
- `src-tauri/src/mcp_tools.rs`、`mcp_server.rs`:项目级登记、状态发现、专用读取;读取遵守现有 bearer 门槛,未认证、跨项目和全局路由拒绝,不增加通用 `get_secret`。
|
||||
- `src-tauri/src/lib.rs`、`src/lib/commands.ts`、`src/components/dashboard/ProjectDevVariablesPanel.tsx`:一张卡一次填写账号与密码;常态列表仅展示目标系统、环境、用途和配置状态,不回显值。
|
||||
- `docs/ai-context/project-context.yaml`、`docs/ai-context/agent-button-system.md`:同步外部契约与例外边界。
|
||||
|
||||
### 验证路径
|
||||
|
||||
- `[cargo test]` 旧 schema 迁移后旧标量仍可读;重复登记同一测试账户只得一张卡,语义冲突拒绝;一次保存后账号与密码同时可读,撤销后同时不可读,列表与错误不含合成值。
|
||||
- `[真实 scoped MCP]` 合成项目登记→Tauri 本体填写→已认证读取→跨项目、无认证及全局路由拒绝;工具目录没有批量导出或任意代理。
|
||||
- `human_verify:` 用户在项目面板一次填写账号与密码,后续会话无需重复填写;仅在人主动修改时出现输入框。
|
||||
|
||||
### 风险与闸门
|
||||
|
||||
- Agent 读取时会得到明文;本能力仅用于用户明确放入的非生产、低权限、可重置测试账户,不承诺对 Agent 保密。
|
||||
- 真实 Codex 非交互 `exec` 对写工具的客户端限制属于 V7 接入验证,不以错误标注只读或放宽全局策略绕过;业务层合成验收可以独立先做,真实客户端全链路未通过前不宣称日常可用。
|
||||
- 不自动把值注入子进程环境、不写 `.env`、不接管生产账号、SSH、SQL、HTTP 或部署。
|
||||
|
||||
### 拆解建议
|
||||
|
||||
按类型与受保护存储 → scoped Agent 投影 → 人用单表单投影 → 合成链路与文档四卡实施;既有 V7 仍单独保持 blocked,直到真实客户端验证通过。
|
||||
|
||||
## 任务拆解:测试账户预设
|
||||
|
||||
### ✅ V8 — 测试账户类型与原子受保护存储
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src-tauri/src/db.rs, src-tauri/src/commands/dev_variables.rs
|
||||
- depends: V6
|
||||
- acceptance: "agent_verify: [cargo test] 旧 schema migrate 后旧 scalar 正常;register_test_account(project,name,service,environment,purpose) 重复调用只保留一条且语义冲突拒绝;save_test_account 一次写入合成账号/密码,read_test_account 同时返回,revoke 后同时不可读;列表及错误不含值,写入失败不留下半配置。"
|
||||
- evidence: `cargo test --locked test_account` 4 项通过;旧表迁移幂等、登记幂等、类型隔离、一次写入/撤销和初次/覆盖失败恢复均由合成数据断言。
|
||||
|
||||
### ✅ V9 — Agent 测试账户需求与项目级读取
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src-tauri/src/mcp_tools.rs, src-tauri/src/mcp_server.rs
|
||||
- depends: V8
|
||||
- acceptance: "agent_verify: [真实 scoped MCP/cargo test] p1 登记一张合成测试账户需求、查询无秘密状态、已认证读取账号与密码;未认证、p2、全局 /mcp 拒绝读取,普通 scalar API 不能读取测试账户;tools/list 不含批量导出或任意代理。"
|
||||
- evidence: `sensitive_read_requires_matching_project_bearer_on_both_transports` 与扩展后的 `scoped_dev_variable_http_pilot_denies_missing_wrong_cross_and_global_auth` 通过;新明文工具先接入认证门槛再暴露,真实本机 HTTP 拒绝未认证/错误认证/p2/全局调用。
|
||||
|
||||
### ✅ V10 — 一张卡填写账号与密码
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src-tauri/src/lib.rs, src/lib/commands.ts, src/components/dashboard/ProjectDevVariablesPanel.tsx
|
||||
- depends: V8
|
||||
- acceptance: "agent_verify: [Tauri command/cargo test + pnpm typecheck] UI 一次提交调用 save_test_account,状态从待填写到已配置,修改与撤销共用本体;常态 DTO、React Query 缓存与日志不含账号或密码,typecheck exit 0。human_verify: 项目面板一张卡一次填写两个字段,默认不回显值。"
|
||||
- human_verify: pending(隔离分支真实桌面 UI 尚未由用户终验)
|
||||
- evidence: `tauri_test_account_command_uses_same_state_without_listing_values` 通过,`mise exec -- pnpm typecheck` exit 0;UI 通过独立调用提交两字段,列表 DTO 只有非秘密元数据和配置状态。
|
||||
|
||||
### ✅ V11 — 合成复用验收与契约同步
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src-tauri/src/mcp_server.rs, docs/ai-context/project-context.yaml, docs/ai-context/agent-button-system.md
|
||||
- depends: V9, V10
|
||||
- acceptance: "agent_verify: [真实 scoped MCP/cargo test] 合成项目登记→同一本体填写→再次查询已配置→读取→撤销后读取失败,并确认目录没有新增 .env 或明文配置;cargo test、pnpm typecheck、git diff --check exit 0。human_verify: 真实桌面 UI 与真实 Agent 客户端跨会话便利性另报未验证,不冒充 V7 完成。"
|
||||
- human_verify: pending(真实桌面 UI 和真实 Agent 客户端跨会话复用尚未终验;V7 保持 blocked)
|
||||
- evidence: 真实本机 scoped MCP HTTP 合成链路逐步断言登记、待填写、受保护存储填写、复查已配置、项目 bearer 读取、撤销后拒绝;数据库重开复用测试通过。`cargo test --locked` 227 passed/4 ignored,`mise exec -- pnpm typecheck` 与 `git diff --check` exit 0;未新增 `.env` 或明文配置文件。
|
||||
|
||||
@ -139,11 +139,11 @@ acceptance 是 agent 自验的唯一判断依据,必须是可执行断言:
|
||||
|
||||
这套 scope 是单用户本机的误操作隔离,不是多租户认证。威胁模型变化前,不向项目配置写持久 token。
|
||||
|
||||
项目开发变量是明确、有限的例外:Codex 项目配置只保存本机 helper 命令和项目 ID digest,随机 bearer 留在 Windows Credential Manager;helper 在连接时向 Codex 提供认证头。普通 scoped MCP 工具继续兼容无认证调用,但 `read_project_dev_variable` 在服务端验证该项目的 bearer,跨项目、全局 `/mcp`、无认证及错误认证均拒绝。同一 Windows 用户的恶意进程仍可能读取该用户可访问的凭证,本机制不声称提供同用户进程隔离;其他 Agent 客户端未验证前不承诺同等取值能力。
|
||||
项目开发变量是明确、有限的例外:Codex 项目配置只保存本机 helper 命令和项目 ID digest,随机 bearer 留在 Windows Credential Manager;helper 在连接时向 Codex 提供认证头。普通 scoped MCP 工具继续兼容无认证调用,但 `read_project_dev_variable` 与 `read_project_test_account` 在服务端验证该项目的 bearer,跨项目、全局 `/mcp`、无认证及错误认证均拒绝。同一 Windows 用户的恶意进程仍可能读取该用户可访问的凭证,本机制不声称提供同用户进程隔离;其他 Agent 客户端未验证前不承诺同等取值能力。
|
||||
|
||||
## 项目资源与凭证代办边界
|
||||
|
||||
项目开发变量由 Agent 在 scoped MCP 中登记名称和用途,人通过对应项目 UI 明确填写、修改或撤销。SQLite 只保存非秘密元数据与随机凭证引用,值留在 Windows Credential Manager;常态列表只报告待填写/已配置,不回传值。唯一明文出口是已认证的 `read_project_dev_variable` 单项调用,结果会进入 Agent 会话,因此只允许非生产、低权限、可重置的开发数据。它不替代子项目运行时 `.env` 注入,也不改变下述 Gitea/API Key 代办边界。
|
||||
项目开发变量由 Agent 在 scoped MCP 中登记名称和用途,人通过对应项目 UI 明确填写、修改或撤销。测试登录前 Agent 先查询非秘密需求状态:已有测试账户卡就复用;没有才以 `register_project_test_account` 登记稳定名称、目标系统、非生产环境和用途,不能通过 MCP 提交账号或密码。用户在同一张卡一次填写账号与密码;两字段作为一份结构化值原子写入 Windows Credential Manager,SQLite 仅保存非秘密元数据与随机引用。常态列表只报告待填写/已配置;`read_project_test_account` 经项目级认证后返回单张卡的账号与密码,旧的 `read_project_dev_variable` 仅返回标量,双方不能跨类型取值。结果会进入 Agent 会话,因此只允许非生产、低权限、可重置的开发数据;不替代子项目运行时 `.env` 注入,也不改变下述 Gitea/API Key 代办边界。
|
||||
|
||||
`get_project_resource_status(project_id)` 是同一项目绑定上的只读 MCP/Tauri 投影,只报告 Gitea PR 与 webhook 的 `configured`、`pending_migration`、`not_configured`、`unavailable` 或 `needs_repair` 及非秘密来源。旧 SQLite 凭证未迁移时只报告 `pending_migration`,不提前宣称可执行;scoped MCP 连接拒绝跨项目参数;状态不含原始凭证、凭证引用、仓库 URL 或连接串。`configured` 仅表示本机代办凭证就绪,不代表远端 Gitea、CI 或部署已验证。
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ contracts:
|
||||
- label: API 接口(Axum)
|
||||
paths:
|
||||
- "src-tauri/src/mcp_server.rs"
|
||||
doc: "MCP 仅监听 127.0.0.1;新项目使用 /mcp/projects/<project_id> scoped route,连接 scope 拒绝跨项目参数和全局管理写工具。旧 /mcp 只作兼容迁移。read_project_dev_variable 是独立例外:仅 scoped 路由、匹配项目的本机 bearer 认证后单项读取;认证失败在 dispatch 前拒绝。路由变更需同步 Agent 按钮体系文档。"
|
||||
doc: "MCP 仅监听 127.0.0.1;新项目使用 /mcp/projects/<project_id> scoped route,连接 scope 拒绝跨项目参数和全局管理写工具。旧 /mcp 只作兼容迁移。read_project_dev_variable 与 read_project_test_account 是两种有界开发值读取:仅 scoped 路由、匹配项目的本机 bearer 认证后单项读取;认证失败在 dispatch 前拒绝。路由变更需同步 Agent 按钮体系文档。"
|
||||
|
||||
- label: MCP 工具接口
|
||||
paths:
|
||||
@ -16,7 +16,7 @@ contracts:
|
||||
- "src-tauri/src/commands/cicd.rs"
|
||||
- "src-tauri/src/commands/gitea.rs"
|
||||
- "src-tauri/src/commands/dev_variables.rs"
|
||||
doc: "工具 schema、dispatch 与调用说明必须同步;get_project_resource_status 为项目 scoped 只读状态,仅返回 Gitea PR/webhook 的状态与来源,不返回凭证、引用、URL;旧凭证未迁移时返回 pending_migration,不提前宣称 configured。MCP 不提供 reveal_api_key、get_secret 或任意 HTTP/SSH/SQL/部署代理。唯一明文例外 read_project_dev_variable 仅返回人显式填写的项目级开发变量,须匹配 scoped 项目及本机认证;登记和列表不返回值,禁止批量导出。production delivery profile 由项目维护,炼境只读 Gitea 部署 context 与公开版本探针,双证据相符才能报告 deployed。外部来源不可用时返回显式降级状态,不得伪造成功。verify_onboarding 必须同时返回静态接入 checks 与 configured/reachable/handshake/tools_ready/reload_required 运行态证据,配置存在不得替代运行可用。CI workflow 使用 plan_cicd_workflow 只读预览,用户确认相同 digest 后方可 apply_cicd_workflow 写入;该接口不接收凭证值且不触发 CI 或部署。"
|
||||
doc: "工具 schema、dispatch 与调用说明必须同步;get_project_resource_status 为项目 scoped 只读状态,仅返回 Gitea PR/webhook 的状态与来源,不返回凭证、引用、URL;旧凭证未迁移时返回 pending_migration,不提前宣称 configured。MCP 不提供 reveal_api_key、get_secret 或任意 HTTP/SSH/SQL/部署代理。明文例外只限 read_project_dev_variable 的单项标量与 read_project_test_account 的单张非生产测试账户;均须匹配 scoped 项目及本机认证。register_project_test_account 只写非秘密需求元数据;列表不返回值,禁止批量导出。production delivery profile 由项目维护,炼境只读 Gitea 部署 context 与公开版本探针,双证据相符才能报告 deployed。外部来源不可用时返回显式降级状态,不得伪造成功。verify_onboarding 必须同时返回静态接入 checks 与 configured/reachable/handshake/tools_ready/reload_required 运行态证据,配置存在不得替代运行可用。CI workflow 使用 plan_cicd_workflow 只读预览,用户确认相同 digest 后方可 apply_cicd_workflow 写入;该接口不接收凭证值且不触发 CI 或部署。"
|
||||
|
||||
- label: 被管理项目身份上下文
|
||||
paths:
|
||||
@ -31,7 +31,7 @@ contracts:
|
||||
paths:
|
||||
- "src-tauri/src/commands/**/*.rs"
|
||||
- "src/lib/commands.ts"
|
||||
doc: "新增 command 时前后端必须同步。Gitea/API Key 普通 DTO 不含原始凭证;API Key 仅本机 UI 显式 reveal,get_project_resource_status 仅返回非秘密状态;项目开发变量列表 DTO 仅含名称、用途、configured 与时间,本机 UI 可显式提交或撤销值但无常态 reveal。旧 SQLite 明文列按 write→verify→事务切换引用并清除的顺序兼容迁移,失败需可恢复,不能降级明文。Agent readiness 必须保留 configured/reachable/handshake/tools_ready/reload_required 分层;Windows autostart 默认关闭,只允许正式安装版,debug/target 构建必须拒绝启用。"
|
||||
doc: "新增 command 时前后端必须同步。Gitea/API Key 普通 DTO 不含原始凭证;API Key 仅本机 UI 显式 reveal,get_project_resource_status 仅返回非秘密状态;项目开发需求列表 DTO 仅含名称、类型、目标系统、环境、用途、configured 与时间。本机 UI 对 test_account 一次提交账号/密码到同一受保护引用,允许修改或撤销但无常态 reveal;旧 scalar 保持兼容。旧 SQLite 明文列按 write→verify→事务切换引用并清除的顺序兼容迁移,失败需可恢复,不能降级明文。Agent readiness 必须保留 configured/reachable/handshake/tools_ready/reload_required 分层;Windows autostart 默认关闭,只允许正式安装版,debug/target 构建必须拒绝启用。"
|
||||
|
||||
architecture_docs:
|
||||
- "AGENTS.md"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user