docs(resource/dev-variables): record scoped plaintext exception and validation
Document V1-V6 evidence and keep V7 in progress until a real Codex tool-call and human UI pilot complete. Rules-Applied: R03,R05,R10,R13
This commit is contained in:
parent
b1c6eaebac
commit
fe71536f33
@ -6,7 +6,7 @@ description: >
|
||||
项目自身保留业务规则、测试、部署声明与交付决策。炼境本身亦被纳入其中,
|
||||
形成可自我进化的开发智能闭环。
|
||||
iteration: 1
|
||||
updated: 2026-09-23
|
||||
updated: 2026-09-26
|
||||
agent_button_carrier: tauri
|
||||
|
||||
|
||||
@ -498,7 +498,20 @@ modules:
|
||||
note: "R1–R11 的合成路径和真实 Codex CLI 客户端试点已验证;真实用户凭证迁移、正式版 UI 与生产链路未验证,未启动第二个日常 Tauri 实例。"
|
||||
position: [3000, 950]
|
||||
|
||||
- id: project-dev-variables
|
||||
name: 项目开发变量补给
|
||||
area: infra
|
||||
status: in_progress
|
||||
progress: 86
|
||||
updated: 2026-09-26
|
||||
note: "V1–V6 合成验收通过;V7 的完整真实 Codex 新工具调用与桌面 UI 人眼终验待做。仅非生产开发用途,运行时 env 注入后置。"
|
||||
position: [3250, 950]
|
||||
|
||||
edges:
|
||||
- from: project-resource-broker
|
||||
to: project-dev-variables
|
||||
type: dependency
|
||||
|
||||
# 前端依赖
|
||||
- from: workspace-mgmt
|
||||
to: project-mgmt
|
||||
|
||||
111
.blueprint/modules/project-dev-variables.md
Normal file
111
.blueprint/modules/project-dev-variables.md
Normal file
@ -0,0 +1,111 @@
|
||||
---
|
||||
id: project-dev-variables
|
||||
name: 项目开发变量补给
|
||||
status: in_progress
|
||||
progress: 86
|
||||
---
|
||||
|
||||
## 设计决策:人填写、Agent 按项目取值(2026-09-26)
|
||||
|
||||
### 背景与目标
|
||||
|
||||
开发 Agent 在子项目验收时会反复需要本机专属配置,例如非生产测试账号、沙箱 API Key 或测试端点。用户希望在炼境的项目 UI 填写一次,此后 Agent 能稳定发现并读取,避免把值留在子项目 `.env` 中。首轮只解决 Agent 获取开发变量;子项目进程的 `process.env` 自动注入、CI、生产凭证及部署能力不在范围内。
|
||||
|
||||
本模块是已完成的 `project-resource-broker` 的**明确例外**:R1–R11 保持 Gitea/API Key/webhook 常态不泄露、按操作代办;只有用户明确放入“Agent 可读开发变量”的值,才允许经专门工具返回明文。不能将旧的 `get_secret` 禁令改写成通用任意取密接口。
|
||||
|
||||
### 方案选择
|
||||
|
||||
| 方案 | 收益 | 代价与结论 |
|
||||
| --- | --- | --- |
|
||||
| 继续各项目 `.env` | 与现有脚本直接兼容 | 需要重复配置,仍有误提交与 Agent 访问不稳定的问题;保留为回退路径 |
|
||||
| 炼境保存后由无认证 scoped MCP 返回值 | 最省实现步骤 | scoped URL 仅隔离误操作,不认证调用者;任何能访问本机端口的进程可能取值,否决 |
|
||||
| **项目级开发变量 + 认证的 scoped MCP 单项读取** | 人填一次、Agent 跨会话复用、仓库无值 | Agent 会看到明文;需要验证 Codex 的认证头与本机凭据供应链,选定 |
|
||||
|
||||
### 信任与数据边界
|
||||
|
||||
- 仅支持登记在炼境的项目、明确标为开发用途且允许 Agent 读取的标量值。用户在对应项目 UI 填写、修改、撤销;Agent 可登记名称/用途和读取状态,但不能通过 MCP 设置值。非生产、低权限、可重置是使用规则,不能靠变量名称自动判断生产性质。
|
||||
- SQLite 只保存 `project_id`、规范化变量名、用途、状态所需元数据和随机 `credential_ref`;值保存在现有 Windows Credential Manager adapter。普通列表、readiness、日志、错误与文档不含值。
|
||||
- 唯一明文出口是 `read_project_dev_variable(project_id, name)`;必须同时验证真实项目绑定、scoped MCP 连接的项目 ID、客户端认证以及记录已由人配置。全局 `/mcp`、未认证请求和跨项目请求必须拒绝。明文进入 Agent 工具结果与会话,因此本方案不声称对 Agent 保密。
|
||||
- MCP 认证材料不得写入项目仓库、URL 或普通日志。Codex `http_headers_helper` 已用两次独立真实 CLI 会话验证:从 Windows Credential Manager 的随机合成项取得 bearer,真实 initialize 请求均带正确 `Authorization`;失败不得降级成无认证接口。正式打包路径尚未验证。
|
||||
- 同一 Windows 用户的恶意进程仍可能读取用户可访问的配置或受保护存储;认证只阻断无凭据的本机 HTTP 调用,不提供跨进程强隔离。其他客户端 adapter 未验证前不宣称兼容。
|
||||
|
||||
### 系统边界与预计文件
|
||||
|
||||
- 数据:`src-tauri/src/db.rs` 增加兼容 migration;新业务模块 `src-tauri/src/commands/dev_variables.rs` 注入数据库连接和 `CredentialStore`,实现登记、保存、读取、撤销的单点边界。
|
||||
- 认证:`src-tauri/src/mcp_server.rs` / `mcp_tools.rs` 在取值调用前验证项目绑定及 bearer;`src-tauri/src/credential_store.rs` 存储随机认证材料;`src-tauri/src/main.rs` 与 `mcp_inject.rs` 评估最小本机 header helper 和配置注入。旧 MCP 工具继续按原契约可用。
|
||||
- 人的投影:`src-tauri/src/lib.rs` 注册 Tauri commands,`src/lib/commands.ts` 同步类型与封装;在 `src/components/dashboard/ProjectCard.tsx` 就近入口接入项目级面板,值仅通过显式填写表单提交。
|
||||
- Agent 投影:`src-tauri/src/mcp_tools.rs` 暴露登记需求、查询非秘密状态、单项取值;不提供批量导出、任意命令、HTTP/SSH/SQL 或部署代理。
|
||||
- 契约同步:`docs/ai-context/project-context.yaml` 与 `docs/ai-context/agent-button-system.md` 说明例外与信任模型;保留旧设计历史,不将项目通用 API Key 改为 Agent 可读。
|
||||
|
||||
### 验证路径
|
||||
|
||||
- `[Codex CLI + 合成 MCP]` 用 `http_headers_helper` 提供合成 bearer 后初始化 → 服务端观测认证头;无 header/错误 header → 敏感工具拒绝;未通过则停止实现取值接口。
|
||||
- `[cargo test]` 用 in-memory SQLite + 模拟 CredentialStore 登记、保存、重启式重建后读取、撤销 → 状态正确,旧值不可再取,列表与错误不含合成值。
|
||||
- `[真实 scoped MCP]` Agent 在 `p1` 登记 `E2E_PASSWORD`,人通过同一本体保存合成值,Agent 单项读取 → 仅 `p1` 的已认证调用得到该值;`p2`、全局路由和无认证调用失败。
|
||||
- `human_verify:` 炼境项目 UI 的待填写、已配置、修改和撤销路径可用,默认不显示值;使用者判断是否比重复配置 `.env` 省事。
|
||||
|
||||
### 风险与阶段闸门
|
||||
|
||||
- **认证材料供应**:helper 与客户端跨会话读取已用随机合成项验证,正式打包版尚未验证;若后续失败必须回到设计,不把 token 写进受 Git 跟踪的 `.codex/config.toml`。
|
||||
- **明文工具结果**:用户选择开发便利,Agent 可能在会话中持有值;先只用合成数据验证,不读取或迁移真实账号。生产和高权限凭证仍用原有代办/CI/运行时机制。
|
||||
- **不替代运行时 `.env`**:Agent 读取值不自动设置子进程环境变量;需要时另立任务,不在本迭代暗加 `export_env`。
|
||||
- **依赖 PR #22**:从已提交的 R11 基线独立分支开发,先核验 PR #22 状态;不得把新改动混入已有 PR 或原 `master` 脏工作区。
|
||||
|
||||
## 任务拆解
|
||||
|
||||
### ✅ V1 — 认证头 helper 真实客户端可行性
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src-tauri/src/main.rs, src-tauri/src/lib.rs, src-tauri/src/credential_store.rs, src-tauri/src/mcp_inject.rs
|
||||
- depends: project-resource-broker
|
||||
- acceptance: "agent_verify: [Codex CLI + 合成 MCP] 通过本机 helper 从模拟受保护存储提供 bearer → initialize 请求含正确 Authorization,重启客户端后仍可读取;helper 缺失/失败时连接或取值 fail closed,项目配置文件不含 token。未通过即停止 V2–V7。"
|
||||
- evidence: `cargo test --locked codex_client_reads_windows_helper_header_across_sessions -- --ignored` 双会话通过;真实 exe helper 的读取/缺失 fail closed 测试通过;config 测试断言无 token。
|
||||
|
||||
### ✅ V2 — 敏感 MCP 调用认证与项目绑定
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src-tauri/src/mcp_server.rs, src-tauri/src/mcp_tools.rs, src-tauri/src/credential_store.rs
|
||||
- depends: V1
|
||||
- acceptance: "[cargo test] 合成 bearer 下 p1 的敏感 tools/call 认证门槛通过;无 header、错误 header、p2 和全局 /mcp 均在 dispatch 前拒绝,现有非敏感 scoped 工具保持可调用;cargo test 全绿。真实取值工具的 HTTP 端到端验收归 V6。"
|
||||
- evidence: `sensitive_read_requires_matching_project_bearer_on_both_transports` 通过;完整 `cargo test --locked` 通过。
|
||||
|
||||
### ✅ V3 — 开发变量元数据与受保护存储本体
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src-tauri/src/db.rs, src-tauri/src/commands/dev_variables.rs, src-tauri/src/credential_store.rs
|
||||
- depends: V2
|
||||
- acceptance: "[cargo test] in-memory DB + 模拟 CredentialStore 完成登记、保存、覆盖、读取、撤销;模拟写入或删除失败时旧值/引用可恢复,列表序列化和错误不含合成值;旧 schema 经 migrate 后可用。"
|
||||
- evidence: `dev_variables::tests` 与 `dev_variable_migration_adds_metadata_table_to_existing_database` 通过;数据库重开后仍可读取合成值,删除失败保留旧引用。
|
||||
|
||||
### ✅ V4 — Tauri 人用命令与前端契约
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src-tauri/src/commands/dev_variables.rs, src-tauri/src/lib.rs, src/lib/commands.ts
|
||||
- depends: V3
|
||||
- acceptance: "[Tauri command/cargo test] 以项目 ID 查询待填写/已配置、保存合成值、撤销 → 状态随真实存储变化;常态返回类型无 value,pnpm typecheck exit 0。"
|
||||
- evidence: `tauri_commands_use_same_state_and_never_return_value_in_list` 通过,`mise exec -- pnpm typecheck` exit 0。
|
||||
|
||||
### ✅ V5 — 项目 UI 填写与撤销投影
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src/components/dashboard/ProjectCard.tsx, src/components/dashboard/ProjectDevVariablesPanel.tsx, src/lib/commands.ts
|
||||
- depends: V4
|
||||
- acceptance: "agent_verify: [Tauri command/cargo test] 填写、覆盖、撤销同一本体状态正确,pnpm typecheck exit 0。human_verify: 在对应项目可见用途与待填写状态,填写/修改/撤销顺手,常态不显示值。"
|
||||
- human_verify: pending(未启动隔离分支的真实桌面 UI;交人终验时判断交互摩擦)
|
||||
- evidence: Tauri command 真实函数路径测试与 TypeScript 类型检查通过;填写值从 React Query mutation 缓存中移除。
|
||||
|
||||
### ✅ V6 — Agent 登记、状态和单项读取工具
|
||||
- status: done
|
||||
- complexity: M
|
||||
- files: src-tauri/src/mcp_tools.rs, src-tauri/src/commands/dev_variables.rs, src-tauri/src/mcp_server.rs
|
||||
- depends: V4, V5
|
||||
- acceptance: "[真实 scoped MCP] p1 Agent 登记 E2E_PASSWORD → UI 待填写;人保存合成值后已认证 Agent 单项读取成功;未认证、p2 和全局路由拒绝;tools/list 无批量导出或任意代理。"
|
||||
- evidence: `scoped_dev_variable_http_pilot_denies_missing_wrong_cross_and_global_auth` 真实本机 HTTP 测试通过;撤销后读取失败,工具清单无批量出口。
|
||||
|
||||
### 🔵 V7 — 契约、合成试点与改动边界验收
|
||||
- status: in_progress
|
||||
- complexity: M
|
||||
- files: docs/ai-context/project-context.yaml, docs/ai-context/agent-button-system.md, .blueprint/modules/project-dev-variables.md
|
||||
- depends: V6
|
||||
- acceptance: "agent_verify: [真实 Codex CLI + 合成数据] 跨会话登记→填写→读取→撤销后再读失败,项目目录无新 .env 或 token;[CLI] cargo test、pnpm typecheck、git diff --check 均 exit 0。human_verify: 不使用真实生产账号、不触发真实 PR/部署/数据库写入,确认日常开发摩擦是否下降。"
|
||||
- pending: 真实 Codex CLI 调新工具完成整条业务链、正式打包版、桌面 UI 人眼便利性终验;V1 的真实 Codex 认证初始化与 V6 的真实 scoped HTTP 业务链已分别验证,不把组合证据冒充本卡端到端完成。
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
version: 1.1.0
|
||||
updated: 2026-09-23
|
||||
updated: 2026-09-26
|
||||
usage: 炼境 agent 按钮体系的完整设计文档,供 Claude 理解体系全貌和设计意图;也是分发给子项目的方针来源
|
||||
---
|
||||
|
||||
@ -139,8 +139,12 @@ acceptance 是 agent 自验的唯一判断依据,必须是可执行断言:
|
||||
|
||||
这套 scope 是单用户本机的误操作隔离,不是多租户认证。威胁模型变化前,不向项目配置写持久 token。
|
||||
|
||||
项目开发变量是明确、有限的例外:Codex 项目配置只保存本机 helper 命令和项目 ID digest,随机 bearer 留在 Windows Credential Manager;helper 在连接时向 Codex 提供认证头。普通 scoped MCP 工具继续兼容无认证调用,但 `read_project_dev_variable` 在服务端验证该项目的 bearer,跨项目、全局 `/mcp`、无认证及错误认证均拒绝。同一 Windows 用户的恶意进程仍可能读取该用户可访问的凭证,本机制不声称提供同用户进程隔离;其他 Agent 客户端未验证前不承诺同等取值能力。
|
||||
|
||||
## 项目资源与凭证代办边界
|
||||
|
||||
项目开发变量由 Agent 在 scoped MCP 中登记名称和用途,人通过对应项目 UI 明确填写、修改或撤销。SQLite 只保存非秘密元数据与随机凭证引用,值留在 Windows Credential Manager;常态列表只报告待填写/已配置,不回传值。唯一明文出口是已认证的 `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 或部署已验证。
|
||||
|
||||
Gitea PR 继续使用既有 `create_pull_request` 有界操作;Windows 本机代办凭证由 Credential Manager 保护,SQLite 只存引用及非秘密元数据。旧值在显式操作时,先在数据库同目录以 SQLite `VACUUM INTO` 生成 `dev-manager.pre-credential-migration.db`,校验完整性和当前旧值确在备份中,再按写入、读取校验、事务切换引用并清除旧列的顺序迁移;备份不可用或失败则保留旧值并报告 `needs_repair`。此备份可能含历史明文,须按原数据库同等敏感级别保护,不能因当前列清空就宣称历史明文已消失。普通 Gitea/API Key DTO 不带原始值;人的 API Key 查看与复制仍通过本机 Tauri 的显式 reveal,MCP 不暴露该入口。Gitea Actions secrets、项目运行时密钥与服务器凭证仍留在各自原用途位置;炼境不提供 `get_secret` 或任意 SSH、SQL、HTTP、部署代理。同一 Windows 用户下的进程隔离不是本方案提供的安全保证。
|
||||
|
||||
@ -29,6 +29,7 @@ src-tauri/src/db.rs 数据库 schema + migration
|
||||
src-tauri/src/credential_store.rs Windows 本机凭证引用、校验与兼容迁移
|
||||
src-tauri/src/mcp_server.rs MCP Server(agent 调用炼境的入口)
|
||||
src-tauri/src/mcp_tools.rs MCP tool schema 与 dispatch
|
||||
src-tauri/src/commands/dev_variables.rs 项目开发变量本体(Agent 登记、人填写、受认证单项读取)
|
||||
src-tauri/src/commands/delivery_status.rs 项目交付信号聚合(Git / Gitea / 部署证据)
|
||||
src-tauri/resources/onboarding/ 接入包分发模板
|
||||
.blueprint/ 项目蓝图
|
||||
|
||||
@ -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 只作兼容迁移。路由变更需同步 Agent 按钮体系文档。"
|
||||
doc: "MCP 仅监听 127.0.0.1;新项目使用 /mcp/projects/<project_id> scoped route,连接 scope 拒绝跨项目参数和全局管理写工具。旧 /mcp 只作兼容迁移。read_project_dev_variable 是独立例外:仅 scoped 路由、匹配项目的本机 bearer 认证后单项读取;认证失败在 dispatch 前拒绝。路由变更需同步 Agent 按钮体系文档。"
|
||||
|
||||
- label: MCP 工具接口
|
||||
paths:
|
||||
@ -15,7 +15,8 @@ contracts:
|
||||
- "src-tauri/src/commands/toolchain.rs"
|
||||
- "src-tauri/src/commands/cicd.rs"
|
||||
- "src-tauri/src/commands/gitea.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/部署代理。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 或部署。"
|
||||
- "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 或部署。"
|
||||
|
||||
- label: 被管理项目身份上下文
|
||||
paths:
|
||||
@ -30,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 仅返回非秘密状态;旧 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 可显式提交或撤销值但无常态 reveal。旧 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