@h-ai/cli 0.1.0-alpha.53 → 0.1.0-alpha.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +18 -0
  2. package/dist/{chunk-U4PA632G.js → chunk-FVDXJYMO.js} +34 -67
  3. package/dist/chunk-FVDXJYMO.js.map +1 -0
  4. package/dist/cli-config-templates-WGN2I23J.js +5 -0
  5. package/dist/{cli-config-templates-GSXKLGU5.js.map → cli-config-templates-WGN2I23J.js.map} +1 -1
  6. package/dist/index.js +174 -105
  7. package/dist/index.js.map +1 -1
  8. package/dist/{src-QNEJJ3BV.js → src-6ZBWDBUB.js} +127 -87
  9. package/dist/{src-QNEJJ3BV.js.map → src-6ZBWDBUB.js.map} +1 -1
  10. package/package.json +13 -4
  11. package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +1 -0
  12. package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +1 -0
  13. package/templates/apps/api/package.json.hbs +1 -0
  14. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +1 -0
  15. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +1 -0
  16. package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +1 -0
  17. package/templates/apps/fullstack/package.json.hbs +1 -0
  18. package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +1 -0
  19. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +1 -0
  20. package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +1 -0
  21. package/templates/base/eslint.config.js.hbs +1 -0
  22. package/templates/base/package.json.hbs +3 -1
  23. package/templates/skills/AGENTS.md +8 -22
  24. package/templates/skills/CLAUDE.md +3 -16
  25. package/templates/skills/bridges/admin/AGENTS.md +3 -16
  26. package/templates/skills/bridges/admin/CLAUDE.md +3 -11
  27. package/templates/skills/bridges/admin/copilot-instructions.md +2 -39
  28. package/templates/skills/bridges/api/AGENTS.md +5 -18
  29. package/templates/skills/bridges/api/CLAUDE.md +3 -11
  30. package/templates/skills/bridges/api/copilot-instructions.md +3 -38
  31. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +24 -59
  32. package/templates/skills/bridges/fullstack/CLAUDE.md.hbs +1 -15
  33. package/templates/skills/bridges/fullstack/copilot-instructions.md.hbs +5 -45
  34. package/templates/skills/bridges/h5/AGENTS.md +4 -17
  35. package/templates/skills/bridges/h5/CLAUDE.md +3 -11
  36. package/templates/skills/bridges/h5/copilot-instructions.md +2 -37
  37. package/templates/skills/bridges/mobile-app/AGENTS.md +5 -18
  38. package/templates/skills/bridges/mobile-app/CLAUDE.md +3 -11
  39. package/templates/skills/bridges/mobile-app/copilot-instructions.md +2 -38
  40. package/templates/skills/bridges/website/AGENTS.md +4 -17
  41. package/templates/skills/bridges/website/CLAUDE.md +3 -11
  42. package/templates/skills/bridges/website/copilot-instructions.md +2 -37
  43. package/templates/skills/copilot-instructions.md +2 -36
  44. package/templates/skills/hai-ai/SKILL.md +35 -389
  45. package/templates/skills/hai-ai/guide.md +383 -0
  46. package/templates/skills/hai-ai/reference.md +6 -2
  47. package/templates/skills/hai-api-client/SKILL.md +6 -6
  48. package/templates/skills/hai-api-contract/SKILL.md +10 -25
  49. package/templates/skills/hai-app-create/SKILL.md +29 -388
  50. package/templates/skills/hai-app-create/reference.md +350 -0
  51. package/templates/skills/hai-app-review/SKILL.md +15 -23
  52. package/templates/skills/hai-app-tests/SKILL.md +29 -494
  53. package/templates/skills/hai-app-tests/reference.md +442 -0
  54. package/templates/skills/hai-audit/SKILL.md +6 -6
  55. package/templates/skills/hai-build/SKILL.md +19 -330
  56. package/templates/skills/hai-build/reference.md +326 -0
  57. package/templates/skills/hai-cache/SKILL.md +28 -31
  58. package/templates/skills/hai-capacitor/SKILL.md +19 -364
  59. package/templates/skills/hai-capacitor/reference.md +352 -0
  60. package/templates/skills/hai-ci/SKILL.md +17 -20
  61. package/templates/skills/hai-core/SKILL.md +25 -564
  62. package/templates/skills/hai-core/reference.md +533 -0
  63. package/templates/skills/hai-crypto/SKILL.md +8 -20
  64. package/templates/skills/hai-datapipe/SKILL.md +9 -23
  65. package/templates/skills/hai-deploy/SKILL.md +18 -24
  66. package/templates/skills/hai-framework-sync/SKILL.md +8 -20
  67. package/templates/skills/hai-iam/SKILL.md +27 -365
  68. package/templates/skills/hai-iam/reference.md +343 -0
  69. package/templates/skills/hai-kit/SKILL.md +6 -6
  70. package/templates/skills/hai-payment/SKILL.md +6 -26
  71. package/templates/skills/hai-pr-review/SKILL.md +6 -22
  72. package/templates/skills/hai-reach/SKILL.md +19 -317
  73. package/templates/skills/hai-reach/reference.md +303 -0
  74. package/templates/skills/hai-reldb/SKILL.md +19 -472
  75. package/templates/skills/hai-reldb/reference.md +452 -0
  76. package/templates/skills/hai-scheduler/SKILL.md +18 -6
  77. package/templates/skills/hai-serv/SKILL.md +27 -759
  78. package/templates/skills/hai-serv/reference.md +736 -0
  79. package/templates/skills/hai-storage/SKILL.md +7 -25
  80. package/templates/skills/hai-ui/SKILL.md +29 -621
  81. package/templates/skills/hai-ui/reference.md +598 -0
  82. package/templates/skills/hai-vecdb/SKILL.md +18 -303
  83. package/templates/skills/hai-vecdb/reference.md +291 -0
  84. package/dist/chunk-U4PA632G.js.map +0 -1
  85. package/dist/cli-config-templates-GSXKLGU5.js +0 -5
@@ -0,0 +1,343 @@
1
+ # hai-iam — 详细用法
2
+
3
+ 从 [SKILL.md](SKILL.md) 选择主题后读取对应小节。代码片段展示 API 用法;省略的业务变量、schema、依赖与 return 上下文需由应用补齐。
4
+
5
+ 角色成员数使用 `getRoleUserCounts(roleIds)`,一次聚合返回 `HaiResult<Map<string, number>>`;成功时无关联为 0,失败必须展示错误,不能伪造零值。
6
+
7
+ 角色资料和权限必须通过 `createRole({ ..., permissionIds })` / `updateRole(id, { ..., permissionIds })` 一次事务保存,禁止在应用层并行增删权限模拟替换。空数组清空、未传保持、未知权限失败、重复 ID 去重;并发以最后提交的完整集合为准。自管事务提交后同步会话,外部事务由调用方提交后同步。
8
+
9
+ 管理界面自动创建角色时使用 `role_${core.id.generate()}` 生成 code,显示名称独立保存;不要通过移除中文、表情或折叠大小写生成标识。重命名不重建 code。
10
+
11
+ > `@h-ai/iam` 是统一的身份与访问管理模块,支持多种认证策略(密码/OTP/LDAP/API Key)、Bearer Token 管理和 RBAC 授权。依赖 `@h-ai/reldb`(持久化)、`@h-ai/cache`(Token + 权限缓存)、`@h-ai/crypto`(密码哈希)、`@h-ai/audit`(审计日志)。
12
+
13
+ ## 运行环境
14
+
15
+ > ⚠️ **服务端模块(Node.js only)。** 浏览器端通过 `@h-ai/api-client` 的 typed client 调用 IAM API,例如 `apiClient.iam.auth.login()`。HTTP 契约统一来自 `@h-ai/api-contract`。
16
+
17
+ ## 依赖
18
+
19
+ | 模块 | 用途 | 是否必需 | 初始化要求 |
20
+ | --- | --- | --- | --- |
21
+ | `@h-ai/reldb` | 数据库(用户/角色/权限持久化) | **必需** | 需在 `iam.init()` 前初始化 |
22
+ | `@h-ai/cache` | 缓存(会话/OTP/重置令牌/权限缓存) | **必需** | 需在 `iam.init()` 前初始化 |
23
+ | `@h-ai/crypto` | 密码哈希 | 内部使用 | 自动初始化 |
24
+ | `@h-ai/audit` | 审计日志(RBAC 关键操作记录) | 内部使用 | 已初始化时自动写入 |
25
+
26
+ ## 适用场景
27
+
28
+ - 用户注册与登录(密码/OTP/LDAP/API Key)
29
+ - Bearer Token 认证与管理(TokenPair: accessToken + refreshToken)
30
+ - Token 刷新(rotation 策略)与吊销
31
+ - RBAC 角色/权限的创建、分配与检查
32
+ - API Key 管理(创建、吊销、验证)
33
+ - 密码重置流程
34
+ - 与 kit 集成的认证守卫
35
+ - 通过 `@h-ai/api-contract` 暴露 IAM HTTP contract
36
+
37
+ ## 使用步骤
38
+
39
+ ### 1. 配置
40
+
41
+ ```yaml
42
+ # config/_iam.yml
43
+ password:
44
+ minLength: 8
45
+ requireUppercase: true
46
+ requireNumber: true
47
+ session:
48
+ maxAge: 86400
49
+ refreshTokenMaxAge: 604800 # 7 天
50
+ sliding: true
51
+ singleDevice: false
52
+ login:
53
+ password: true
54
+ otp: false
55
+ register:
56
+ enabled: true
57
+ security:
58
+ maxLoginAttempts: 5
59
+ lockoutDuration: 900
60
+ rbac:
61
+ defaultRole: user
62
+ superAdminRole: super_admin
63
+ ```
64
+
65
+ 约定环境变量优先于 YAML,例如 `HAI_IAM_PASSWORD_MINLENGTH`、
66
+ `HAI_IAM_SESSION_MAXAGE`、`HAI_IAM_SECURITY_MAXLOGINATTEMPTS`。
67
+
68
+ ### 2. 初始化
69
+
70
+ ```typescript
71
+ import { cache } from '@h-ai/cache'
72
+ import { reldb } from '@h-ai/reldb'
73
+ import { iam } from '@h-ai/iam'
74
+
75
+ // 必须先初始化 reldb 和 cache
76
+ await reldb.init(core.config.get('db'))
77
+ await cache.init(core.config.get('cache'))
78
+
79
+ // IAM 自动使用已初始化的 reldb 和 cache 单例
80
+ await iam.init({
81
+ ...core.config.get('iam'),
82
+ seedDefaultData: true,
83
+ })
84
+ ```
85
+
86
+ `iam.config` 返回的是脱敏后的配置快照;LDAP `url` / `bindPassword` 等敏感值会自动隐藏。
87
+
88
+ 初始化时自动创建数据库表(5 张):`hai_iam_users`、`hai_iam_roles`、`hai_iam_permissions`、`hai_iam_role_permissions`、`hai_iam_user_roles`。
89
+
90
+ Token 和 OTP 存储在 cache 中(不落库)。refreshToken 使用独立的 cache key 存储。
91
+
92
+ ## 核心 API
93
+
94
+ ### 认证 — `iam.auth`
95
+
96
+ | 方法 | 签名 | 说明 |
97
+ | ------------------ | ----------------------------------------------------------- | ---------------------------------- |
98
+ | `login` | `({ identifier, password }) => Promise<HaiResult<AuthResult>>` | 密码登录(用户名/邮箱/手机号) |
99
+ | `loginWithOtp` | `({ identifier, code }) => Promise<HaiResult<AuthResult>>` | OTP 验证码登录 |
100
+ | `loginWithLdap` | `({ username, password }) => Promise<HaiResult<AuthResult>>` | LDAP 登录 |
101
+ | `loginWithApiKey` | `({ key }) => Promise<HaiResult<AuthResult>>` | API Key 登录 |
102
+ | `sendOtp` | `(identifier) => Promise<HaiResult<{ expiresAt }>>` | 发送 OTP 验证码 |
103
+ | `verifyToken` | `(token) => Promise<HaiResult<Session>>` | 验证令牌(推荐入口,委托 session) |
104
+ | `logout` | `(token) => Promise<HaiResult<void>>` | 登出 |
105
+ | `registerAndLogin` | `(options: RegisterOptions) => Promise<HaiResult<AuthResult>>` | 注册并登录(一站式) |
106
+
107
+ **AuthResult**(已改造为 TokenPair):
108
+
109
+ ```typescript
110
+ interface AuthResult {
111
+ user: User
112
+ tokens: TokenPair
113
+ roles: string[]
114
+ permissions: string[]
115
+ agreements?: AgreementDisplay
116
+ }
117
+
118
+ interface TokenPair {
119
+ accessToken: string
120
+ refreshToken: string
121
+ expiresIn: number
122
+ tokenType: 'Bearer'
123
+ }
124
+ ```
125
+
126
+ ### 会话管理 — `iam.session`
127
+
128
+ | 方法 | 签名 | 说明 |
129
+ | ------------------- | -------------------------------------------------------------------- | --------------------------------------- |
130
+ | `create` | `({ userId, username, roles, source? }) => Promise<HaiResult<Session>>` | 创建会话(返回含 TokenPair 的 session) |
131
+ | `get` | `(token) => Promise<HaiResult<Session \| null>>` | 获取会话(滑动续期自动延长) |
132
+ | `verifyToken` | `(token) => Promise<HaiResult<Session>>` | 验证令牌 |
133
+ | `update` | `(token, data) => Promise<HaiResult<void>>` | 更新会话字段(浅合并 data) |
134
+ | `delete` | `(token) => Promise<HaiResult<void>>` | 删除会话 |
135
+ | `deleteByUserId` | `(userId) => Promise<HaiResult<number>>` | 删除用户所有会话(返回删除数量) |
136
+ | `refresh` | `(refreshToken) => Promise<HaiResult<TokenPair>>` | 刷新 Token(rotation:旧 Token 失效) |
137
+ | `revokeRefresh` | `(refreshToken) => Promise<HaiResult<void>>` | 吊销 refreshToken |
138
+ | `patchUserSessions` | `(userId, updates: SessionFieldUpdates) => Promise<HaiResult<void>>` | 批量更新用户所有会话的 roles/permissions |
139
+
140
+ **Token 刷新(rotation 策略)**:
141
+
142
+ - `refresh()` 会删除旧的 accessToken + refreshToken
143
+ - 创建全新的 session,返回新的 TokenPair
144
+ - 旧 refreshToken 立即失效,防止重放攻击
145
+
146
+ ### 一次性票据 — `iam.ticket`
147
+
148
+ 短期、一次性能力票据,用于无法携带 Bearer Token 的通道(如 WebSocket URL)。密码学安全随机、TTL、原子单次消费、用途绑定。
149
+
150
+ | 方法 | 签名 | 说明 |
151
+ | ---------- | -------------------------------------------------------------------------------------- | ------------------------------------- |
152
+ | `issue` | `({ subjectId, purpose, grant?, ttlMs? }) => Promise<HaiResult<{ ticket, expiresAt }>>` | 签发(默认 30s) |
153
+ | `consume` | `(ticket, { purpose? }?) => Promise<HaiResult<{ subjectId, purpose, grant }>>` | 原子消费(单次有效,用途不符拒绝) |
154
+
155
+ ```ts
156
+ const issued = await iam.ticket.issue({ subjectId, purpose: 'ai-audio', grant: { operation: 'transcribe' } })
157
+ const consumed = await iam.ticket.consume(ticket, { purpose: 'ai-audio' }) // 并发消费仅一个成功
158
+ ```
159
+
160
+ 错误码:`TICKET_INVALID`(hai:iam:110) / `TICKET_EXPIRED`(hai:iam:111) / `TICKET_ISSUE_FAILED`(hai:iam:112)。
161
+
162
+ ### 用户管理 — `iam.user`
163
+
164
+ | 方法 | 签名 | 说明 |
165
+ | -------------------------- | ----------------------------------------------------------------------- | ------------------------------------ |
166
+ | `register` | `(input) => Promise<HaiResult<RegisterResult>>` | 用户注册 |
167
+ | `getUser` | `(id, options?) => Promise<HaiResult<User \| null>>` | 获取用户(可选 include: ['roles']) |
168
+ | `getCurrentUser` | `(token) => Promise<HaiResult<User>>` | 通过令牌获取当前用户 |
169
+ | `updateCurrentUser` | `(token, data: UpdateCurrentUserInput) => Promise<HaiResult<User>>` | 当前用户修改个人资料(白名单字段) |
170
+ | `listUsers` | `(options?: ListUsersOptions) => Promise<HaiResult<PaginatedResult<User>>>` | 用户列表(分页 + 搜索 + 过滤 + 白名单排序) |
171
+ | `updateUser` | `(id, data) => Promise<HaiResult<User>>` | 更新用户信息 |
172
+ | `deleteUser` | `(id) => Promise<HaiResult<void>>` | 删除用户(自动清除会话) |
173
+ | `changePassword` | `(id, old, new) => Promise<HaiResult<void>>` | 修改密码(自动清除会话) |
174
+ | `changeCurrentUserPassword`| `(token, old, new) => Promise<HaiResult<void>>` | 当前用户修改密码(通过令牌识别) |
175
+ | `requestPasswordReset` | `(email) => Promise<HaiResult<void>>` | 请求密码重置(防枚举) |
176
+ | `confirmPasswordReset` | `(token, newPassword) => Promise<HaiResult<void>>` | 确认密码重置(自动清除会话) |
177
+ | `adminResetPassword` | `(userId, newPassword) => Promise<HaiResult<void>>` | 管理员直接重置密码 |
178
+ | `validatePassword` | `(password) => HaiResult<void>` | 验证密码强度(**同步方法**) |
179
+
180
+ ### RBAC 授权 — `iam.authz`
181
+
182
+ | 方法 | 签名 | 说明 |
183
+ | -------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------- |
184
+ | `checkPermission` | `(userId, permission) => Promise<HaiResult<boolean>>` | 检查权限(超管自动通过,支持通配符) |
185
+ | `getUserPermissions` | `(userId) => Promise<HaiResult<Permission[]>>` | 获取用户权限列表(通过角色聚合去重) |
186
+ | `getUserRoles` | `(userId) => Promise<HaiResult<Role[]>>` | 获取用户角色列表 |
187
+ | `getUserRolesForMany` | `(userIds) => Promise<HaiResult<Map<string, Role[]>>>` | 批量获取多用户角色(避免 N+1) |
188
+ | `assignRole` | `(userId, roleId, tx?) => Promise<HaiResult<void>>` | 分配角色给用户 |
189
+ | `removeRole` | `(userId, roleId, tx?) => Promise<HaiResult<void>>` | 移除用户角色 |
190
+ | `syncRoles` | `(userId, roleIds, tx?) => Promise<HaiResult<void>>` | 同步用户角色(替换为目标列表) |
191
+ | `createRole` | `({ code, name, description? }, tx?) => Promise<HaiResult<Role>>` | 创建角色 |
192
+ | `getRole` | `(roleId) => Promise<HaiResult<Role \| null>>` | 获取角色 |
193
+ | `getRoleByCode` | `(code) => Promise<HaiResult<Role \| null>>` | 根据代码获取角色 |
194
+ | `getAllRoles` | `(options?) => Promise<HaiResult<PaginatedResult<Role>>>` | 获取所有角色(分页) |
195
+ | `updateRole` | `(roleId, data, tx?) => Promise<HaiResult<Role>>` | 更新角色 |
196
+ | `deleteRole` | `(roleId, tx?) => Promise<HaiResult<void>>` | 删除角色(级联清理关联 + 会话同步) |
197
+ | `createPermission` | `({ code, name, type?, resource?, action? }, tx?) => Promise<HaiResult<Permission>>`| 创建权限 |
198
+ | `getPermission` | `(permissionId) => Promise<HaiResult<Permission \| null>>` | 获取权限 |
199
+ | `getPermissionByCode` | `(code) => Promise<HaiResult<Permission \| null>>` | 根据代码获取权限 |
200
+ | `getAllPermissions` | `(options?: PermissionQueryOptions) => Promise<HaiResult<PaginatedResult<Permission>>>` | 获取所有权限(分页 + 类型/关键字筛选) |
201
+ | `deletePermission` | `(permissionId, tx?) => Promise<HaiResult<void>>` | 删除权限(级联清理关联 + 会话同步) |
202
+ | `assignPermissionToRole` | `(roleId, permId, tx?) => Promise<HaiResult<void>>` | 分配权限给角色 |
203
+ | `removePermissionFromRole` | `(roleId, permId, tx?) => Promise<HaiResult<void>>` | 移除角色权限 |
204
+ | `getRolePermissions` | `(roleId) => Promise<HaiResult<Permission[]>>` | 获取角色的权限列表 |
205
+ | `getRolePermissionsForMany`| `(roleIds) => Promise<HaiResult<Map<string, Permission[]>>>` | 批量获取多角色权限(避免 N+1) |
206
+
207
+ **通配符规则**:`admin:*` 匹配 `admin:read`、`admin:write` 等。超管角色自动拥有所有权限。
208
+
209
+ ### API Key 管理 — `iam.apiKey`
210
+
211
+ | 方法 | 签名 | 说明 |
212
+ | -------------- | ----------------------------------------------------------------------- | -------------------------------------- |
213
+ | `createApiKey` | `(userId, options: CreateApiKeyOptions) => Promise<HaiResult<CreateApiKeyResult>>` | 创建 API Key(明文密钥仅返回一次) |
214
+ | `listApiKeys` | `(userId, options?) => Promise<HaiResult<PaginatedResult<ApiKey>>>` | 分页列出用户的 API Key |
215
+ | `getApiKey` | `(keyId) => Promise<HaiResult<ApiKey \| null>>` | 获取 API Key 详情 |
216
+ | `revokeApiKey` | `(keyId) => Promise<HaiResult<void>>` | 吊销/删除 API Key |
217
+ | `verifyApiKey` | `(rawKey) => Promise<HaiResult<ApiKey>>` | 验证 API Key 并返回实体(含用户 ID) |
218
+
219
+ > 需在 `login.apikey: true` 时才会初始化此子模块,否则访问返回 `NOT_INITIALIZED` 错误。
220
+
221
+ ## HTTP API 契约
222
+
223
+ IAM HTTP API 统一由 `@h-ai/api-contract` 的 `apiContract.iam` 定义,由 `@h-ai/serv/features/iam` 绑定到本模块。
224
+
225
+ ```typescript
226
+ import { apiClient } from '@h-ai/api-client'
227
+
228
+ const result = await apiClient.iam.auth.login({ identifier: username, password })
229
+ ```
230
+
231
+ ## 错误码 — `HaiIamError`
232
+
233
+ | 错误码 | code | 说明 |
234
+ |--------|------|------|
235
+ | `HaiIamError.AUTH_FAILED` | `hai:iam:001` | 认证失败 |
236
+ | `HaiIamError.INVALID_CREDENTIALS` | `hai:iam:002` | 凭证无效 |
237
+ | `HaiIamError.USER_NOT_FOUND` | `hai:iam:003` | 用户不存在 |
238
+ | `HaiIamError.USER_DISABLED` | `hai:iam:004` | 用户已禁用 |
239
+ | `HaiIamError.USER_LOCKED` | `hai:iam:005` | 用户已锁定 |
240
+ | `HaiIamError.USER_ALREADY_EXISTS` | `hai:iam:006` | 用户已存在 |
241
+ | `HaiIamError.PASSWORD_EXPIRED` | `hai:iam:007` | 密码已过期 |
242
+ | `HaiIamError.PASSWORD_POLICY_VIOLATION` | `hai:iam:008` | 密码不符合策略 |
243
+ | `HaiIamError.OTP_INVALID` | `hai:iam:009` | 验证码无效 |
244
+ | `HaiIamError.NOT_INITIALIZED` | `hai:iam:010` | 未初始化 |
245
+ | `HaiIamError.OTP_RESEND_TOO_FAST` | `hai:iam:011` | 发送过于频繁 |
246
+ | `HaiIamError.LOGIN_DISABLED` | `hai:iam:012` | 登录方式已禁用 |
247
+ | `HaiIamError.REGISTER_DISABLED` | `hai:iam:013` | 注册已禁用 |
248
+ | `HaiIamError.STRATEGY_NOT_SUPPORTED` | `hai:iam:014` | 认证策略不支持 |
249
+ | `HaiIamError.APIKEY_INVALID` | `hai:iam:015` | API Key 无效 |
250
+ | `HaiIamError.APIKEY_EXPIRED` | `hai:iam:016` | API Key 已过期 |
251
+ | `HaiIamError.APIKEY_DISABLED` | `hai:iam:017` | API Key 已禁用 |
252
+ | `HaiIamError.APIKEY_NOT_FOUND` | `hai:iam:018` | API Key 不存在 |
253
+ | `HaiIamError.RESET_TOKEN_INVALID` | `hai:iam:019` | 重置令牌无效 |
254
+ | `HaiIamError.RESET_TOKEN_EXPIRED` | `hai:iam:020` | 重置令牌已过期 |
255
+ | `HaiIamError.RESET_TOKEN_MAX_ATTEMPTS` | `hai:iam:021` | 重置验证次数超限 |
256
+ | `HaiIamError.OTP_EXPIRED` | `hai:iam:022` | 验证码已过期 |
257
+ | `HaiIamError.SESSION_NOT_FOUND` | `hai:iam:101` | 会话不存在 |
258
+ | `HaiIamError.SESSION_EXPIRED` | `hai:iam:102` | 会话已过期 |
259
+ | `HaiIamError.SESSION_INVALID` | `hai:iam:103` | 会话无效 |
260
+ | `HaiIamError.SESSION_CREATE_FAILED` | `hai:iam:104` | 会话创建失败 |
261
+ | `HaiIamError.TOKEN_EXPIRED` | `hai:iam:105` | 令牌已过期 |
262
+ | `HaiIamError.TOKEN_INVALID` | `hai:iam:106` | 令牌无效 |
263
+ | `HaiIamError.TOKEN_REFRESH_FAILED` | `hai:iam:107` | 令牌刷新失败 |
264
+ | `HaiIamError.PERMISSION_DENIED` | `hai:iam:201` | 权限不足 |
265
+ | `HaiIamError.ROLE_NOT_FOUND` | `hai:iam:202` | 角色不存在 |
266
+ | `HaiIamError.PERMISSION_NOT_FOUND` | `hai:iam:203` | 权限不存在 |
267
+ | `HaiIamError.ROLE_ALREADY_EXISTS` | `hai:iam:204` | 角色已存在 |
268
+ | `HaiIamError.PERMISSION_ALREADY_EXISTS` | `hai:iam:205` | 权限已存在 |
269
+ | `HaiIamError.LDAP_CONNECTION_FAILED` | `hai:iam:301` | LDAP 连接失败 |
270
+ | `HaiIamError.LDAP_BIND_FAILED` | `hai:iam:302` | LDAP 绑定失败 |
271
+ | `HaiIamError.LDAP_SEARCH_FAILED` | `hai:iam:303` | LDAP 搜索失败 |
272
+ | `HaiIamError.REPOSITORY_ERROR` | `hai:iam:401` | 存储层操作错误 |
273
+ | `HaiIamError.NOT_FOUND` | `hai:iam:402` | 资源不存在 |
274
+ | `HaiIamError.CONFLICT` | `hai:iam:403` | 资源冲突 |
275
+ | `HaiIamError.FORBIDDEN` | `hai:iam:501` | 禁止访问 |
276
+ | `HaiIamError.INVALID_ARGUMENT` | `hai:iam:502` | 参数无效 |
277
+ | `HaiIamError.CONFIG_ERROR` | `hai:iam:901` | 配置错误 |
278
+ | `HaiIamError.INTERNAL_ERROR` | `hai:iam:999` | 内部错误 |
279
+
280
+ ## 常见模式
281
+
282
+ ### 与 kit 集成(hooks.server.ts)
283
+
284
+ ```typescript
285
+ import { iam } from '@h-ai/iam'
286
+ import { kit } from '@h-ai/kit'
287
+
288
+ // 应用启动时已成功初始化 IAM。
289
+ export const handle = kit.createHandle({
290
+ auth: {
291
+ verifyToken: async (token) => {
292
+ const result = await iam.auth.verifyToken(token)
293
+ return result.success ? result.data : null
294
+ },
295
+ operations: () => iam.auth,
296
+ loginUrl: '/auth/login',
297
+ protectedPaths: ['/admin/*', '/api/*'],
298
+ publicPaths: ['/api/auth/*', '/api/public/*'],
299
+ },
300
+ })
301
+ ```
302
+
303
+ ### 客户端认证流程
304
+
305
+ ```typescript
306
+ // 登录 → 保存 Token
307
+ const login = await apiClient.iam.auth.login({ identifier: username, password })
308
+ if (login.success) {
309
+ await apiClient.auth.setTokens(login.data.tokens)
310
+ }
311
+
312
+ // 获取当前用户
313
+ const me = await apiClient.iam.auth.currentUser()
314
+ if (me.success) {
315
+ // 返回 User + 服务端当前会话的 roles/permissions。
316
+ // 身份资料与访问范围可在状态层拆开,但不要持久化权限快照。
317
+ const { roles, permissions, ...user } = me.data
318
+ }
319
+
320
+ // Token 过期时,api-client 自动调用 refreshPath 刷新
321
+ // 刷新失败时,清除 Token 并跳转登录页
322
+
323
+ // 登出
324
+ await apiClient.iam.auth.logout({})
325
+ await apiClient.auth.clear()
326
+ ```
327
+
328
+ ### 自动会话失效
329
+
330
+ 以下操作自动清除受影响用户的所有活跃会话:
331
+
332
+ - `deleteUser` / `updateUser({ enabled: false })` / `changePassword` / `confirmPasswordReset`
333
+ - `assignRole` / `removeRole` / `deleteRole` 会同步更新活跃会话中的角色列表
334
+
335
+ ## 相关 Skills
336
+
337
+ - `hai-build`:模块初始化顺序(db → cache → iam)
338
+ - `hai-kit`:SvelteKit 集成(Bearer Token + 契约处理)
339
+ - `hai-api-client`:客户端契约调用
340
+ - `hai-reldb`:底层数据存储
341
+ - `hai-cache`:Token 与权限缓存
342
+ - `hai-crypto`:密码哈希(内部依赖)
343
+ - `hai-ui`:IAM 场景组件(LoginForm/RegisterForm 等)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hai-kit
3
- description: 使用 @h-ai/kit 构建 SvelteKit 请求管道、认证守卫、统一响应、Zod 校验、浏览器端 apiFetch、A2A 与双构建适配;当需求涉及 hooks.server.ts、权限守卫、CORS、限流、同源 transport 或 SvelteKit API endpoint 时使用。
3
+ description: "使用 @h-ai/kit 集成 SvelteKit hooks、守卫、校验、响应及同源客户端传输。"
4
4
  ---
5
5
 
6
6
  # hai-kit
@@ -9,11 +9,11 @@ description: 使用 @h-ai/kit 构建 SvelteKit 请求管道、认证守卫、统
9
9
 
10
10
  | 项目 | 契约 |
11
11
  | --- | --- |
12
- | 能力 | 使用 @h-ai/kit 构建 SvelteKit 请求管道、认证守卫、统一响应、Zod 校验、浏览器端 apiFetch、A2A 与双构建适配;当需求涉及 hooks.server.ts、权限守卫、CORS、限流、同源 transport 或 SvelteKit API endpoint 时使用。 |
13
- | 适用场景 | 当任务与 `hai-kit` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
- | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
- | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
- | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
12
+ | 能力 | 使用 @h-ai/kit 集成 SvelteKit hooks、守卫、校验、响应及同源客户端传输 |
13
+ | 适用场景 | SvelteKit hooks、load 和同源端点集成 |
14
+ | 输入 | SvelteKit handle/RequestEvent、schema、guard、transport |
15
+ | 输出 | handle、Response、校验值和客户端请求结果 |
16
+ | 限制 | 无 init/close;保留 SvelteKit 控制流异常。跨端共享 HTTP contract 用 api-contract + serv,勿复制到 kit。 |
17
17
 
18
18
  > `@h-ai/kit` 只负责 SvelteKit 集成:`handle` hook、guard、response、validate、client、auth、crud、A2A。公共跨端 HTTP API 契约统一使用 `@h-ai/api-contract` + `@h-ai/serv`,不要在 kit 中定义业务 API contract。
19
19
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hai-payment
3
- description: 使用 @h-ai/payment 接入微信支付、支付宝、Stripe 统一支付;支持创建订单、回调验签、订单查询与退款;当需求涉及支付接入、订单创建、支付回调、退款或客户端调起支付时使用。
3
+ description: "使用 @h-ai/payment 创建支付订单、验证回调、查单和退款,客户端调起支付。"
4
4
  ---
5
5
 
6
6
  # hai-payment
@@ -9,30 +9,24 @@ description: 使用 @h-ai/payment 接入微信支付、支付宝、Stripe 统一
9
9
 
10
10
  | 项目 | 契约 |
11
11
  | --- | --- |
12
- | 能力 | 使用 @h-ai/payment 接入微信支付、支付宝、Stripe 统一支付;支持创建订单、回调验签、订单查询与退款;当需求涉及支付接入、订单创建、支付回调、退款或客户端调起支付时使用。 |
13
- | 适用场景 | 当任务与 `hai-payment` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
- | 输入 | 模块配置、类型化业务参数、依赖初始化状态和目标运行环境 |
15
- | 输出 | 符合模块公共 API 的实现或示例;业务结果使用 HaiResult,并同步必要测试与文档 |
16
- | 限制 | 遵守 init → use → close 生命周期与运行环境边界;不绕过类型、授权、输入校验或敏感信息保护 |
12
+ | 能力 | 使用 @h-ai/payment 创建支付订单、验证回调、查单和退款,客户端调起支付 |
13
+ | 适用场景 | 服务端支付集成及客户端调起流程 |
14
+ | 输入 | Provider 配置、订单/退款参数、原始回调内容 |
15
+ | 输出 | 服务端 HaiResult;客户端 invokePayment 按 client 契约使用 |
16
+ | 限制 | 服务端保存凭据并验签;客户端完成不代表付款成功,以可信回调/查单为准。订单履约与重试需幂等。 |
17
17
 
18
18
  > `@h-ai/payment` 是 hai-framework 的统一支付模块,通过 Provider 模式支持微信支付、支付宝、Stripe。服务端处理订单和回调,客户端调起支付。
19
19
 
20
- ---
21
-
22
20
  ## 运行环境
23
21
 
24
22
  > **服务端 + 浏览器分工模块。** `payment.createOrder` / `payment.handleNotify` / `payment.refund` 等操作在 Node.js 端执行。浏览器端使用 `invokePayment()`(从 `@h-ai/payment/client` 导入)调起支付。
25
23
 
26
- ---
27
-
28
24
  ## 依赖
29
25
 
30
26
  | 模块 | 用途 | 是否必需 | 初始化要求 |
31
27
  | --- | --- | --- | --- |
32
28
  | `@h-ai/audit` | 审计日志(支付操作自动审计) | 可选 | 已初始化时自动写入审计日志 |
33
29
 
34
- ---
35
-
36
30
  ## 适用场景
37
31
 
38
32
  - 接入微信支付(JSAPI / H5 / Native / App)
@@ -42,8 +36,6 @@ description: 使用 @h-ai/payment 接入微信支付、支付宝、Stripe 统一
42
36
  - 订单查询与退款
43
37
  - 客户端调起支付(Web / H5 / App)
44
38
 
45
- ---
46
-
47
39
  ## 使用步骤
48
40
 
49
41
  ### 1. 配置
@@ -165,8 +157,6 @@ import { invokePayment } from '@h-ai/payment/client'
165
157
  const payResult = await invokePayment(orderResult.data)
166
158
  ```
167
159
 
168
- ---
169
-
170
160
  ## 核心 API(服务端)
171
161
 
172
162
  | API | 用途 | 返回值 |
@@ -187,8 +177,6 @@ const payResult = await invokePayment(orderResult.data)
187
177
  | ------------------------ | -------- | ----------------------------- |
188
178
  | `invokePayment(options)` | 调起支付 | `HaiResult<InvokePaymentResult>` |
189
179
 
190
- ---
191
-
192
180
  ## 错误码 — `HaiPaymentError`
193
181
 
194
182
  | 错误码 | code | 说明 |
@@ -207,8 +195,6 @@ const payResult = await invokePayment(orderResult.data)
207
195
  | `HaiPaymentError.INVOKE_APP_FAILED` | `hai:payment:061` | App 端调起支付失败 |
208
196
  | `HaiPaymentError.CONFIG_ERROR` | `hai:payment:070` | 配置无效 |
209
197
 
210
- ---
211
-
212
198
  ## Provider 模式
213
199
 
214
200
  内置 Provider:
@@ -230,8 +216,6 @@ import { apiContract } from '@h-ai/api-contract'
230
216
  // apiContract.payment.notifications.wechat — POST /payment/notifications/wechat
231
217
  ```
232
218
 
233
- ---
234
-
235
219
  ## 常见模式
236
220
 
237
221
  ### 服务端路由(SvelteKit)
@@ -272,16 +256,12 @@ export const POST = kit.handler(async ({ request, locals }) => {
272
256
  7. 客户端:轮询或回调查询订单状态
273
257
  ```
274
258
 
275
- ---
276
-
277
259
  ## 审计日志
278
260
 
279
261
  关键支付操作(创建订单、回调、退款、关闭订单)成功后自动写入审计日志(依赖 `@h-ai/audit`),无需额外配置。`queryOrder` 为只读操作,不写审计日志。
280
262
 
281
263
  内置 Provider 的 HTTP 请求默认带 15 秒超时;Stripe 可通过 `webhookToleranceSeconds` 调整 webhook 时间戳容忍窗口。
282
264
 
283
- ---
284
-
285
265
  ## 相关 Skills
286
266
 
287
267
  - `hai-kit`:服务端 API 路由与契约处理
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hai-pr-review
3
- description: 审查 Pull Request 的交付质量、scope、风险、验证方式、AI-assisted 说明与合并准备度;当需求涉及 PR review、AI Review 策略、PR 模板、CODEOWNERS 或合并门禁时使用。
3
+ description: "审查 PR 范围、风险、验证证据和合并准备度。"
4
4
  ---
5
5
 
6
6
  # hai-pr-review — PR 审查与 AI Review 规范
@@ -9,16 +9,14 @@ description: 审查 Pull Request 的交付质量、scope、风险、验证方式
9
9
 
10
10
  | 项目 | 契约 |
11
11
  | --- | --- |
12
- | 能力 | 审查 Pull Request 的交付质量、scope、风险、验证方式、AI-assisted 说明与合并准备度;当需求涉及 PR review、AI Review 策略、PR 模板、CODEOWNERS 或合并门禁时使用。 |
13
- | 适用场景 | 当任务与 `hai-pr-review` 的能力描述匹配,并且需要遵循本 Skill 的流程和边界时 |
14
- | 输入 | 用户指定的审查范围、代码/差异、仓库规范与可复现证据 |
15
- | 输出 | 按优先级排列的问题、影响、定位和修正建议;仅在用户要求时实施修改 |
16
- | 限制 | 不把风格偏好当缺陷,不猜测未读取的实现,不在审查请求中擅自发布或改动外部状态 |
12
+ | 能力 | 审查 PR 范围、风险、验证证据和合并准备度 |
13
+ | 适用场景 | 用户要求 PR 审查或合并准备度评估 |
14
+ | 输入 | PR diff、相关实现、CI 结果及仓库合并规则 |
15
+ | 输出 | 可定位的问题、验证缺口与审查结论 |
16
+ | 限制 | AI 建议不等于 CI 通过;不代替用户批准合并,不因审查擅自发布评论。 |
17
17
 
18
18
  > PR 是团队协作和 AI 辅助开发的交付边界。AI 可以帮助发现问题,但不能替代确定性 CI 和人类最终责任。
19
19
 
20
- ---
21
-
22
20
  ## 适用场景
23
21
 
24
22
  - 审查 AI-generated / AI-assisted PR
@@ -31,8 +29,6 @@ description: 审查 Pull Request 的交付质量、scope、风险、验证方式
31
29
 
32
30
  不负责:代码级质量审查(用 `hai-app-review` / 模块审查技能)、测试用例设计(用 `hai-app-tests`)、workflow 触发/权限/secret 细节(用 `hai-ci`)。
33
31
 
34
- ---
35
-
36
32
  ## 审查分层
37
33
 
38
34
  ### 第 1 层:确定性检查(必须)
@@ -54,8 +50,6 @@ description: 审查 Pull Request 的交付质量、scope、风险、验证方式
54
50
  - 只有在 CI 稳定、误报可控、团队明确同意后,才考虑将特定静态规则设为 blocking。
55
51
  - AI 的建议必须由人类判断,不得自动 merge。
56
52
 
57
- ---
58
-
59
53
  ## AI-assisted PR 要求
60
54
 
61
55
  PR 描述必须说明:
@@ -65,8 +59,6 @@ PR 描述必须说明:
65
59
  - 人类如何验证:命令、截图、日志或 reviewer 重点
66
60
  - 是否复制了聊天记录;若有,只能复制脱敏后的结论,禁止包含 token、cookie、私有 URL、账号密码
67
61
 
68
- ---
69
-
70
62
  ## Issue 关联与上下文交接
71
63
 
72
64
  - PR 必须关联 issue 或说明为什么不需要 issue。
@@ -74,8 +66,6 @@ PR 描述必须说明:
74
66
  - AI-assisted PR 必须说明 AI 负责了哪些阶段,以及人类如何复核。
75
67
  - 多人或多 agent 协作时,PR 描述必须列出 reviewer focus,避免重复 review。
76
68
 
77
- ---
78
-
79
69
  ## 自动 Review 工具选择
80
70
 
81
71
  | 工具 | 推荐定位 | 是否适合 blocking |
@@ -87,8 +77,6 @@ PR 描述必须说明:
87
77
  | Claude Code Action | 定制化深度 review / 修改建议 | 默认 advisory,严格限制权限 |
88
78
  | Codex Action | 定制化 review / 修复建议 | 默认 advisory,严格控制 API key |
89
79
 
90
- ---
91
-
92
80
  ## 权限与安全红线
93
81
 
94
82
  - ❌ 不在 `pull_request_target` 中运行 AI agent 读取 PR 代码和 secrets。
@@ -97,8 +85,6 @@ PR 描述必须说明:
97
85
  - ❌ 不把私有提示词、聊天原文、token、cookie、连接串写入 PR。
98
86
  - ✅ AI Review 的 prompt 必须限制任务范围、禁止执行 secrets、要求引用具体文件/行。
99
87
 
100
- ---
101
-
102
88
  ## PR Review 检查清单
103
89
 
104
90
  - [ ] PR 关联 issue,scope 单一
@@ -110,8 +96,6 @@ PR 描述必须说明:
110
96
  - [ ] workflow 权限或 secrets 变化已由 `hai-ci` 审查
111
97
  - [ ] AI-assisted 内容已由人类复核
112
98
 
113
- ---
114
-
115
99
  ## 相关 Skills
116
100
 
117
101
  - `hai-ci` — CI/CD 与 workflow 安全