@h-ai/cli 1.0.0-beta.22 → 1.0.0-beta.24

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 (47) hide show
  1. package/README.en.md +11 -12
  2. package/README.ja.md +11 -12
  3. package/README.md +11 -12
  4. package/dist/{chunk-EFC6IHNF.js → chunk-CWMU5QU2.js} +486 -6
  5. package/dist/chunk-CWMU5QU2.js.map +1 -0
  6. package/dist/{chunk-2ZL5ORQ2.js → chunk-P2VZ3VV6.js} +2 -14
  7. package/dist/chunk-P2VZ3VV6.js.map +1 -0
  8. package/dist/cli-config-templates-OWLL4H6K.js +5 -0
  9. package/dist/{cli-config-templates-JJD7YXKL.js.map → cli-config-templates-OWLL4H6K.js.map} +1 -1
  10. package/dist/{cli-skill-templates-D6S2OQ6X.js → cli-skill-templates-JKF6E3PI.js} +3 -3
  11. package/dist/{cli-skill-templates-D6S2OQ6X.js.map → cli-skill-templates-JKF6E3PI.js.map} +1 -1
  12. package/dist/index.js +163 -257
  13. package/dist/index.js.map +1 -1
  14. package/dist/metafile-esm.json +1 -1
  15. package/package.json +14 -14
  16. package/templates/apps/fullstack/docs/security-configuration.md.hbs +3 -3
  17. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +1 -1
  18. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +4 -1
  19. package/templates/base/package.json.hbs +1 -1
  20. package/templates/skills/hai-ai/acp.md +68 -4
  21. package/templates/skills/hai-ai/guide.md +1 -1
  22. package/templates/skills/hai-ai/reference.md +1 -1
  23. package/templates/skills/hai-api-client/SKILL.md +1 -1
  24. package/templates/skills/hai-app-create/development.md +3 -3
  25. package/templates/skills/hai-app-create/logging.md +1 -1
  26. package/templates/skills/hai-audit/SKILL.md +1 -1
  27. package/templates/skills/hai-audit/reference.md +1 -1
  28. package/templates/skills/hai-build/SKILL.md +1 -1
  29. package/templates/skills/hai-build/paths.md +1 -1
  30. package/templates/skills/hai-crypto/SKILL.md +1 -1
  31. package/templates/skills/hai-crypto/reference.md +1 -1
  32. package/templates/skills/hai-deploy/SKILL.md +6 -8
  33. package/templates/skills/hai-deploy/middleware.md +2 -2
  34. package/templates/skills/hai-framework-sync/SKILL.md +4 -4
  35. package/templates/skills/hai-iam/SKILL.md +1 -1
  36. package/templates/skills/hai-iam/reference.md +1 -1
  37. package/templates/skills/hai-kit/reference.md +2 -2
  38. package/templates/skills/hai-reach/SKILL.md +1 -1
  39. package/templates/skills/hai-reldb/SKILL.md +1 -1
  40. package/templates/skills/hai-reldb/reference.md +1 -2
  41. package/templates/skills/hai-scheduler/reference.md +1 -1
  42. package/templates/skills/hai-serv/reference.md +2 -2
  43. package/templates/skills/hai-storage/reference.md +2 -2
  44. package/dist/chunk-2ZL5ORQ2.js.map +0 -1
  45. package/dist/chunk-EFC6IHNF.js.map +0 -1
  46. package/dist/cli-config-templates-JJD7YXKL.js +0 -5
  47. package/templates/skills/hai-deploy/credentials.md +0 -19
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@h-ai/cli",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.22",
4
+ "version": "1.0.0-beta.24",
5
5
  "description": "Hai Framework CLI for project scaffolding and code generation.",
6
6
  "license": "Apache-2.0",
7
7
  "keywords": [
@@ -30,7 +30,7 @@
30
30
  "node": "^22.23.4 || ^24.22.1 || ^26.12.1"
31
31
  },
32
32
  "dependencies": {
33
- "@h-ai/core": "1.0.0-beta.22",
33
+ "@h-ai/core": "1.0.0-beta.24",
34
34
  "cac": "^7.1.0",
35
35
  "chalk": "^6.0.1",
36
36
  "fast-wrap-ansi": "^0.2.2",
@@ -41,18 +41,18 @@
41
41
  "yaml": "^2.9.1"
42
42
  },
43
43
  "devDependencies": {
44
- "@h-ai/api-client": "1.0.0-beta.22",
45
- "@h-ai/cache": "1.0.0-beta.22",
46
- "@h-ai/crypto": "1.0.0-beta.22",
47
- "@h-ai/deploy": "1.0.0-beta.22",
48
- "@h-ai/feedback": "1.0.0-beta.22",
49
- "@h-ai/iam": "1.0.0-beta.22",
50
- "@h-ai/kit": "1.0.0-beta.22",
51
- "@h-ai/payment": "1.0.0-beta.22",
52
- "@h-ai/reach": "1.0.0-beta.22",
53
- "@h-ai/reldb": "1.0.0-beta.22",
54
- "@h-ai/storage": "1.0.0-beta.22",
55
- "@h-ai/vecdb": "1.0.0-beta.22",
44
+ "@h-ai/api-client": "1.0.0-beta.24",
45
+ "@h-ai/cache": "1.0.0-beta.24",
46
+ "@h-ai/crypto": "1.0.0-beta.24",
47
+ "@h-ai/deploy": "1.0.0-beta.24",
48
+ "@h-ai/feedback": "1.0.0-beta.24",
49
+ "@h-ai/iam": "1.0.0-beta.24",
50
+ "@h-ai/kit": "1.0.0-beta.24",
51
+ "@h-ai/payment": "1.0.0-beta.24",
52
+ "@h-ai/reach": "1.0.0-beta.24",
53
+ "@h-ai/reldb": "1.0.0-beta.24",
54
+ "@h-ai/storage": "1.0.0-beta.24",
55
+ "@h-ai/vecdb": "1.0.0-beta.24",
56
56
  "@types/fs-extra": "^11.0.4",
57
57
  "@types/node": "^26.6.6",
58
58
  "@types/prompts": "^2.4.9",
@@ -31,7 +31,7 @@ HAI_AUDIT_BACKUP_ENABLED=true
31
31
 
32
32
  这里列的是 fullstack 模板默认值,不是所有项目或底层 Schema 的普适限制。
33
33
 
34
- 加密请求默认有效 300 秒,允许客户端时间领先服务器最多 30 秒。可在 `_serv.yml` 的 `transport` 下设置 `maxRequestAgeSeconds`(1~600)和 `maxFutureSkewSeconds`(0~300),单位为整数秒。超限时,前端显示校验时的服务器 UTC 时间,提示用户开启设备自动校时或手工修改时间,然后刷新。升级旧版本后,从最后一个旧节点停止处理请求起等待 12 分钟,再把请求有效期调到 300 秒以上。
34
+ 加密请求默认有效 300 秒,允许客户端时间领先服务器最多 30 秒。可在 `_serv.yml` 的 `transport` 下设置 `maxRequestAgeSeconds`(1~600)和 `maxFutureSkewSeconds`(0~300),单位为整数秒。超限时,前端显示校验时的服务器 UTC 时间,提示用户开启设备自动校时或手工修改时间,然后刷新。
35
35
 
36
36
  | 条目 | fullstack 默认及启用入口 | 使用影响 |
37
37
  | ---------------------------- | --------------------------------------------------------------- | -------------------------------------------------------- |
@@ -65,7 +65,7 @@ HAI_AUDIT_BACKUP_ENABLED=true
65
65
 
66
66
  在 `_iam.yml` 设置 `register.enabled: false` 会隐藏访客注册入口,同时由服务端拒绝自助注册;已有账号仍可登录,管理员也仍可创建用户。设回 true 恢复访客注册。
67
67
 
68
- `register.defaultAccountStatus: dormant` 表示自助注册成功后创建休眠账号,等待系统管理员激活后才能登录。默认 active 表示无需审批;仅影响新自助注册账号,管理员创建可另选状态。环境变量为 `HAI_IAM_REGISTER_ENABLED` / `HAI_IAM_REGISTER_DEFAULTACCOUNTSTATUS`。账号只有激活、休眠、注销三种生命周期,不再使用独立启用/停用开关。系统管理员可管理所有职责账号的资料、状态、角色并重置密码;审计与业务配置权限仍归各职责。
68
+ `register.defaultAccountStatus: dormant` 表示自助注册成功后创建休眠账号,等待系统管理员激活后才能登录。默认 active 表示无需审批;仅影响新自助注册账号,管理员创建可另选状态。环境变量为 `HAI_IAM_REGISTER_ENABLED` / `HAI_IAM_REGISTER_DEFAULTACCOUNTSTATUS`。账号状态包括激活、休眠和注销。系统管理员可管理所有职责账号的资料、状态、角色并重置密码;审计与业务配置权限仍归各职责。
69
69
 
70
70
  ## 账号类型、状态和自动休眠
71
71
 
@@ -330,7 +330,7 @@ alerts:
330
330
 
331
331
  反馈 console 通知默认 consoleContent: metadata,只打印编号、应用版本等元数据;summary 是显式选项,可能包含业务信息。Reach API 默认拒绝重定向,敏感发送始终拒绝重定向,生产敏感发送默认要求 HTTPS;可信内网例外必须显式配置 requireHttps: false 并评估网络边界。
332
332
 
333
- 升级前可用 `hai upgrade <精确版本>` 检查实际消费的包和已发布迁移导出。报告出现 migrateAudit({ dryRun: true }) 时先只读预检,再按结果安排备份和实际迁移;报告本身不执行数据库迁移。旧部署缺少受管凭据状态时仍拒绝普通部署,按 hai-deploy skill 的凭据导入流程处理,不删除旧卷或生成新密码替代。
333
+ 升级前可用 `hai upgrade <精确版本>` 核对消费包、安装状态和技能差异。发布前在独立环境验证数据库结构与应用启动,备份数据库、会话缓存、数据卷和受保护的部署状态。部署预检发现已有卷缺少匹配状态时,从核验过的备份恢复。
334
334
 
335
335
  ## 其他模板和业务项目如何复用
336
336
 
@@ -80,7 +80,7 @@ LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IA
80
80
 
81
81
  feedback.init(config, { collectEvidence }) 支持等待业务 text/data 与文本/ZIP/GZIP 附件;_feedback.yml 提供业务采集超时和 Webhook URL/签名密钥/请求超时。密钥仅放服务端私有环境。Webhook 持久重试,详情展示状态并允许管理员重试。
82
82
 
83
- 反馈的 console/disabled/reach 独立选择;SDK getView/ratio/saveDraft 与 createFeedbackReview 统一预览、标注、保存及轮询。退出身份清理草稿和观察器。宿主生命周期由 core.module.createRuntime 处理,框架表升级前备份停旧写入并运行各模块 dryRun 预检。
83
+ 反馈的 console/disabled/reach 独立选择;SDK getView/ratio/saveDraft 与 createFeedbackReview 统一预览、标注、保存及轮询。退出身份清理草稿和观察器。宿主生命周期由 core.module.createRuntime 处理。
84
84
 
85
85
  ## 开发测试
86
86
 
@@ -1,3 +1,4 @@
1
+ import type { KeyExchangeResponse } from '@h-ai/crypto'
1
2
  import { HaiApiClientError } from '@h-ai/api-client'
2
3
  import { authenticateTransportRequest, createInMemoryKeyStore, crypto, TRANSPORT_PROTOCOL } from '@h-ai/crypto'
3
4
  import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'
@@ -41,7 +42,9 @@ function createServerFetch() {
41
42
  serverKeyId: server.getServerKeyId(),
42
43
  serverPublicKey: server.getServerPublicKey(),
43
44
  clientId,
44
- })
45
+ maxPlaintextBytes: server.bodyLimits.plaintextBytes,
46
+ clientKeyTtlSeconds: server.clientKeyTtlSeconds,
47
+ } satisfies KeyExchangeResponse)
45
48
  }
46
49
  const clientId = request.headers.get(TRANSPORT_PROTOCOL.CLIENT_ID_HEADER)
47
50
  if (!clientId)
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "engines": { "node": "^22.23.4 || ^24.22.1 || ^26.12.1" },
3
3
  "name": "{{projectName}}",
4
- "version": "1.0.0-beta.22",
4
+ "version": "1.0.0-beta.24",
5
5
  "private": true,
6
6
  "packageManager": "pnpm@12.11.2",
7
7
  "description": "{{#if_eq appType 'admin'}}Enterprise management system built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'website'}}Enterprise website built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'h5'}}Mobile H5 app built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'api'}}REST API service built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'mobile-app'}}Mobile app built with hai Agent Framework{{/if_eq}}",
@@ -10,13 +10,21 @@ ACP 把宿主应用接到能操作工程的智能体。`ai.llm` 负责模型调
10
10
  | `builtin-service` | 使用已构建镜像启动专属容器 | 引用 Hai 模型;workspace volume 挂 `/workspace`,状态卷挂 `/state` |
11
11
  | `custom-service` | 已有原生 HTTP/WS ACP 服务 | 远端自行维护模型;传远端可见的 cwd;框架不操作远端 Git |
12
12
 
13
- Codex 用 `adapter: 'codex'`,DeepSeek Harness 用 `adapter: 'deepseek-harness'`,其他已配置模型的 ACP 程序用 `adapter: 'generic'` 和 `command/args`。需生成其他原生配置时,向 `ai.init(config, { acpAdapters })` 提供可信服务端适配器;适配器返回 command、args、env、可选 files(写到隔离状态目录)。不把密钥存入 Agent 定义,`environmentRefs` 是目标变量名到宿主环境变量名的映射。
13
+ Codex 用 `adapter: 'codex'`,DeepSeek Harness 用 `adapter: 'deepseek-harness'`,Goose 用 `adapter: 'goose'`。其他已配置模型的 ACP 程序用 `adapter: 'generic'` 和 `command/args`。需生成其他原生配置时,向 `ai.init(config, { acpAdapters })` 提供可信服务端适配器。适配器返回 command、args、env 和写到隔离状态目录的可选 files。`environmentRefs` 保存目标变量名到宿主环境变量名的映射。
14
14
 
15
- 内置 Codex/dsh 通过 stdio 使用。HTTP/WS 是锁定 SDK 2.2.0 的官方实验传输,服务必须实现相同的 ACP 传输版本;不把任意 HTTP 聊天接口当 ACP,也不自动架设 stdio 网关。自定义服务必须声明 `supportedTransports`,协议不匹配返回错误。
15
+ 内置 Codex、DSH 和 Goose 通过原生 stdio 接入。HTTP/WS 是锁定 SDK 2.2.0 的官方实验传输,服务必须实现相同的 ACP 传输版本。自定义服务必须声明 `supportedTransports`,协议不匹配返回错误。
16
+
17
+ Agent 镜像按任务选择 `minimal`、`documents`、`office`、`browser` 或 `developer`。将构建后的镜像 ID 或仓库清单 digest 登记到 Runner 环境。无需在任务内安装工具链。需要直接处理文件时,也可使用具备相应权限的独立工具作业。
18
+
19
+ 使用 `session.changeExecution({ mode: 'task', acceptNewSession: true, historySummary })` 切换到任务独占容器时,可带入当前用户确认过的历史摘要。摘要最多 8 KiB UTF-8,作为新会话首次请求的历史文本发送一次。会话工具和资料仍按当前授权重新核验。
20
+
21
+ 受管请求可传 `workspaceId`。应用用 `acpPolicy.allowWorkspace` 核验主体,用 `resolveWorkspace` 在执行节点提供文件名到 `Uint8Array` 的映射。快照最多 8 个平铺文件、合计不超过 16 MiB 和环境 `scratchMiB`,仅挂载到独占任务的只读 `/input`。临时副本写入 `/workspace`,会话结束后回收。
16
22
 
17
23
  Linux 上运行 embedded Codex 前,按 [Codex 沙箱前置](https://learn.chatgpt.com/docs/sandboxing) 准备 bubblewrap 和所需的 AppArmor profile,并用 `codex sandbox` 在临时目录验证读写。沙箱初始化失败应先修复宿主环境,不能通过关闭沙箱或让模型猜测文件内容完成任务。
18
24
 
19
- ## 原生 HTTP/WS 服务:Goose
25
+ ## Goose 的原生接入
26
+
27
+ 受管 Goose 使用 `goose acp`,选择 `adapter: 'goose'`、`mode: 'embedded'` 或 `'builtin-service'`,绑定登记的 Hai 模型。适配器使用独立 Goose 状态目录和逐次工具审批,模型协议支持 Chat Completions、Responses 和 Anthropic。Goose 和 DSH 的每次受管启动只注入本次选中模型的凭据。
20
28
 
21
29
  Goose 1.57.0 自身提供 `goose serve` 与 `/acp` HTTP/WS,使用 custom-service 接入。先由部署方启动服务、挂载工作区/状态卷,并在 Goose 端维护模型(例如 `GOOSE_PROVIDER=openrouter`、`GOOSE_MODEL`、`OPENROUTER_API_KEY`);服务独立设置 `GOOSE_SERVER__SECRET_KEY`。Hai 只使用 `X-Secret-Key` 认证,不向服务注入 Hai 模型密钥。
22
30
 
@@ -42,6 +50,62 @@ WebSocket 改为 `transport: 'ws'` 和 `ws://` 地址。`cwd` 是远端可见路
42
50
 
43
51
  `acp.agents`、`acp.workspaces` 可以直接写在配置文件里,也可通过 register 保存到数据库。get/list 返回 `{ value, source, version? }`,配置同 ID 优先且不可修改;数据库支持完整 update 和 remove。模型、MCP 等清单也遵循此规则,见 [资源清单](resources.md)。创建会话可通过 `mcpServerIds` 绑定合并清单里的 MCP。
44
52
 
53
+ ## 为受管会话绑定第三方工具
54
+
55
+ 先在 `mcp.servers` 登记第三方 Streamable HTTP 服务,设置 `allowedTools` 和上游认证头引用。每个执行节点挂载自己的工具入口,并给 Worker 提供可达的地址。入口只把当前会话的短期 Bearer 传给 Agent,真实上游凭据由服务端解析。建议使用执行节点的内网服务地址和受保护的网络。
56
+
57
+ ```ts
58
+ import { createServer } from 'node:http'
59
+ import { ai, type ACPPlatformPolicy, type MCPServiceBroker, type MCPServiceBrokerOptions } from '@h-ai/ai'
60
+
61
+ // 应用传入真实 IAM 检查。该函数复核任务归属、权限及实际工具参数。
62
+ function prepareTools(url: string, authorize: MCPServiceBrokerOptions['authorize']) {
63
+ let broker: MCPServiceBroker | undefined
64
+ const http = createServer((req, res) => {
65
+ if (broker) return void broker.handleRequest(req, res)
66
+ res.writeHead(503).end()
67
+ })
68
+ const policy: ACPPlatformPolicy = {
69
+ // 示例只给 manuals 租户的 librarian 账号开放这一个工具。
70
+ allowTools: (scope, _agentId, ids) =>
71
+ scope.tenantId === 'manuals' && scope.userId === 'librarian' && ids.every(id => id === 'manual_search'),
72
+ async bindTools(scope, sessionId, ids, signal) {
73
+ if (!broker || ids.length !== 1 || ids[0] !== 'manual_search')
74
+ throw new Error('Manual tool binding is unavailable')
75
+ const bound = await broker.bind({
76
+ principal: { tenantId: scope.tenantId, userId: scope.userId },
77
+ taskId: sessionId,
78
+ signal,
79
+ tools: [{
80
+ id: 'manual_search',
81
+ serviceId: 'manual',
82
+ tool: 'search_manual',
83
+ description: 'Search authorized manuals',
84
+ inputSchema: {
85
+ type: 'object', properties: { query: { type: 'string', maxLength: 1000 } },
86
+ required: ['query'], additionalProperties: false,
87
+ },
88
+ }],
89
+ })
90
+ if (!bound.success) throw new Error(bound.error.message)
91
+ return bound.data
92
+ },
93
+ }
94
+ return {
95
+ http, policy,
96
+ activate() {
97
+ // ai.init(config, { runner, acpPolicy: policy }) 成功后,监听 HTTP 端口之前激活。
98
+ const created = ai.mcp.services.createBroker({ url, authorize })
99
+ if (created.success) broker = created.data
100
+ return created
101
+ },
102
+ close() { broker?.close() },
103
+ }
104
+ }
105
+ ```
106
+
107
+ 创建绑定时,工具入口为每项工具检查目录白名单和输入 Schema。每次调用重新检查业务权限和目录,网络重定向会失败。绑定默认有效 15 分钟。会话关闭、租约失效或服务停止时撤销绑定。多个执行节点分别挂载自己的入口,使 Agent 始终访问签发本次凭据的节点。
108
+
45
109
  ## 最小本机接入
46
110
 
47
111
  下面的目录、Git 地址、模型和密钥由部署方提供。首次登记一次,后续用 get/list 读取;重复 register 返回冲突。普通 API 都先检查 `success`。
@@ -122,7 +186,7 @@ Podman 不自动继承远程服务的代理变量。需要代理时,使用 Age
122
186
 
123
187
  发布仅允许框架创建的隔离 session,避免将共享目录中别人的修改算入当前任务。操作前停止受管进程/容器,避免背景工具继续写入;要继续编码显式 `sessions.resume(id)`。原生 Agent 自己创建的 worktree 不自动纳入框架发布范围。
124
188
 
125
- 私有仓库把 Git 凭据引用写入 workspace 的 `gitEnvironmentRefs`,把 Agent 专用变量写入 agent 的 `environmentRefs`。旧 workspace 的 `environmentRefs` 仍共用,迁移时移走其中的 Git 凭据。启用 Git 隔离后,远程克隆、拉取、推送只使用登记的远端地址和可信环境注入,在独立 Git 目录运行;需要的网络代理或 CA 设置也随 Git 引用配置。认证脚本和全局 Git 配置应由可信执行器提供。任务之间的访问权限仍由应用和运行环境隔离。
189
+ 私有仓库把 Git 凭据引用写入 workspace 的 `gitEnvironmentRefs`,把 Agent 专用变量写入 agent 的 `environmentRefs`。启用 Git 隔离后,远程克隆、拉取、推送只使用登记的远端地址和可信环境注入,在独立 Git 目录运行;需要的网络代理或 CA 设置也随 Git 引用配置。认证脚本和全局 Git 配置应由可信执行器提供。任务之间的访问权限仍由应用和运行环境隔离。
126
190
 
127
191
  多个工程不是原子事务。失败时返回 `ACP_PARTIAL_FAILURE`,`error.cause.reports` 列出每个工程 success、phase、commit 和 error;已完成工程不回滚,冲突保留现场。失败于 push 后,排除权限/网络问题可重试;远端结果不明时先核对实际分支。普通文件的修改留在 session 目录,不自动纳入 Git 发布。失败创建的 worktree 也保留,避免删除已有成果。
128
192
 
@@ -82,7 +82,7 @@ await ai.close()
82
82
 
83
83
  ## 配置要点
84
84
 
85
- LLM 协议使用 `llm.protocol`、`llm.models[].protocol` 和 `tempModel.protocol`,值为 `chat | responses | anthropic`;环境变量使用 `HAI_AI_LLM_PROTOCOL`、`HAI_AI_LLM_MODELS_0_PROTOCOL` 等。旧 `api` 字段及旧协议变量会报迁移错误,密钥字段 `apiKey` 不变。
85
+ LLM 协议使用 `llm.protocol`、`llm.models[].protocol` 和 `tempModel.protocol`,值为 `chat | responses | anthropic`;环境变量使用 `HAI_AI_LLM_PROTOCOL`、`HAI_AI_LLM_MODELS_0_PROTOCOL` 等。
86
86
 
87
87
  ```yaml
88
88
  llm:
@@ -73,7 +73,7 @@ await mcp.connect(new StdioServerTransport())
73
73
 
74
74
  ### `ai.mcp`
75
75
 
76
- 这是进程内注册表,不会自动绑定独立 MCP Server 的 transport。工具注册时编译 JSON Schema、调用时校验输入;非法输入不执行 handler。资源必须恰好含 text/blob 之一;提示词必填参数必须是自身字符串属性,输出使用 SDK 消息类型(含 image/audio)。同名注册覆盖,缺失 requestId 自动补 UUID。已移除未使用的 MCPProvider 与 AIMCPFunctionsDeps 类型;使用 MCPOperations 即可。
76
+ 这是进程内注册表,不会自动绑定独立 MCP Server 的 transport。工具注册时编译 JSON Schema、调用时校验输入;非法输入不执行 handler。资源必须恰好含 text/blob 之一;提示词必填参数必须是自身字符串属性,输出使用 SDK 消息类型(含 image/audio)。同名注册覆盖,缺失 requestId 自动补 UUID。调用接口类型为 `MCPOperations`。
77
77
 
78
78
  | 方法 | 说明 |
79
79
  | --- | --- |
@@ -29,7 +29,7 @@ description: "接入或排查 @h-ai/api-client typed API、登录 Token、自动
29
29
 
30
30
  ## 按需参考
31
31
 
32
- Serv/Kit 对通过请求绑定、签名和 MAC 校验但超出时间窗口的请求返回加密的 HTTP 400 错误。客户端抛出 `TransportTimeError`(`hai:crypto:071`),显示校验时的服务器 UTC 时间,提示开启设备的自动校时或手工修改时间后刷新。`serverTime` 为 Unix 毫秒,旧服务端未提供该值时仍显示校时提示。`api-client` 映射为 `VALIDATION_FAILED`,在 `cause.transportCode` 和 `cause.serverTime` 保留诊断信息。
32
+ Serv/Kit 对通过请求绑定、签名和 MAC 校验但超出时间窗口的请求返回加密的 HTTP 400 错误。客户端抛出 `TransportTimeError`(`hai:crypto:071`),显示校验时的服务器 UTC 时间,提示开启设备的自动校时或手工修改时间后刷新。`serverTime` 为 Unix 毫秒。`api-client` 映射为 `VALIDATION_FAILED`,在 `cause.transportCode` 和 `cause.serverTime` 保留诊断信息。
33
33
 
34
34
  按本次操作读取对应小节;以已安装版本的公开类型核验签名,示例中的业务变量由应用提供。
35
35
 
@@ -22,13 +22,13 @@ README 编辑先读章节,把功能说明与示例合并到对应章节;新
22
22
 
23
23
  ### 页面与布局
24
24
 
25
- 每个模板只安装实际使用的模块:admin/h5 包含认证、验证码及找回密码通知,以及数据库、缓存、加密依赖;website 只包含 Core/Kit/UI;API 包含认证、通知、上传和反馈;fullstack 保留管理后台的认证、审计、存储、通知、调度和反馈;mobile-app 只使用客户端能力。AI、payment、vecdb、datapipe 不默认安装。所有项目保留完整模块 YAML 和 `.env.example`,未启用项以注释提供,只有已启用项进入公共环境默认值。后续添加对应依赖、取消所需配置注释,再接入初始化、关闭及业务路由;添加依赖不会自动启用功能。`--template`、`--features`、`--examples/--no-examples` 已删除,`create --yes/-y` 改为 `--defaults`,旧参数明确报错;`deploy --yes` 保持原义。已有工程不会自动裁剪依赖。
25
+ 每个模板只安装实际使用的模块:admin/h5 包含认证、验证码及找回密码通知,以及数据库、缓存、加密依赖;website 只包含 Core/Kit/UI;API 包含认证、通知、上传和反馈;fullstack 保留管理后台的认证、审计、存储、通知、调度和反馈;mobile-app 只使用客户端能力。AI、payment、vecdb、datapipe 不默认安装。所有项目保留完整模块 YAML 和 `.env.example`,未启用项以注释提供,只有已启用项进入公共环境默认值。后续添加对应依赖、取消所需配置注释,再接入初始化、关闭及业务路由;添加依赖不会自动启用功能。无交互创建项目使用 `hai create --defaults`。执行 `hai deploy --yes` 时使用已保存的部署配置。
26
26
 
27
27
  website默认SSR;静态发布须先移除服务端业务依赖、初始化及API/actions。静态构建与实际路径验证按[hai-build](../hai-build/SKILL.md)。
28
28
 
29
29
  admin、website、h5 和 Fullstack Web 在入口 HTML 加载 `_hai/browser-check/startup.js` 后才进入应用。检测到 Chrome/Edge 低于 111、Firefox 低于 114、Safari 或 iOS/iPadOS 低于 16.4 时,浏览器跳转到同目录的静态升级页。保留经典脚本标签和静态资源,验证根目录和发布子目录都能在应用包加载失败时显示升级提示。
30
30
 
31
- 网站挂载到`/yyy/`等目录时,按[网站挂载目录](../hai-build/paths.md)同步资源、链接、认证端点和服务端守卫。SvelteKit在编译时固定base,Vite默认相对资源加hash导航;API基址单独配置。SDK子目录制品使用格式5,健康与增量检查随制品处理,不手工修改旧格式清单来代替重新构建。
31
+ 网站挂载到`/yyy/`等目录时,按[网站挂载目录](../hai-build/paths.md)同步资源、链接、认证端点和服务端守卫。SvelteKit在编译时固定base,Vite默认相对资源加hash导航;API基址单独配置。镜像清单使用格式 5,部署健康检查和增量更新按清单中的 `webBasePath` 处理。
32
32
 
33
33
  页面共用根布局的 header/footer。独立移动应用的页面放在 `src/lib/pages/**/*.svelte`,Fullstack 放在 `packages/<name>-shared/src/lib/pages/**/*.svelte`,由 `HashRouter` 和 `import.meta.glob` 自动发现;新增页面无需修改路由表,菜单按业务配置入口。SvelteKit 保留 `src/routes/**/+page.svelte` 自动文件路由、服务端鉴权和刷新定位。
34
34
 
@@ -85,7 +85,7 @@ Fullstack 的环境文件在工程根;service 脚本通过 `../../.env*` 加
85
85
 
86
86
  先把原来被忽略的 `.env` 私有值迁入 `.env.local`,再提交公共基础和环境文件。本机文件只保留需要覆盖的值,避免整份复制示例后固定开发环境。旧的 `HAI_AI_LLM_API_KEY` / `HAI_AI_LLM_BASE_URL` 改为 `HAI_AI_LLM_APIKEY` / `HAI_AI_LLM_BASEURL`;音频和图像厂商回退变量同样使用 `APIKEY` 后缀。Reach 和 deploy 凭据按当前 YAML 路径命名,以项目 `.env.example` 为准,同步迁移部署平台变量和本机文件。
87
87
 
88
- 原 `HAI_AI_ANTHROPIC_API_KEY` / `HAI_AI_ANTHROPIC_BASE_URL` 不再使用。默认协议为 `anthropic` 时改用标准 LLM 变量;混合模型池中有独立凭据或端点时,将 `apiKey` / `baseUrl` 配置在对应模型项。厂商回退 `ANTHROPIC_API_KEY` / `ANTHROPIC_BASE_URL` 保留,优先级以 AI 模块说明为准。
88
+ 默认协议为 `anthropic` 时使用标准 LLM 配置。混合模型池的独立凭据或端点配置在对应模型项的 `apiKey` 和 `baseUrl`。厂商环境变量及优先级见 AI 模块说明。
89
89
 
90
90
  #### 常用变量及约束
91
91
 
@@ -23,7 +23,7 @@
23
23
 
24
24
  ## Storage
25
25
 
26
- `storage` 默认开启写操作摘要,读操作按需开启。常规操作使用 `debug`,上传、下载、删除等失败返回业务错误并记录 `warn`,初始化、连接或关闭失败记录 `error`。日志省略对象键、签名地址和内容。使用 `HAI_CORE_LOGGING_LEVEL`,旧的 `HAI_STORAGE_OPERATIONLOG_LEVEL` 与 `operationLog.level` 已移除。
26
+ `storage` 默认开启写操作摘要,读操作按需开启。常规操作使用 `debug`,上传、下载、删除等失败返回业务错误并记录 `warn`,初始化、连接或关闭失败记录 `error`。日志省略对象键、签名地址和内容,由 `HAI_CORE_LOGGING_LEVEL` 过滤。
27
27
 
28
28
  流式上传保留源读取错误、取消原因和 S3 原始写入错误。分片清理也失败时单独保留清理错误,并记录可用的 S3 操作名和请求编号。条件写入冲突按 `ALREADY_EXISTS` 处理。使用 Storage 时查阅项目中 `hai-storage` 的配置与错误说明。
29
29
 
@@ -29,7 +29,7 @@ description: "接入 @h-ai/audit 记录业务操作,查询分页日志与统
29
29
 
30
30
  `audit.log(input,tx)`、`audit.capture(input,{tx})` 可使用调用者现有 RelDB 事务,事件和变更一并提交或回滚;失败尝试须在回滚后由入口记录。自动记录失败输出诊断并保留已生效业务结果;强制审计的业务检查同事务显式 log 的 HaiResult 后再提交。list 支持 requestId/traceId 关联筛选。
31
31
 
32
- `retention:{enabled:true,minDays:90}` 将最低保留写入共享数据库,cleanup(0) 也必须遵守;数据库触发器保护近期行的改删与覆盖。框架首次未配置不强制保护;未传 retention 的重初始化保留既有策略,显式可信配置可关闭。DB 所有者 DDL/权限与独立归档是部署边界。升级前停旧写入、备份并用 `migrateAudit({dryRun:true})` 预检。写失败返回失败并输出诊断;close 等待在途写入后再关闭数据库。
32
+ `retention:{enabled:true,minDays:90}` 将最低保留写入共享数据库,cleanup(0) 也必须遵守;数据库触发器保护近期行的改删与覆盖。框架首次未配置不强制保护;未传 retention 的重初始化保留既有策略,显式可信配置可关闭。DB 所有者 DDL/权限与独立归档是部署边界。`audit.init()` 校验当前表结构。用户名取自事件时的身份快照。写失败返回失败并输出诊断;close 等待在途写入后再关闭数据库。
33
33
 
34
34
  常见事件使用 `audit.helper` 与公开 `AuditHelper` 类型;内部记录器装配工厂不从包入口导出。
35
35
 
@@ -69,7 +69,7 @@ if (!closeResult.success) {
69
69
 
70
70
  `audit.log(input,tx)`、`audit.capture(input,{tx})` 可使用调用者现有 RelDB 事务,事件和变更一并提交或回滚;失败尝试须在回滚后由入口记录。自动记录失败输出诊断并保留已生效业务结果;强制审计的业务检查同事务显式 log 的 HaiResult 后再提交。list 支持 requestId/traceId 关联筛选。
71
71
 
72
- `retention:{enabled:true,minDays:90}` 启用共享最低保留,cleanup(0) 不能绕过。触发器拒绝保护期内改删及冲突覆盖;未传 retention 的重初始化沿用已有策略,只有显式可信配置能关闭。默认清理90天不等于不可变保护,首次未配置时不强制启用。DB 所有者 DDL、权限与独立归档需部署侧控制。升级前停旧写入并备份,`migrateAudit({dryRun:true})` 只读预检,init 自动升级;close 会等待已开始的写入。
72
+ `retention:{enabled:true,minDays:90}` 启用共享最低保留,cleanup(0) 不能绕过。触发器拒绝保护期内改删及冲突覆盖;未传 retention 的重初始化沿用已有策略,只有显式可信配置能关闭。默认清理90天不等于不可变保护,首次未配置时不强制启用。DB 所有者 DDL、权限与独立归档需部署侧控制。`audit.init()` 校验当前表结构。用户名取自事件时的身份快照。`audit.close()` 等待已开始的写入。
73
73
 
74
74
  `backup.enabled` 默认关闭;开启后注入已初始化的私有 StorageFunctions。backup.run({id?,from?,to?,signal?}) 流式条件创建 JSONL,返回记录数/SHA-256/截止时间;稳定 ID 只复用完整且条件相同的归档,不覆盖。backup.verify(key) 有界核对;batchSize/maxRecordBytes 控制内存,超限不截断证据。AUDIT_BACKUP_PREFIX 固定为 hai-private/audit-backups/,公开读取入口只允许指定资源,关闭备份不解除私有边界;已配置公开 publicUrl 的 S3 不能启用备份。
75
75
 
@@ -58,7 +58,7 @@ description: "构建或排查 hai 应用的源码、静态网站、容器镜像
58
58
 
59
59
  交付角色统一为 `serv`(独立 API 后端)、`web`(静态或 SSR 浏览器站点)、`app`(Android/iOS 手机安装包)、`desktop`(桌面安装包)。Fullstack 容器为 serv + 可选 web,API 为 serv,admin/website/h5/mobile-app 的浏览器镜像为 web;原生 app/desktop 不作为服务器 Compose 服务。`--images` 与 `--services` 使用 serv/web,`--target app` 与 `--target desktop` 生成原生包。API workspace 的服务目录为 `apps/<项目>-serv`。镜像与容器共用工程根 `package.json.name` 的归一化身份(去 scope、转小写、非法字符合并为连字符);名称缺失或无效时报错,不回退目录名。镜像为 `localhost/hai-<项目>-<角色>:<buildId>`,容器为 `hai-<项目>-<环境>-<角色>`,镜像可跨环境复用。
60
60
 
61
- 制品格式4和5都记录primaryService(serv/web),hasWeb表示完整工程是否包含浏览器端;格式5另记录非根目录webBasePath。只有serv + web生成同源API代理;格式1至3须重新构建。CLI的--project-name与SDK的DeployAppOptions.projectName覆盖入口已移除,旧参数明确报错,请在工程根package.json.name维护身份。迁移旧工程先同步build.images、Dockerfile及API workspace的-serv包名与引用,重新安装依赖并重建完整制品。旧部署先备份、核对项目名、卷和受管凭据,再建立完整基线。工具不自动跨项目迁移数据;完整部署仍按Compose规则清理同项目旧服务,不能仅改deploy-target.json.directory完成迁移。网站目录与格式5迁移见[网站挂载目录](paths.md)。
61
+ 镜像制品统一使用格式 5,`webBasePath` 为空字符串时表示域名根目录。`primaryService` 记录主服务,`hasWeb` 记录完整 Web 拓扑。部署身份来自工程根 `package.json.name`。只有 `serv` 与 `web` 同时存在时才生成同源 API 代理。 公开挂载目录见[网站挂载目录](paths.md)。
62
62
 
63
63
  ## 按需参考
64
64
 
@@ -21,7 +21,7 @@ SvelteKit 3 的宿主在 `sveltekit({ paths: { base: 挂载目录, relative: fal
21
21
  ## SDK容器交付
22
22
 
23
23
  - `PUBLIC_BASE_PATH=/yyy`用于compile或image网站构建;HAI_BUILD_STATIC仍只用于website的compile静态预渲染。
24
- - 根目录制品沿用格式4,非根目录制品使用格式5并记录webBasePath。使用支持格式5的CLI/Deploy;旧工具拒绝新格式,不能手改编号绕过。
24
+ - 镜像清单使用格式 5,`webBasePath` 为必填项。域名根目录写空字符串。
25
25
  - SDK生成匹配的Nginx目录、运行配置入口、健康检查和访问URL。外部网关转发到此入口时保留目录,避免再次剥离。
26
26
  - 每次完整或部分构建保持同一PUBLIC_BASE_PATH,即使只构建serv。目录变化须全量部署;遗漏或改变目录的增量包会在替换前拒绝。失败恢复使用旧发布的健康路径;容器恢复不撤销业务数据。
27
27
 
@@ -32,7 +32,7 @@ transport 仅支持 v2:SM2 发送方签名、独立密钥的 Encrypt-then-HMAC
32
32
 
33
33
  业务容量统一配置 transport.maxPlaintextBytes:UTF-8 JSON 明文字节,默认 1 MiB,有效整数范围 1 KiB~64 MiB,请求和响应共用。客户端从握手获取服务端预算,可选本地上限取较小值;resolveTransportBodyLimits 自动推导密文预算为两倍明文加 32 KiB。握手 JSON 16 KiB、公钥 4 KiB、认证头 16 KiB、路径 8 KiB、认证及防重放保持独立。原流超限/取消立即停止、取消并释放 reader;请求 413、响应返回加密的 500 容量错误,客户端识别 TransportBodyTooLargeError / hai:crypto:070。 自定义适配器使用 manager.bodyLimits 和 readTransportBody 消费原流,不 clone/tee;握手返回 maxPlaintextBytes。
34
34
 
35
- Serv/Kit 对通过请求绑定、签名和 MAC 校验但超出时间窗口的请求返回加密的 HTTP 400 错误。客户端抛出 `TransportTimeError`(`hai:crypto:071`),显示校验时的服务器 UTC 时间,提示开启设备的自动校时或手工修改时间后刷新。`serverTime` 为 Unix 毫秒,旧服务端未提供该值时仍显示校时提示。`api-client` 映射为 `VALIDATION_FAILED`,在 `cause.transportCode` 和 `cause.serverTime` 保留诊断信息。
35
+ Serv/Kit 对通过请求绑定、签名和 MAC 校验但超出时间窗口的请求返回加密的 HTTP 400 错误。客户端抛出 `TransportTimeError`(`hai:crypto:071`),显示校验时的服务器 UTC 时间,提示开启设备的自动校时或手工修改时间后刷新。`serverTime` 为 Unix 毫秒。`api-client` 映射为 `VALIDATION_FAILED`,在 `cause.transportCode` 和 `cause.serverTime` 保留诊断信息。
36
36
 
37
37
  ## 按需参考
38
38
 
@@ -235,7 +235,7 @@ const manager = crypto.transport.createServer({ serverKeyRing: ring.data, keySto
235
235
 
236
236
  业务容量统一配置 transport.maxPlaintextBytes:UTF-8 JSON 明文字节,默认 1 MiB,有效整数范围 1 KiB~64 MiB,请求和响应共用。客户端从握手获取服务端预算,可选本地上限取较小值;resolveTransportBodyLimits(limit, { requiredPlaintextBytes }) 合并模块需求:保留显式上限,不足时报配置冲突;省略时按需要推导,无模块需要仍为 1 MiB。Serv/Kit 的 auto 规范化为 undefined。密文预算为两倍明文加 32 KiB。握手 JSON 16 KiB、公钥 4 KiB、认证头 16 KiB、路径 8 KiB、认证及防重放保持独立。原流超限/取消立即停止、取消并释放 reader;请求 413、响应返回加密的 500 容量错误,客户端识别 TransportBodyTooLargeError / hai:crypto:070。 自定义适配器使用 manager.bodyLimits 和 readTransportBody 消费原流,不 clone/tee;握手返回 maxPlaintextBytes。
237
237
 
238
- Serv/Kit 对通过请求绑定、签名和 MAC 校验但超出时间窗口的请求返回加密的 HTTP 400 错误。客户端抛出 `TransportTimeError`(`hai:crypto:071`),显示校验时的服务器 UTC 时间,提示开启设备的自动校时或手工修改时间后刷新。`serverTime` 为 Unix 毫秒,旧服务端未提供该值时仍显示校时提示。`api-client` 映射为 `VALIDATION_FAILED`,在 `cause.transportCode` 和 `cause.serverTime` 保留诊断信息。
238
+ Serv/Kit 对通过请求绑定、签名和 MAC 校验但超出时间窗口的请求返回加密的 HTTP 400 错误。客户端抛出 `TransportTimeError`(`hai:crypto:071`),显示校验时的服务器 UTC 时间,提示开启设备的自动校时或手工修改时间后刷新。`serverTime` 为 Unix 毫秒。`api-client` 映射为 `VALIDATION_FAILED`,在 `cause.transportCode` 和 `cause.serverTime` 保留诊断信息。
239
239
 
240
240
  自定义 HTTP 适配器检查失败原因 `error instanceof TransportTimeError && error.context` 后,使用 `createTransportErrorResponse(error, { manager, context: error.context })` 加密拒绝响应;不能根据未认证报文的时间戳给出可信时间诊断。
241
241
 
@@ -20,13 +20,11 @@ description: "构建并发布或交付已有镜像:完整离线包、按服务
20
20
 
21
21
  Vercel API/文件上传只请求官方入口,拒绝重定向,每次请求和完整 JSON 读取共用 30 秒期限;超时先查询平台实际状态,不无条件重复发布。此期限没有配置开关。
22
22
 
23
- --plan 和 --inspect-remote 从 CLI 完整透传,只读失败不得退回部署。target.runtime 只表示远端配置。旧凭据用服务器本机 `hai deploy-secrets <directory> --import <private.json>` 预检,--apply 才导入;SDK importDeploymentSecrets 默认 dryRun:true,验证项目/卷/实际凭据、共享 flock、v2 状态特殊字符与原子 0600 写入,缺状态的普通部署仍拒绝。完整格式和恢复步骤见 [凭据导入](credentials.md)。
23
+ --plan 和 --inspect-remote 从 CLI 完整透传,只读失败不得退回部署。target.runtime 只表示远端配置。
24
24
 
25
25
  ## 操作流程
26
26
 
27
- 全量与增量都须在变更前核对实际卷和后端家族。服务器 `persistent-backends` 在任何启动前保存绑定,服务移除、首次失败及恢复均保留;与 `managed-secrets.env`、数据卷成套保护和备份。不能删除或编辑账本强行认领,不把“移除 PostgreSQL 再加 MySQL”视为新环境。旧 active 只有已知家族和唯一真实服务容器的 Mounts、Config.Image 同时吻合才能补证;未知 dormant 旧卷拒绝猜测,活动卷缺失拒绝空库自愈。新 release 的 `previous-state-backends` 仅供恢复前核验旧 tuple、账本与实际卷,不回退永久记录。此私有元数据没有新增公开配置 API。
28
-
29
- 受控导入 v2 可为未认领旧卷补证,但须项目/凭据组/精确卷绑定与唯一运行原容器的真实角色标签、Mounts、Image 家族完全一致;Docker/Podman namespace冲突拒绝,已知 ledger/context/daemon 冲突不覆盖。导入不创建 current,缺成功基线时必须当前 CLI 新 ID 完整全量包,完整成功后才可增量。详见[凭据导入](credentials.md),不得把导入或接管称作数据库数据恢复。
27
+ 全量和增量部署都须在变更服务前核对实际卷及后端家族。已有卷须匹配 `persistent-backends`,缺少记录或活动卷时停止部署,先恢复核验过的备份。服务启动前写入账本,移除服务、首次安装失败和恢复都会保留。账本与 `managed-secrets.env`、数据卷成套备份。`previous-state-backends` 用于恢复前重新验证原绑定。
30
28
 
31
29
  身份限制只发生在 SSH 目标 Linux 服务器执行 `apply.sh`:固定 SSH uid、本地默认 Docker context 或实际本地 Podman,以及 daemon/store;远程连接、非默认 context、显式存储覆盖拒绝。生产显式 pin `remote.runtime`;auto 因新装 Podman 换引擎时,先恢复原 runtime/用户/store。Windows/macOS 操作机用 Docker Desktop/Podman VM 构建打包再 SSH 发布不受限。有意更换 daemon、服务器或恢复/替换数据时单独迁移,不能用 uid、路径或家族相同证明数据格式兼容;主版本和 Schema 兼容仍须单独确认。
32
30
 
@@ -34,12 +32,12 @@ Vercel API/文件上传只请求官方入口,拒绝重定向,每次请求和
34
32
 
35
33
  1. 读取项目 scripts、images/ 中的 Dockerfile、项目根 hai.json 的 build/deploy 与服务目录运行配置。构建与部署属于整个项目;服务目录只用于扫描运行依赖。创建默认带开发期部署工具;用户明确 --no-deploy 时不生成部署入口。构建细节见 [hai-build](../hai-build/SKILL.md)。
36
34
  2. 选择环境,验证 .env.<mode> 存在,再处理部署目标与必要中间件。SSH 支持 key/agent 或 password,缺项按说明补齐,有效完整配置直接复用;--bundle-only 在构建和中间件配置后、打包前最后询问是否添加或修改 SSH 信息,保存并用于本次和后续 target;--yes 或跳过时复用已有配置。新私有参数写 .env.<mode>.local,共享 .env.local 保留本机私有值;私钥仅引用路径,密码隐藏输入并保留原值。Core、Node/Vite 和部署统一加载模式私有层,按来源先父后细项。优先级与认证边界见 [middleware.md](middleware.md)。
37
- 3. 先校验所选制品、版本、服务和SHA-256。--build只构建所选应用镜像;不带它时缺产物明确失败,不隐式补构建。根目录使用格式4,非根目录使用格式5及webBasePath;两者都记录appVersion、buildId、partial、hasWeb、镜像归档及显式配置的servContainerPort/webContainerPort,部分构建也保留未选镜像端口,缺省使用部署默认值。网站目录由构建进程PUBLIC_BASE_PATH确定,所有部分构建须保持一致;目录变化必须全量,健康与恢复按制品记录处理。具体步骤见[网站挂载目录](../hai-build/paths.md)。同一应用版本可重建,镜像引用区分实际内容;禁止latest与无版本镜像。
35
+ 3. 先校验所选制品、版本、服务和SHA-256。--build只构建所选应用镜像;不带它时缺产物明确失败,不隐式补构建。制品使用格式 5,记录 `webBasePath`(域名根目录为空字符串)、appVersion、buildId、partial、hasWeb、镜像归档及显式配置的servContainerPort/webContainerPort,部分构建也保留未选镜像端口,缺省使用部署默认值。网站目录由构建进程PUBLIC_BASE_PATH确定,所有部分构建须保持一致;目录变化必须全量,健康与恢复按制品记录处理。具体步骤见[网站挂载目录](../hai-build/paths.md)。同一应用版本可重建,镜像引用区分实际内容;禁止latest与无版本镜像。
38
36
  4. 完整包自动导出实际自建中间件镜像并去重;只更新 Web 不重新打包 API/中间件。打包机需容器引擎导出中间件,服务器仅 load,禁止 pull/build。外部连接及云开通不能伪称为离线自包含服务。
39
37
  5. --services 使用目标服务器最后成功状态为基线,检查端口/拓扑及未选依赖,保留未选配置、凭据、网络和卷。脚本先按项目/服务标签仅删除选中旧容器(保留卷),再 up -d --no-deps --no-build --pull never --no-recreate 创建新容器并保留其他容器;先等待选中中间件健康,再启动 serv/Web,失败恢复同序,避免 Compose Provider 连带重建反向依赖,禁止整个项目 down。S3 可选 createBucket 在 storage.init 中检查并创建缺失桶,自建 S3 注入 HAI_STORAGE_CREATEBUCKET=true;仅更新 storage 无须应用镜像,新桶在下次应用初始化时创建。Compose 网络统一 hai-app,序列化不使用 YAML 锚点。
40
38
  6. 每次交付只生成工程根 .hai/deploy/<环境>/bundle-<项目>-<部署ID>-<版本>/ 一个目录,外层仅含 tar、deploy.sh、deploy.ps1、deploy-target.json、read-target.awk、deploy-local.sh 和 README.txt;Compose、运行环境、web.conf 和 manifest 仅在 tar 内,README 记录部署 ID。--output release.tar 生成同目录的 release-<版本>/release-<版本>.tar,不能覆盖已有交付。--bundle-only 不连接 SSH,生成带逐项说明的 deploy-target.json,只引用 passwordEnv 而不含 SSH 密码值;修改 target 仅影响本包。Windows PowerShell 5+ deploy.ps1、Linux/macOS deploy.sh 读取该文件,上传并自动解包部署;隔离服务器复制整个目录后执行 sh deploy-local.sh,自动解包再执行 apply.sh。只复制归档时,解压后阅读同目录的 `APPLY.txt`,在该目录执行 `sh ./apply.sh`。脚本不依赖源码、Node 或 pnpm;本机运行 deploy.sh 需 sh、awk、ssh、scp。manifest.partial/selectedServices 固化模式:完整构建且无 --services 为全量;部分构建或显式 --services 为增量,必须匹配服务器成功基线。
41
39
  7. 工具预检、基线、上传、校验、镜像导入、服务更新和 HTTP 检查分别报告。失败返回非零退出码,结果文件保留失败阶段;只有检查成功才更新服务器 current。已有部署失败尝试恢复所选服务的旧容器和配置,并按旧发布端口/路径验证容器和 HTTP;result 的 recoveryStatus 为 not-needed/passed/failed/stopped。数据卷保留,已写业务数据和不兼容 Schema 迁移不回退。恢复验证失败不能表述为已回滚成功。禁止把本地打包记录当服务器成功状态。
42
- 8. 部署及恢复全程用 Linux flock 持有固定 `.deploy.lock`;不得删除/替换文件或按时间抢锁。父进程强杀后,继承 FD 的活跃子命令仍持锁;所有持有进程退出或重启后自动释放。旧 `.deploy-lock` 目录保持原样,升级前结束旧版部署进程。强杀/断电不执行恢复 trap,缺结果文件须人工核对容器、镜像和 current 后用新包恢复,锁释放不代表副作用已回退。
40
+ 8. 部署及恢复全程用 Linux flock 持有固定 `.deploy.lock`;不得删除/替换文件或按时间抢锁。父进程强杀后,继承 FD 的活跃子命令仍持锁;所有持有进程退出或重启后自动释放。强杀/断电不执行恢复 trap,缺结果文件须人工核对容器、镜像和 current 后用新包恢复,锁释放不代表副作用已回退。
43
41
 
44
42
  成功后手工回退使用**当前 CLI**、旧应用 build 制品和匹配配置,省略 `--build`、`--services` 生成新全量 ID;离线也须重新打包,不能运行旧 bundle 或旧工具绕过账本。旧制品通常只保留 serv/web 镜像,中间件仍按当前 CLI 固定版本规划,不承诺精确回退全部中间件版本、DDL 或业务数据。确认主版本、Schema、拓扑和数据兼容并准备备份,再发布和验证。
45
43
 
@@ -73,7 +71,7 @@ Node 后端(Serv / SvelteKit SSR)每次启动读取服务器 `<部署目录>
73
71
 
74
72
  每个部署包的外层 `README.txt` 和归档内 `APPLY.txt` 都包含文件索引、环境优先级、当前包的变量名和排障步骤。解包目录的 `config/.env.runtime` 是发布输入,部署根下的是当前运行配置,`releases/<ID>/` 下的是历史记录。外部 PostgreSQL 改密后更新项目源环境并发布后端。部署校验拒绝 URL 与分字段密码冲突,增量切换外部与随包中间件需要改用全量发布。 `HAI_SERV_REFRESH_COOKIE_SECURE` 独立于 `HAI_SERV` 父配置,容器部署接受 `true`、`false` 或空值。
75
73
 
76
- 部署归档顶层包含 `apply.sh`、`APPLY.txt`、`manifest.json`、`config/`、`images/` 和 `.hai/`。`config/.env.runtime` 是唯一应用环境文件;`manifest.json.metadata` 集中保存依赖、布局、健康路径、镜像列表、受管绑定等非敏感元数据。`.hai/compose.json` 是完整服务快照;局部更新在服务边界替换并保留未选服务,不串联历史 Compose 文件。`.hai/` 还存原生环境、加载器、Nginx/TLS、策略和校验和,秘密不写入 manifest。辅助脚本合入 `apply.sh`。失败时先恢复原应用配置再恢复服务,凭据、后端账本和数据卷继续保护。新包格式为 2,不实现旧目录兼容或迁移。
74
+ 部署归档顶层包含 `apply.sh`、`APPLY.txt`、`manifest.json`、`config/`、`images/` 和 `.hai/`。`config/.env.runtime` 是唯一应用环境文件;`manifest.json.metadata` 集中保存依赖、布局、健康路径、镜像列表、受管绑定等非敏感元数据。`.hai/compose.json` 是完整服务快照;局部更新在服务边界替换并保留未选服务,不串联历史 Compose 文件。`.hai/` 还存原生环境、加载器、Nginx/TLS、策略和校验和,秘密不写入 manifest。辅助脚本合入 `apply.sh`。失败时先恢复原应用配置再恢复服务,凭据、后端账本和数据卷继续保护。部署归档的 `bundleFormat` 为 `2`。
77
75
 
78
76
  ## CLI
79
77
 
@@ -86,7 +84,7 @@ pnpm build --target image --images web
86
84
  pnpm run deploy --env prod --services web
87
85
  ```
88
86
 
89
- 制品格式4和5都记录primaryService(serv/web),hasWeb表示完整工程是否包含浏览器端;格式5另记录非根目录webBasePath。只有serv + web生成同源API代理;格式1至3须重新构建。CLI的--project-name与SDK的DeployAppOptions.projectName覆盖入口已移除,旧参数明确报错,请在工程根package.json.name维护身份。迁移旧工程先同步build.images、Dockerfile及API workspace的-serv包名与引用,重新安装依赖并重建完整制品。旧部署先备份、核对项目名、卷和受管凭据,再建立完整基线。工具不自动跨项目迁移数据;完整部署仍按Compose规则清理同项目旧服务,不能仅改deploy-target.json.directory完成迁移。
87
+ 镜像制品统一使用格式 5,`webBasePath` 为空字符串时表示域名根目录。`primaryService` 记录主服务,`hasWeb` 记录完整 Web 拓扑。部署身份来自工程根 `package.json.name`。只有 `serv` 与 `web` 同时存在时才生成同源 API 代理。
90
88
 
91
89
  上传脚本先复用操作机密码;缺失或为空时直接隐藏输入并继续本次部署,输入不落盘;非交互调用明确失败且不等待。无效输入显示变量名和约束;SCP 上传期间通过 SSH 查询远端归档大小,显示已接收/总字节与百分比,成功后才显示 100%。增量部署先恢复已停止或 Compose down 的既有完整基线,复用本地镜像且不重建正在运行的容器,再检查依赖和更新选中服务;恢复失败须检查诊断,不能推进 current。
92
90
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  默认部署名取工程根(最近的 `hai.json` 或锁文件所在目录)的 `package.json.name`,缺失时报错,再附加显式环境后缀。例如 fullstack 工程 `hai-delivery` 扫描 `packages/hai-delivery-serv`,`--env test` 生成 `/opt/hai/apps/hai-delivery-test` 和 `bundle-hai-delivery-test-<部署ID>-<版本>.tar.gz`。远端目录、交付包、Compose 项目、API/Web/中间件容器、数据卷、服务器凭据状态及增量基线统一使用该名称;不会按字符串删除真实项目名中的 `-serv`。
10
10
 
11
- 资源身份和制品格式沿用[构建技能](../hai-build/SKILL.md)及[网站挂载目录](../hai-build/paths.md):根目录格式4,非根目录格式5,两者都有primaryService/hasWeb;webBasePath仅格式5。旧工程同步镜像角色、Dockerfile、-serv包名与引用后重建,不手改清单。旧部署先核对项目名、卷和受管凭据,再建立完整基线;工具不跨项目迁移数据,改target目录不能完成迁移。
11
+ 部署身份取自工程根 `package.json.name`。镜像清单字段及公开挂载目录见[构建技能](../hai-build/SKILL.md)与[网站挂载目录](../hai-build/paths.md)。
12
12
 
13
13
  `hai deploy` 首先输入部署环境,或用 `hai deploy --env test` 指定。`.env.test` / `.env.prod` 必须由用户先创建;缺失时停止,不代替用户创建一个空文件继续部署。指定要部署的目录,例如 `hai deploy packages/my-app-serv --env test`,该目录必须对应 lockfile 的一个 importer;不遍历 apps/packages 或猜测 fullstack 布局。环境文件默认取当前目录(有 `.env` 时)或 lockfile 根目录,必要时传 `--env-dir`。
14
14
 
@@ -23,7 +23,7 @@
23
23
 
24
24
  `.env.<mode>.local` 同时用于普通开发、Node 启动和部署;通过公共 Core 工具合并,不实现模块专用来源顺序。
25
25
 
26
- 交付 tar 内的 `.env.runtime` 是按上述配置生成的 Compose 运行文件,不是下次部署的配置源。`NODE_ENV` 默认按目标模式选择:test 为 test,dev/development 为 development,其余为 production;显式应用配置仍可覆盖。构建保持正式优化模式,旧包需重新生成。完整配置使用 `--env test --yes` 复用;需要保持中间件时追加 `--skip-middleware`。自建中间件的密码由服务器 `<remoteDir>/managed-secrets.env` 持久保存(权限 0600),应与数据卷一起备份。每次打包只生成首次初始化的随机候选,不依赖打包机缓存;在线 SDK、deploy.sh、deploy.ps1 和 deploy-local.sh 都在部署锁内复用服务器值,同时更新应用连接配置及中间件原生变量。交付 tar 保持不可变,只有服务器私有运行文件使用定稿值。若状态缺失而对应数据卷已存在,部署在变更服务前明确停止,须恢复服务器凭据备份;不会自动换密或删除数据。旧版本可通过显式预检和凭据导入流程迁移,缺状态的普通部署仍拒绝。
26
+ 交付 tar 内的 `.env.runtime` 是按上述配置生成的 Compose 运行文件,不是下次部署的配置源。`NODE_ENV` 默认按目标模式选择:test 为 test,dev/development 为 development,其余为 production;显式应用配置仍可覆盖。构建保持正式优化模式,旧包需重新生成。完整配置使用 `--env test --yes` 复用;需要保持中间件时追加 `--skip-middleware`。自建中间件的密码由服务器 `<remoteDir>/managed-secrets.env` 持久保存(权限 0600),应与数据卷一起备份。每次打包只生成首次初始化的随机候选,不依赖打包机缓存;在线 SDK、deploy.sh、deploy.ps1 和 deploy-local.sh 都在部署锁内复用服务器值,同时更新应用连接配置及中间件原生变量。交付 tar 保持不可变,只有服务器私有运行文件使用定稿值。若状态缺失而对应数据卷已存在,部署在变更服务前明确停止,须恢复服务器凭据备份;不会自动换密或删除数据。
27
27
 
28
28
  自建或云开通的整体 `HAI_*` 配置会清除被替换的旧叶字段,例如 Redis 覆盖后不再留下 `HAI_CACHE_TYPE=memory`。全局 `~/.hai/credentials.yml` 只补缺项,不能覆盖当前环境/进程的同名键或父配置。部署先启动选中中间件,等待 PostgreSQL/MySQL/Redis/S3 健康,再启动 serv/Web;增量和失败恢复沿用此顺序,未选容器保持不变。
29
29
 
@@ -17,7 +17,7 @@ description: "升级应用的 hai-framework 到最新或指定发布版本:分
17
17
 
18
18
  ## 任务入口
19
19
 
20
- - 用户说“升级 Hai-framework 到最新版本”时,直接从当前应用执行下方升级流程。该请求已授权常规依赖更新、必要兼容迁移、skills 合并和本地验证;不为每个文件修改重复确认,也不只输出升级建议后结束。
20
+ - 用户说“升级 Hai-framework 到最新版本”时,直接从当前应用执行下方升级流程。该请求已授权常规依赖更新、必要的应用调用和配置更新、skills 合并和本地验证;不为每个文件修改重复确认,也不只输出升级建议后结束。
21
21
  - 用户仅要求审查/比较版本时,完成现状、目标与差异分析,不安装或修改应用。
22
22
  - 仅同步通用规范、AI 入口或联调两个仓库时,按需读取 [同步与本地联调](sync.md);普通应用升级不要求框架仓库可写。
23
23
  - 先识别当前目录是否为目标应用;确实无法确定目标项目时才询问。应用升级不包含 npm 发布、部署、生产数据迁移或系统级工具安装,已有明确授权时按其范围执行。
@@ -50,7 +50,7 @@ npm view @h-ai/cli dist-tags --json
50
50
 
51
51
  ### 3. 比较累计差异并关联应用
52
52
 
53
- 在修改依赖前,读取当前到目标版本之间的 Release/CHANGELOG、迁移说明及官方提交差异,覆盖中间版本;混版本逐包比较。上游仓库从包元数据或官方 README 确认,按发布 tag/commit 定位,不能把 main 分支的未发布能力归到目标版本。
53
+ 在修改依赖前,读取当前到目标版本之间的 Release、CHANGELOG 和上游提交差异,覆盖中间版本;混版本逐包比较。上游仓库从包元数据或官方 README 确认,按发布 tag/commit 定位,不能把 main 分支的未发布能力归到目标版本。
54
54
 
55
55
  没有本地框架源码也应继续:在临时目录用 `npm pack <包名>@<精确版本> --ignore-scripts --pack-destination <临时目录>` 获取当前/目标包,比较 package.json.exports、公开 `.d.ts`、配置 schema/默认值、实现与随包文档;从同版本 CLI 的 `templates/skills/` 获取完整技能目录及入口模板。占位参数先替换为已确认值;只读比较产物,不覆盖应用或执行其中脚本。命令依据:[npm view](https://docs.npmjs.com/cli/commands/npm-view)、[npm pack](https://docs.npmjs.com/cli/commands/npm-pack)。
56
56
 
@@ -59,7 +59,7 @@ npm view @h-ai/cli dist-tags --json
59
59
  逐项检查并关联实际文件/调用点:
60
60
 
61
61
  - 公开入口、API/类型/错误码、HaiResult 与流/抛错语义、初始化依赖和关闭行为。
62
- - 配置 schema、默认行为、环境覆盖、认证/安全策略、DB schema/迁移、外部服务与引擎要求。
62
+ - 配置 schema、默认行为、环境覆盖、认证/安全策略、持久表结构、外部服务与引擎要求。
63
63
  - 构建/运行/发布脚本、第三方 peer 依赖、原生/容器集成,以及版本绑定的补丁是否仍必要。
64
64
  - skills 及相邻资源、AGENTS/Claude/Copilot/OpenCode 路由。
65
65
 
@@ -106,4 +106,4 @@ npm view @h-ai/cli dist-tags --json
106
106
  - 修复本次引入的失败,区分升级前已有失败。必要验收缺服务/凭证/平台时提示阻塞;额外平台或未涉及的真实 Provider 验证明确标为未执行及原因,不能用 mock/Web 结果冒充真实/原生验证。
107
107
  - 最终报告当前 → 目标及来源、复用的框架能力与清理项、补丁等用户决定、配置与关键流程的变动、变更文件与同步入口、实际门禁和未验证边界、恢复方法。依赖与必要迁移完成、选择/阻塞已解除且必要验证通过才称“升级完成”;否则报告当前进度与下一步,用户处理后继续完成。
108
108
 
109
- 指定精确版本后先 hai upgrade <version>,一次核对实际消费包及 CLI/deploy 发布完整性、制品/skills、catalog/lock/安装漂移和业务定制。此命令只读,缺包不得先改工程;报告完整后再按本 skill 执行获授权的升级,合并定制不覆盖。数据库迁移单独停旧写入、备份、migrateIam/migrateReach/migrateScheduler 预检;无凭据代次的旧会话重新登录。
109
+ 指定精确版本后先 hai upgrade <version>,一次核对实际消费包及 CLI/deploy 发布完整性、制品/skills、catalog/lock/安装漂移和业务定制。此命令只读,缺包不得先改工程;报告完整后再按本 skill 执行获授权的升级,合并定制不覆盖。发布前核对持久结构,保留数据库和会话缓存备份。在独立环境验证初始化和登录。
@@ -80,7 +80,7 @@ OTP 发布/消费用单身份 CAS;密码重置最终 SQL 同时核验 resetVer
80
80
 
81
81
  配置示例用 `IamConfigInput` 表达可省略默认值的输入;需要完整策略快照时用对应 Schema.parse 得到输出类型。应用仅从 `@h-ai/iam` 取公开函数/类型,不深导内部策略与仓储。源码内部示例明确标注上下文,文档示例类型检查不替代真实共享存储和通知集成验证。
82
82
 
83
- 默认 Reach 通知自动使用 sensitive/expiresAt/idempotencyKey,不保存凭据正文或进入延迟队列;自定义回调同样遵守有效期与幂等。RelDB 初始化后可 migrateIam({dryRun:true}),iam.init 执行支持版本的字段升级,保留用户/密码。升级前停旧写入并备份;无安全代次的旧会话需重新登录,不能降级凭据安全代次。
83
+ 默认 Reach 通知自动使用 sensitive/expiresAt/idempotencyKey,不保存凭据正文或进入延迟队列;自定义回调同样遵守有效期与幂等。先初始化 RelDB。`iam.init()` 创建并校验当前表结构,结构不符时返回初始化失败。会话凭据代次不匹配时重新登录。
84
84
 
85
85
  - 可选再认证规则为文件 operations 与权限 sensitiveOperations 的并集,主开关仍是 reauthentication.enabled;可信管理端使用 authz.setPermissionSensitiveOperations,异步 iam.getPublicConfig 返回含数据库的有效公开策略,读取失败拒绝放行。session.terminalLimits 按 web/app/desktop/api 限制,非空时未列类型拒绝;全局 maxSessions/singleDevice 同时生效,终端分组不是硬件真实性证明。原地登录使用标准 expectedUserId 限定原用户,凭据/验证码/锁定规则照常执行。
86
86
 
@@ -511,7 +511,7 @@ SvelteKit 使用 `kit.auth.createApi(iam)` 导出标准 handler,匿名端点
511
511
 
512
512
  未启用额外期限时,access 与 refresh 独立到期:access 过期仍可凭有效 refresh 轮换,刷新不先要求旧 access 认证。`session.idleTimeout`、`absoluteTimeout` 以秒配置,0关闭;启用后 access 与 refresh 均检查,刷新保留首次登录时间。成功的 access 认证请求算活动;自动 refresh 仅换票,不延长闲置期限。后台业务轮询仍需按项目设计。`maxSessions: 0` 不限,否则在用户分区 CAS 原子限制有效会话数;`singleDevice: true` 默认顶旧保新,`singleDeviceMode: 'reject'` 保留旧会话并拒绝新登录。删除 access、logoutAll、单设备替换均撤销对应 refresh;`revokeRefresh` 保留仍有效的 access。
513
513
 
514
- 账号生命周期仅使用必填 `accountStatus`(active/dormant/closed),无 User.enabled;列表过滤/排序同名,注册 defaultAccountStatus 默认 active、可设 dormant。beta.1 迁移前停旧写入并备份数据库;v6 将原停用 active 账号转 dormant 后删除旧列,镜像回滚不能恢复数据库。账号默认 `permanent/active`;管理端可配置 `temporary` 与 `accountExpiresAt`,或设 `accountStatus` 为 `dormant/closed`。状态/有效期变化推进持久凭据代际,重新激活不恢复旧会话。`accounts.dormantAfterDays: 0` 关闭自动休眠;启用后按 `scanIntervalSeconds` 扫描最后成功登录/创建时间,也可从可信后台调用 `iam.user.scanInactiveAccounts()`。公开注册不能接受管理字段;`closed` 保留记录,个人数据注销由项目处理。
514
+ 账号生命周期使用必填 `accountStatus`(active/dormant/closed)。列表过滤和排序使用同名字段,注册 `defaultAccountStatus` 默认为 `active`,也可设置为 `dormant`。账号默认 `permanent/active`;管理端可配置 `temporary` 与 `accountExpiresAt`,或设 `accountStatus` 为 `dormant/closed`。状态/有效期变化推进持久凭据代际,重新激活不恢复旧会话。`accounts.dormantAfterDays: 0` 关闭自动休眠;启用后按 `scanIntervalSeconds` 扫描最后成功登录/创建时间,也可从可信后台调用 `iam.user.scanInactiveAccounts()`。公开注册不能接受管理字段;`closed` 保留记录,个人数据注销由项目处理。
515
515
 
516
516
  `password.minCharacterClasses` 支持任意 N 类字符;创建/改密/重置共用服务端强度校验。`expirationDays: 0` 关闭期限;`preventSamePassword` 可独立启用,期限或首次强改时也拒绝旧密码。`requireInitialChange` 只约束管理端初始/重置密码,关闭后不受历史标记约束。首次/过期用户用 `iam.user.renewPassword({identifier,password,newPassword})` 完成原密码验证与换密后重新登录,不能先授予普通会话。AuthPanel 与标准 Kit/Serv 端点提供该流程。
517
517
 
@@ -8,7 +8,7 @@ HTTP/UI 边界只对明确的有效 4xx 状态公开业务提示;错误缺少
8
8
 
9
9
  认证协议仅支持 v2:独立随机 SM4-CBC 密钥和 HMAC-SM3 密钥由 SM2 封装,先验签、再验证 MAC,最后解密 CBC。请求由客户端私钥签名,响应由所选服务端版本签名。认证字段包括 version、direction、serverKeyId、clientId、128 位随机 requestId(兼 nonce)、issuedAt、HTTP method、pathname + 原始 search 的 SM3 pathHash,以及响应 status。请求默认有效期为 5 分钟,客户端时间最多可领先服务器 30 秒。服务端可用 `maxRequestAgeSeconds`(1~600)和 `maxFutureSkewSeconds`(0~300)调整,单位为整数秒。共享 registry 原子消费 (clientId, requestId),nonce 保留到 issuedAt + 11 分钟,覆盖最长可配窗口及节点时钟差,存储故障拒绝请求。Redis 必须保留有效 nonce,使用 noeviction/可靠持久化策略;各节点时钟须同步。此能力防止同一传输消息重放,业务重试仍需自己的幂等键。
10
10
 
11
- 在 `_kit.yml` 的 `transport` 块配置时间窗口,将字段传给服务端 transport 装配。完成旧节点升级后等待 12 分钟,再把有效期调到 300 秒以上。校时提示与 `TransportTimeError.serverTime` 见 [Crypto 参考](../hai-crypto/reference.md)。`kit.client.createAuthActions()` 将已认证校时错误转为 `HaiResult`,供 AuthPanel 展示。
11
+ 在 `_kit.yml` 的 `transport` 块配置时间窗口,将字段传给服务端 transport 装配。校时提示与 `TransportTimeError.serverTime` 见 [Crypto 参考](../hai-crypto/reference.md)。`kit.client.createAuthActions()` 将已认证校时错误转为 `HaiResult`,供 AuthPanel 展示。
12
12
 
13
13
  空 POST 也发送空明文的认证封装;GET/HEAD 将封装放在 X-Hai-Transport 头,204/304/HEAD 等无正文响应也使用同名头承载认证封装。其它请求/响应在 JSON 正文承载封装并带 X-Encrypted: true。客户端必须关联原请求上下文和 HTTP status,缺标记、旧格式或认证失败一律 reject;明文接口由 Serv/Kit 路径规则 `encryption: disabled` 或宿主 `excludePaths` 显式允许;调用方同步选择普通请求,API Client/Kit 包装器使用自己的 `excludePaths`。CORS 须允许并暴露 X-Hai-Transport。握手公钥的真实性依赖 TLS,不替代 IAM 业务授权。
14
14
 
@@ -101,7 +101,7 @@ export const handle = kit.createHandle({
101
101
  })
102
102
  ```
103
103
 
104
- 需要保护会话 Cookie 时配置 `crypto.encryptedCookies`,并通过 `crypto.cookieEncryptionKey` 或 `HAI_KIT_COOKIE_KEY` 提供密钥。密钥必须为 32 位十六进制。Cookie 采用分离子密钥的 SM4-CBC/HMAC-SHA256,先验证版本、名称、IV 与密文,再解密;旧版无认证 Cookie 升级后失效,需重新登录。缺少或非法密钥会在 `createHandle()` 时失败;加解密错误不会回退到明文 Cookie。
104
+ 需要保护会话 Cookie 时配置 `crypto.encryptedCookies`,并通过 `crypto.cookieEncryptionKey` 或 `HAI_KIT_COOKIE_KEY` 提供密钥。密钥必须为 32 位十六进制。Cookie 使用独立子密钥执行 SM4-CBC 和 HMAC-SHA256,验证版本、名称、IV 与密文后解密。`createHandle()` 会拒绝缺失或无效的密钥。
105
105
 
106
106
  不再使用无运行入口的旧 Crypto Helpers 或其 `CryptoServiceLike`、`EncryptedCookieConfig`、`CryptoCsrfConfig`、`WebhookVerifyConfig` 类型;这些已删除。Cookie 通过上述 `kit.createHandle` 配置保护,其他加密能力使用 `@h-ai/crypto` 真实公开 API。
107
107
 
@@ -42,4 +42,4 @@ API 空 2xx 表示受理成功;非空 JSON 回执上限 64 KiB。redirect 默
42
42
 
43
43
  IAM 通知使用 `otp_email`、`otp_sms`、`password_reset`、`password_reset_sms` 标准模板;将已初始化的 `reach` 传入 `iam.init`。Console Provider 只记录元数据,不输出验证码/令牌,不代替实际邮件/短信发送。
44
44
 
45
- 凭据通知用 sensitive:true、Unix 毫秒 expiresAt 和无凭据的稳定 idempotencyKey。共享 DB 仅存元数据回执,不存正文/变量/凭据摘要,不延迟重投;成功返回 receiptId,不明结果不自动重发。开发 Console 明确允许的输出与持久观察器隔离,生产 Console 限制不变。普通通知可用 deferPolicy: reject 将排队交给调用方。升级先 migrateReach({dryRun:true}),旧载荷一次性退役,旧在途 unknown,先备份停旧写入。
45
+ 凭据通知用 sensitive:true、Unix 毫秒 expiresAt 和无凭据的稳定 idempotencyKey。共享 DB 仅存元数据回执,不存正文/变量/凭据摘要,不延迟重投;成功返回 receiptId,不明结果不自动重发。开发 Console 明确允许的输出与持久观察器隔离,生产 Console 限制不变。普通通知可用 deferPolicy: reject 将排队交给调用方。`reach.init()` 创建并校验发送日志表及队列标识约束。
@@ -41,4 +41,4 @@ description: "使用 @h-ai/reldb 访问 SQLite/PostgreSQL/MySQL,编写 SQL、C
41
41
 
42
42
  JSON 对象合并使用 RFC 7396 补丁,必须将返回的 SQL/params 放在同一次 UPDATE 内;禁止先读对象再覆盖整个列来模拟跨节点原子合并。路径函数的后端差异和完整可类型检查示例见 [reference.md](reference.md)。
43
43
 
44
- 框架模块维护自己的版本迁移,应用不直接 ALTER 框架表。`reldb.schemaColumns(table, sql?)` 只读真实列;`reldb.migrateSchema(module, steps, { dryRun: true })` 不创建账本。生产先停旧写入并备份 DB/共享会话缓存;SQLite/PostgreSQL 事务,MySQL DDL 隐式提交须可重入,失败不推进版本且重试检查真实结构。回退恢复兼容 DB 与代码,不只换二进制。模块 migrateIam/migrateReach/migrateScheduler 分别预检,初始化执行受支持步骤。
44
+ `reldb.schemaColumns(table, sql?)` 读取实际列名。框架模块按当前定义初始化并校验各自的表。应用只管理自己的业务表。
@@ -444,7 +444,6 @@ if (!result.success) throw new Error(result.error.message)
444
444
  | `HaiReldbError.QUERY_FAILED` | `hai:reldb:002` | 查询或执行失败 |
445
445
  | `HaiReldbError.CONSTRAINT_VIOLATION` | `hai:reldb:003` | 约束违反 |
446
446
  | `HaiReldbError.TRANSACTION_FAILED` | `hai:reldb:004` | 事务失败 |
447
- | `HaiReldbError.MIGRATION_FAILED` | `hai:reldb:005` | 迁移失败 |
448
447
  | `HaiReldbError.RECORD_NOT_FOUND` | `hai:reldb:006` | 记录不存在 |
449
448
  | `HaiReldbError.DUPLICATE_ENTRY` | `hai:reldb:007` | 重复条目 |
450
449
  | `HaiReldbError.DEADLOCK` | `hai:reldb:008` | 死锁 |
@@ -500,7 +499,7 @@ const result = await reldb.tx.wrap(async (tx) => {
500
499
 
501
500
  ## 生产共享状态
502
501
 
503
- 应用自己的表迁移使用 `reldb.schemaColumns(table, sql?)` 读取真实列,使用 `reldb.migrateSchema(module, steps, options?)` 执行版本步骤;两者属于已初始化实例,不另传 reldb 句柄。`dryRun: true` 不写账本,失败不推进版本;MySQL DDL 必须可重入。框架表由各模块迁移入口维护,应用不要直接修改。
502
+ `reldb.schemaColumns(table, sql?)` 只读查询实际列名。传入当前事务的 SQL 操作句柄,可在同一事务中检查表结构。框架模块初始化时校验各自的表结构,业务表由应用管理。
504
503
 
505
504
  生产仅使用 PostgreSQL/MySQL;SQLite(含磁盘文件)只用于开发/明确测试,不能作为跨主机共享状态。 NODE_ENV 或 HAI_CORE_ENV 为 production 时在初始化成功前检查,只有 HAI_E2E=1/HAI_E2E_MOCK=1 明确测试豁免。不要将租约当作最终写入条件,外部未知效果须按稳定业务键核对。
506
505