测试身份适配指南
更新时间:2026-09-30
本文档用于新的 subapp 适配 auth-center 的 Test Identity / 测试身份登录。
测试身份用于 agent、CLI、浏览器自动化和人工临时进入已发布 subapp 检查可用性。它不是普通用户账号,不进入 users 表,没有普通密码,也不会出现在普通登录页。
登录流程
- admin 在 auth-center dashboard 的
Test Access创建测试身份。 - 创建、轮换或打开详情页时,dashboard 可复制完整 secret。
- agent 在终端用
name + secret + target_subapp调用/api/test-auth/exchange。 - auth-center 返回一次性
login_url。 login_url默认 60 秒内必须打开并消费。- 消费成功后 auth-center 设置测试 session,并签发 JWT 跳转到目标 subapp。
- 测试 session 默认 30 分钟,可按测试身份配置调整。
注意:60 秒只限制一次性登录链接的消费时间,不限制测试时长。
Preview 浏览器入口
管理员可在 /dash -> Test Access 为测试身份开启 Preview。开启后,创建、轮换或详情页会提供:
https://accounts.aryuki.com/preview#name=<name>&secret=<secret>
人工 QA 可直接在浏览器打开该链接,点击 START 后从真实允许的应用列表进入目标 subapp。Preview 不替代 CLI:agent、CI 和脚本仍建议调用 /api/test-auth/exchange,取得一次性 login_url。
安全规则:
secret只放在 URL fragment,不放 query string 或 pathname;Preview 页面会立即从地址栏删除 fragment 后才请求服务端。- Preview 创建独立
test_preview_session,该 HttpOnly、Secure、SameSite=Strict Cookie 仅限/preview,不会覆盖普通sso_session。 - Preview 只列出身份
allowed_subapps中真实 active 的 D1apps;点击应用后会在新标签页使用既有 callback query JWT 流程进入 subapp,原卡片保留 2 秒启动反馈后恢复。subapp 无需新增 Preview 路由。 - 关闭 Preview、禁用或删除测试身份会立即拒绝 Preview session;轮换 secret 只让旧链接失效,已存在的 session 可维持到其配置的过期时间或被管理员撤销。
- 不要把 Preview 链接、secret、JWT 或 callback token 写入 Git、日志、公开聊天、前端代码或 issue。
Dashboard 管理入口
/dash→Test Access用于创建、禁用、启用、删除和编辑测试身份。- 测试身份详情页路径为
/dev/@name,页面展示已放开的 app、读写权限、API per session、secret 复制入口和真实活动记录。 /dash→Register中点击 register code 行会打开详情弹窗,可核对该 code 对应的 app 权限、cookie 有效期、使用状态和使用人。- 删除确认、敏感配置确认、测试身份编辑和 register code 详情弹窗均浮在 dashboard 顶栏之上;移动端打开后锁定底层页面滚动,仅滚动弹窗内容。
JWT 字段
测试身份 JWT 会继续使用 auth-center 的签名方式,旧 subapp 的 JWT 校验入口可以保持不变。
新增字段示例:
{
"sub": "test_identity_id",
"uuid": "test_identity_id",
"username": "agent-ocr-checker",
"role": "user",
"identity_type": "test",
"test_session": true,
"allowed_subapps": ["ocr", "paste"],
"data_scope": "public_read",
"data_scope_permissions": ["public_read", "private_read"],
"session_id": "test_session_id"
}
普通用户 JWT 不会包含 test_session=true。
旧 subapp 兼容策略
为了保证旧 subapp 可测试,未适配 data_scope 的旧 subapp 默认全可见。也就是说,只要旧 subapp 使用现有 /api/verify 校验 JWT,测试身份仍可进入。
新的 subapp 必须主动读取:
identity_typetest_sessionallowed_subappsdata_scopedata_scope_permissionssession_id
并按下面规则限制 API。
data_scope 定义
data_scope_permissions 是 auth-center 展开后的等效权限数组。公共权限默认包含同级私有权限:例如 public_read 同时包含 private_read,但不包含 private_write。新 subapp 可以优先读取 data_scope_permissions,旧 subapp 也可以继续按 data_scope 判断。
public_read:Public read
可以读取公共数据和私人数据,不能写入公共数据或私人数据。等效权限:public_read、private_read。
公共数据包括:
- subapp 全局配置
- 公开页面配置
- 公开模板
- 公开资源
- 公开列表
- 公开统计
- 公开状态
- 非用户私有的系统信息
public_write:Public write
可以读取和写入公共数据,并包含私人读写权限。等效权限:public_read、public_write、private_read、private_write。
在此模式下,公共数据相关敏感 API 可以放开,例如:
- 更新 subapp 全局配置
- 修改公开模板
- 触发公开数据同步
- 重建公开索引
- 刷新公开缓存
- 修改公开资源
此模式风险较高,只应短期使用,并记录操作日志。
private_read:Private read
可以读取公共数据和私人数据,不能写入任何数据。
私人数据包括:
- 真实用户内容
- 用户文件
- 用户邮件
- 用户 paste
- 用户 OCR 记录
- 用户 API key 列表
- 用户个人配置
- 用户 usage 明细
private_write:Private write
可以读取和写入公共数据、私人数据。这是最高风险模式,只应在必要生产测试中短期使用。
中间件伪代码
function requireSubappAccess(payload, appId) {
if (!payload) throw unauthorized();
if (payload.identity_type === "test" || payload.test_session === true) {
if (!payload.allowed_subapps?.includes(appId) && !payload.allowed_subapps?.includes("*")) {
throw forbidden();
}
return {
identityType: "test",
subjectId: payload.sub,
role: payload.role,
dataScope: payload.data_scope || "public_read",
dataScopePermissions: payload.data_scope_permissions || [payload.data_scope || "public_read"],
sessionId: payload.session_id
};
}
return {
identityType: "user",
subjectId: payload.sub || payload.uuid,
role: payload.role || "user"
};
}
function canReadPrivate(ctx) {
if (ctx.identityType !== "test") return true;
return (ctx.dataScopePermissions || []).includes("private_read");
}
function canWritePrivate(ctx) {
if (ctx.identityType !== "test") return true;
return (ctx.dataScopePermissions || []).includes("private_write");
}
function canWritePublic(ctx) {
if (ctx.identityType !== "test") return true;
return (ctx.dataScopePermissions || []).includes("public_write");
}
API 使用量上报
新的 subapp 可在测试身份请求结束后向 auth-center 上报用量:
POST /api/test-auth/usage
Authorization: Bearer <subapp_secret_key>
Content-Type: application/json
{
"test_identity_id": "test_identity_id",
"session_id": "test_session_id",
"subapp": "ocr",
"api_path": "/api/ocr/jobs",
"method": "POST",
"amount": 1,
"status_code": 200,
"metadata": {
"route_group": "ocr"
}
}
旧 subapp 如果仍使用 /api/quota/check 和 /api/quota/consume,auth-center 会对测试身份做兼容放行,并写入基础使用记录。
接入 checklist
- JWT 校验仍使用 auth-center 现有公用逻辑。
- 读取
identity_type=test判断测试身份。 - 使用
allowed_subapps判断当前 app 是否允许访问。 - 使用
data_scope和data_scope_permissions限制 public/private scope。 - 所有用户资产和业务数据仍使用
uuid/sub作为稳定归属键。 - 展示名称、username、email 只用于 UI,不作为数据归属键。
- 对
private_write做额外操作日志。 - 上报
/api/test-auth/usage以便 auth-center dashboard 查看测试活动。