Эх сурвалжийг харах

feat(core): 新增 7.0 运行身份与凭据自举铁则 + docs/agent-identity-bootstrap.md

- agentId 高兼容解析链(FMODE_AGENT_ID>AGENT_ID>配置),绝不用 hostname
- sessionToken 配置兜底解析(env 可能缺失)
- 验证码登录兜底方案
- 事故复盘:交付物上报静默失效根因
liuyuyang 18 цаг өмнө
parent
commit
18d546494d
3 өөрчлөгдсөн 138 нэмэгдсэн , 3 устгасан
  1. 18 1
      SKILL.md
  2. 118 0
      docs/agent-identity-bootstrap.md
  3. 2 2
      package.json

+ 18 - 1
SKILL.md

@@ -1,7 +1,7 @@
 ---
 slug: fmode-skill-core-guide
 displayName: skill-core-guide
-version: 1.0.3
+version: 1.0.5
 summary: Fmode Harness 平台母技能标准指南 —— 平台端点真值表、ESM-first 四端标准、元数据规范、四渠道分发、六项自动质检、一键凭证供给、新技能脚手架。
 description: "Fmode 技能生态的宪法级规范文档。定义平台端点真值表(live/planned/deprecated 三态)、ESM-first 四端等价打包标准、元数据与标签规范、Gogs/GitHub/npm/skillhub 四渠道分发、六项自动质检(skip≠pass)、5 级诚实凭据链与新技能脚手架。读它不需要先读任何别的文档。The constitution of the Fmode skill ecosystem — platform endpoint truth table, ESM-first packaging standard, metadata spec, four-channel distribution, six-point quality gate."
 platform: HermesAgent
@@ -685,6 +685,23 @@ skill-core check . --allow-skip                 # 有 skip 也返回 0(慎用
 
 ## 七、一键凭证供给机制
 
+### 7.0 运行身份与凭据自举铁则(Agent Identity & Credential Bootstrapping)
+
+> **所有需要鉴权的平台调用(云函数 / API / OBS / 上报)在动手前,必须先高兼容解析两件事**:
+
+**① 我是谁(agentId)** —— 语义名 `agent-node` 等,**绝不回退到 docker hostname**(容器重启后 hash 会变)。
+解析链:`FMODE_AGENT_ID` > `AGENT_ID` > `~/.fmode/config.json` > `<cwd>/.fmode/config.json`。
+
+**② 我凭什么(sessionToken)** —— 只控制 ACL,不告知「是谁干活」。解析链:
+`FMODE_SESSION_TOKEN`(env)> `~/.fmode/config.json` > `~/.fmode/config/user.json` > `<cwd>/.fmode`。
+**坑**:HM 容器常不把 sessionToken 写入 env,技能必须主动读配置文件兜底。
+
+**全链枯竭兜底**:触发验证码登录重新初始化(端点未上线则打向导,**绝不伪造 token 假装成功**)。
+
+> 完整规范见 [`docs/agent-identity-bootstrap.md`](docs/agent-identity-bootstrap.md)。
+> 事故背景:交付物上报静默失效 —— 容器重建后 agentId 变 hostname、sessionToken 未进 env,双缺失导致
+> `404 agent not found` / `403 only owner or superadmin can report`。
+
 ### 7.1 诚实声明(先读这段)
 
 任务书描述的「手机号 + 验证码 → 自动创建 `~/.fmode/`」路径依赖端点:

+ 118 - 0
docs/agent-identity-bootstrap.md

@@ -0,0 +1,118 @@
+# 运行身份与凭据自举机制(Agent Identity & Credential Bootstrapping)
+
+> 本规范是 Fmode Harness 平台**所有技能**运行时自举的宪法。任何技能在调用需要鉴权的
+> 平台 API / 云函数 / 对象存储之前,**必须先解决两个问题**:
+>
+> 1. **我是谁** —— 本容器 / 本 Agent 的身份(agentId),确保上报/查询定位到正确的 Agent。
+> 2. **我凭什么** —— 本会话的凭据(sessionToken / apiToken),决定我能访问哪些资源(ACL)。
+>
+> 两者独立、都高兼容地解析,缺一不可。sessionToken 只控制 ACL,**不负责**告诉平台「是谁干活」。
+
+---
+
+## 一、Agent 身份(agentId)高兼容解析链
+
+**唯一真相**:`FmodeAgent` 表的语义名 agentId(如 `agent-node`、`agent-node-xinting`),
+**不是** Docker hostname(`6ec71e98949e` 这类随机 hash),也不是 PID。
+
+按以下顺序解析(第一个命中即停):
+
+| 级 | 来源 | 示例 | 说明 |
+|----|------|------|------|
+| 1 | 环境变量 `FMODE_AGENT_ID` | `FMODE_AGENT_ID=agent-node` | 最显式的强制指定 |
+| 2 | 环境变量 `AGENT_ID` | `AGENT_ID=agent-node` | 兼容 provision 脚本旧变量名 |
+| 3 | `.fmode/config.json` → `agentId` | `{"agentId":"agent-node"}` | 用户级配置持久化 |
+| 4 | `<cwd>/.fmode/config.json` → `agentId` | 同 | 项目级覆盖 |
+| 5 | hames 文件 `.fmode-harness-agent/agent.json` → `agentId` | 同上 | 容器初始化时由生命周期写入 |
+| 6 | 兜底:`hostname`(仅作显示,不可作业务键) | `6ec71e98949e` | 仅警告,不使用该值上报 |
+
+> ⚠️ **陷阱**:容器重启后 `hostname` 会变(Docker 随机生成短 hash)。
+> 上报云函数 `agentId` 参数若传了 hostname,会被判定「agent not found」。
+> 所以 agentId 必须来自**持久化配置**(env / .fmode),绝不能用 hostname。
+
+---
+
+## 二、sessionToken 高兼容解析链(ACL)
+
+sessionToken 只用于资源访问控制(ACL 判定、确认调用者身份),同样四级解析:
+
+| 级 | 来源 | 说明 |
+|----|------|------|
+| 1 | 环境变量 `FMODE_SESSION_TOKEN` | 最直接 |
+| 2 | `~/.fmode/config/user.json` → `sessionToken` | Hermes / FMODE Studio 保存位置 |
+| 3 | `~/.fmode/config.json` → `sessionToken` | 旧兼容位置 |
+| 4 | `<cwd>/.fmode/config.json` → `sessionToken` | 项目级 |
+
+> ⚠️ **陷阱**:`FMODE_SESSION_TOKEN` **不会自动导出到进程环境**——它存在
+> `~/.fmode/config/user.json` 里,但许多容器(尤其 Hermes)没把它写入 `.env` / 环境变量。
+> 技能必须**主动读取配置文件**兜底,不能只信环境变量。
+
+---
+
+## 三、apiToken(sk-)解析链
+
+(按 skill-core-guide 既有 §7 第 0-4 级,此处略,见主文档。)
+
+---
+
+## 四、全链枯竭时的兜底:验证码登录重新初始化
+
+当 agentId 与 sessionToken 都无法从 env / 配置找到时,**不能假装成功**,必须触发
+验证码登录自举(这是让技能能自主恢复的最后手段):
+
+```
+POST https://server.fmode.cn/api/fmode/verifycode
+  body: { "mobile": "<手机号>" }
+  → 返回验证码请求结果
+
+POST https://server.fmode.cn/api/fmode/verifycode/verify   # 或平台等价端点
+  body: { "mobile": "<手机号>", "code": "<6位验证码>" }
+  → 校验通过 → 返回并持久化 sessionToken
+
+将 sessionToken 写入 ~/.fmode/config/user.json
+将 agentId 写入 ~/.fmode/config.json(若云函数有注册接口则调之)
+```
+
+路径依赖端点是否上线;若端点未上线(404),则打印**清晰的初始化向导**并提供管理员邮箱,
+**绝不伪造**一个 token 假装成功(诚实原则,见 §9.1 伪自举事故)。
+
+---
+
+## 五、上报封闭示例(skill-deliverable 类)
+
+```
+谁:  agentId = resolveAgentId()        # 第 1-5 级,绝不取 hostname
+凭:  token   = resolveSessionToken()   # 第 1-4 级,env + 配置文件都试
+
+上报:POST https://server.fmode.cn/api/functions
+  body: {
+    token,                                 # ACL 用
+    id: "<deliverable 云函数 id>",
+    params: { action:"report", agentId, title, summary, project, artifacts, tags }
+  }
+```
+
+> **ACL 前置条件**:sessionToken 对应的用户必须是该 agentId 的 owner,或属于
+> `FMODE_AGENT_SUPERADMIN` 系统超管角色,否则云函数返回
+> `403 only owner or superadmin can report`。若报此错,属权限配置问题,不是本机制故障,
+> 需平台侧把该用户加入超管角色。
+
+---
+
+## 六、为什么必须同时高兼容解析「身份 + 凭据」
+
+| 场景 | 只解析身份 | 只解析凭据 |
+|------|-----------|-----------|
+| 容器重启(hostname 变) | ✅ 仍能定位 agent | ❌ 上报错目标/丢记录 |
+| 凭据存配置文件未导 env | ❌ 该容器无法鉴权 | ✅ 但可能报错目标 |
+| 新容器未初始化 | ❌ | ❌(触发验证码兜底) |
+
+两者都要高兼容,缺一个都会让「自动上报」静默失效——这正是交付物上报此前「没生效」的根因。
+
+---
+
+## 七、更新记录
+
+| 版本 | 日期 | 变更 |
+|------|------|------|
+| 1.0 | 2026-09-23 | 依交付物上报事故提炼;加入 agentId 解析链 + sessionToken 配置兜底 + 验证码兜底 |

+ 2 - 2
package.json

@@ -1,7 +1,7 @@
 {
   "name": "skill-core-guide",
-  "version": "1.0.4",
-  "description": "Fmode Harness \u5e73\u53f0\u6bcd\u6280\u80fd\u6807\u51c6\u6307\u5357\uff1a\u5e73\u53f0\u7aef\u70b9\u771f\u503c\u8868\u3001ESM-first \u56db\u7aef\u6807\u51c6\u3001\u56db\u6e20\u9053\u5206\u53d1\u3001\u516d\u9879\u81ea\u52a8\u8d28\u68c0\u3001\u4e00\u952e\u51ed\u8bc1\u4f9b\u7ed9\u3001\u65b0\u6280\u80fd\u811a\u624b\u67b6\u3002",
+  "version": "1.0.5",
+  "description": "Fmode Harness 平台母技能标准指南:平台端点真值表、ESM-first 四端标准、四渠道分发、六项自动质检、一键凭证供给、新技能脚手架。",
   "type": "module",
   "main": "./lib/index.mjs",
   "exports": {