oclaw/uds-auth/docs/skill-auth-standard.zh.md
oliver df97c5e042
Some checks are pending
ci / test (push) Waiting to run
ci / test-postgresql (push) Waiting to run
fix(uds-auth): emergency login workspaces, Desktop key prompts, persistent sessions
Emergency (fallback / sealed-box) admins lost the workspace sidebar and saw
"sign-in failed / add API key" on DSH Desktop because the remote.mux opens
anonymously at boot and every early call was rejected terminally.

- gateway: anonymous workspace/follow reaches dsh-acl's empty baseline;
  anonymous streams are parked until the carrier aborts instead of failing;
  anonymous workspace/initializeDefault answers "nothing created"
- request-auth: a dead UDS_SESSION cookie no longer shadows a valid WS ticket
  or bridge (sync + async variants used by all callers)
- dsh-acl: /api/* waits (bounded 15s) for the gateway ACL during Host startup
  instead of 403, so the Desktop welcome read no longer fails
- desktop-bootstrap: key/account projection is best-effort per reference
- client: emit connection/reset after login so boot-time caches (settings
  describe mirror -> Settings > Models) re-read under the real principal
- sessions: absolute lifetime fixed at 7 days (was min(ttl, 7d) = 30 min);
  bridge expiry slides with its session; MemoryStore persisted to
  sessions.json (bearer hash only, userData AES-256-GCM sealed)
- README: session lifetime/persistence and DSH compatibility notes

Also includes previously uncommitted uds-auth 0.3.x work in this tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:11:09 +08:00

131 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Skill 认证标准(uds-auth)
面向 DeepSeekHarness:现场安装 **uds-auth 插件**(内含 skill `uds-skill-auth`)后,第三方 / 自研 skill 按本标准取凭证或出站调用。
**转发给改造方时**:发整个 `uds-auth` 插件即可;公共 skill 在 [`skills/uds-skill-auth/`](../skills/uds-skill-auth/),说明见 [uds-skill-auth.zh.md](./uds-skill-auth.zh.md)。
## 现场形态
```text
安装 uds-auth 插件(内含 skills/uds-skill-auth)
→ 将 uds-skill-auth 加入 skills 路径(或复制到工作区 skills/)
→ 用户扫码登录
→ 安装/加载业务 skill
→ 可用
```
无需再配全局 `coclaw_token` / `AUTH_VALUE`。
**认证公共库随插件分发**:路径 `uds-auth/skills/uds-skill-auth/`。
## 双轨模型
| 轨道 | 用途 | 行为 |
|------|------|------|
| UI | Cookie + `sessionStore` + `/api/me` | **保持原样**;logout 仍清 cookie 并 `sessionStore.delete` |
| Skill | `skillCredentialCache`(`skill-credentials.json`) | 登录成功时写入/刷新;供 agent / cron |
配置项:
- `retainSkillCredentialsOnLogout`(默认 `true`):UI 退出时是否保留 skill token
- `skillCredentialTtlSeconds`(默认 `604800` = 7 天)
- `outboundAllowedHosts`:出站白名单(逗号分隔)
管理员删除用户会同时清掉该用户的 skill 凭证。
## Agent 环境
Shell / 任务 env(非密钥除非 Host 显式注入 capability):
- `DSH_SESSION_ID` — 当前 agent 会话
- `DSH_WEB_URL` — 可选,用于拼 Host 地址
- `UDS_TASK_CAPABILITY` — **推荐**:Host/`mintTaskCapability` 签发的短期令牌(scopes: `outbound` 和/或 `credentials`)
Host 在 `session/created` 时会 `stampSessionOwner(sessionId, empNo)`。Cron 可按 `ownerEmpNo` 解析并 mint capability;**不要**依赖浏览器 Cookie。
账号停用/删除会撤销该用户全部 task capability。
## 两种合法模式
### Mode Outbound(推荐新 skill)
```http
POST /uds-auth/outbound
X-DSH-Session-Id: <DSH_SESSION_ID>
X-UDS-Task-Capability: <UDS_TASK_CAPABILITY> # scope 须含 outbound
{ "url": "https://icenterapi.zte.com.cn/...", "method": "POST", "headers": {...}, "body": {...} }
```
- 仅 **loopback**
- Host 注入 `X-Emp-No` / `X-Auth-Value`
- 剥离客户端自带鉴权头
- host 必须在白名单内;URL 必须 **HTTPS**
- capability 仅 `credentials` scope 时 **不能** 调 outbound
Python(先把 `uds-skill-auth/scripts` 加入 `sys.path`):
```python
from uds_skill_auth import request
out = request("POST", url, headers={...}, body={...})
# out["statusCode"], out["json"], out["body"]
```
### Mode Creds(必须自管 HTTP 时)
默认 `allowRawAgentToken=false`。开启后:
```http
POST /uds-auth/agent-credentials
X-DSH-Session-Id: <DSH_SESSION_ID>
X-UDS-Task-Capability: <UDS_TASK_CAPABILITY> # scope 须含 credentials
```
返回 `{ empNo, token }`。可设进程内 `EMP_NO` / `AUTH_VALUE` 别名,**禁止**写进 SKILL.md 教模型 `printenv`。仅 `outbound` scope 的 capability **不能**取 raw token。
```python
from uds_skill_auth import resolve
# 优先用 request()/outbound;仅在 allowRawAgentToken=true 时使用 resolve
creds = resolve(apply_env_aliases=False)
```
Helpers 来源:插件内 skill `uds-auth/skills/uds-skill-auth/scripts/`(装到 skills 路径后,或环境变量 `UDS_AUTH_HELPERS`)。
## 改造现有 Skill 清单
1. 现场确保已从插件安装 `uds-skill-auth`(`uds-auth/skills/uds-skill-auth`)
2. 业务脚本定位 sibling:`.../skills/uds-skill-auth/scripts` → `import uds_skill_auth`
3. 替换原来的 `coclaw_*` / `EMP_NO`/`AUTH_VALUE` 手工读环境:改用 `resolve()` 或 `request()`
4. SKILL.md 只写「需已 UDS 登录,并已安装 uds-skill-auth」,不写 token 变量名
5. JSON stdout;日志脱敏
定位示例:
```python
from pathlib import Path
import sys
def load_uds_skill_auth():
here = Path(__file__).resolve().parent
candidate = here.parents[1] / "uds-skill-auth" / "scripts"
if not (candidate / "uds_skill_auth.py").is_file():
raise RuntimeError("请先安装 uds-skill-auth skill")
sys.path.insert(0, str(candidate))
import uds_skill_auth
return uds_skill_auth
```
## 禁止项
- 全局共享 token / 把 token 注入 `shellEnv`
- SKILL 教打印环境变量中的密钥
- 无白名单的开放代理
- 用 UI `sessionStore` 的 30min TTL 冒充 skill 长凭证
- 业务 skill 硬编码插件源码路径(应用 `uds-skill-auth` skill)
## 验收
- UI 登录/退出与改前一致
- 默认配置下 UI 退出后 skill/cron 仍可用
- `retainSkillCredentialsOnLogout=false` 时退出后取证失败
- 未安装 `uds-skill-auth` 时业务 skill 报错清晰
- 两会话不串号;未登录错误可理解且无 token 泄露