@h-ai/cli 1.0.0-beta.21 → 1.0.0-beta.22
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.
- package/README.en.md +2 -0
- package/README.ja.md +2 -0
- package/README.md +2 -0
- package/dist/{chunk-L53P43B2.js → chunk-EFC6IHNF.js} +38 -18
- package/dist/chunk-EFC6IHNF.js.map +1 -0
- package/dist/cli-config-templates-JJD7YXKL.js +5 -0
- package/dist/{cli-config-templates-LWMD2I6V.js.map → cli-config-templates-JJD7YXKL.js.map} +1 -1
- package/dist/index.js +27 -10
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -1
- package/package.json +14 -14
- package/templates/apps/fullstack/images/web/nginx.conf.hbs +3 -1
- package/templates/base/images/web/nginx.conf.hbs +3 -1
- package/templates/base/package.json.hbs +1 -1
- package/templates/shared/download-error/http.conf +19 -0
- package/templates/shared/download-error/server.conf +52 -0
- package/templates/skills/hai-api-client/SKILL.md +1 -1
- package/templates/skills/hai-app-create/SKILL.md +2 -0
- package/templates/skills/hai-app-create/logging.md +32 -0
- package/templates/skills/hai-app-create/project.md +1 -0
- package/templates/skills/hai-app-create/reference.md +2 -4
- package/templates/skills/hai-app-review/SKILL.md +1 -1
- package/templates/skills/hai-core/reference.md +2 -11
- package/templates/skills/hai-crypto/reference.md +2 -2
- package/templates/skills/hai-deploy/SKILL.md +2 -0
- package/templates/skills/hai-kit/SKILL.md +2 -2
- package/templates/skills/hai-kit/reference.md +1 -1
- package/templates/skills/hai-reldb/reference.md +1 -1
- package/templates/skills/hai-serv/SKILL.md +1 -1
- package/templates/skills/hai-storage/SKILL.md +1 -0
- package/templates/skills/hai-storage/reference.md +13 -3
- package/templates/skills/hai-vecdb/reference.md +1 -1
- package/dist/chunk-L53P43B2.js.map +0 -1
- package/dist/cli-config-templates-LWMD2I6V.js +0 -5
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.
|
|
4
|
+
"version": "1.0.0-beta.22",
|
|
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.
|
|
33
|
+
"@h-ai/core": "1.0.0-beta.22",
|
|
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.
|
|
45
|
-
"@h-ai/cache": "1.0.0-beta.
|
|
46
|
-
"@h-ai/crypto": "1.0.0-beta.
|
|
47
|
-
"@h-ai/deploy": "1.0.0-beta.
|
|
48
|
-
"@h-ai/feedback": "1.0.0-beta.
|
|
49
|
-
"@h-ai/iam": "1.0.0-beta.
|
|
50
|
-
"@h-ai/kit": "1.0.0-beta.
|
|
51
|
-
"@h-ai/payment": "1.0.0-beta.
|
|
52
|
-
"@h-ai/reach": "1.0.0-beta.
|
|
53
|
-
"@h-ai/reldb": "1.0.0-beta.
|
|
54
|
-
"@h-ai/storage": "1.0.0-beta.
|
|
55
|
-
"@h-ai/vecdb": "1.0.0-beta.
|
|
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",
|
|
56
56
|
"@types/fs-extra": "^11.0.4",
|
|
57
57
|
"@types/node": "^26.6.6",
|
|
58
58
|
"@types/prompts": "^2.4.9",
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{{! @skipIfEmpty }}
|
|
2
2
|
{{#if fullstack.frontends.web}}
|
|
3
|
+
{{{nginxDownloadErrors "http"}}}
|
|
3
4
|
server {
|
|
4
5
|
listen 8080;
|
|
5
6
|
server_name _;
|
|
6
7
|
root /usr/share/nginx/html;
|
|
7
8
|
|
|
9
|
+
{{{nginxDownloadErrors "server"}}}
|
|
8
10
|
location / {
|
|
9
|
-
try_files $uri $uri/
|
|
11
|
+
try_files $uri $uri/ @hai_spa_fallback;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
location = /runtime-config.js {
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{{! @skipIfEmpty }}
|
|
2
2
|
{{#if isSvelteOnlyApp}}
|
|
3
|
+
{{{nginxDownloadErrors "http"}}}
|
|
3
4
|
server {
|
|
4
5
|
listen 8080;
|
|
5
6
|
server_name _;
|
|
6
7
|
root /usr/share/nginx/html;
|
|
7
8
|
|
|
9
|
+
{{{nginxDownloadErrors "server"}}}
|
|
8
10
|
location / {
|
|
9
|
-
try_files $uri $uri/
|
|
11
|
+
try_files $uri $uri/ @hai_spa_fallback;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
location = /runtime-config.js {
|
|
@@ -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.
|
|
4
|
+
"version": "1.0.0-beta.22",
|
|
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}}",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
map "$request_method:$args" $hai_signed_download {
|
|
2
|
+
default 0;
|
|
3
|
+
"~*^(GET|HEAD):(?:[^&]*&)*X-Amz-Signature=[^&]+(?:&|$)" 1;
|
|
4
|
+
}
|
|
5
|
+
map $http_accept_language $hai_download_language {
|
|
6
|
+
default zh-CN;
|
|
7
|
+
~*^en en-US;
|
|
8
|
+
~*^ja ja-JP;
|
|
9
|
+
}
|
|
10
|
+
map $hai_download_language $hai_download_title {
|
|
11
|
+
default "下载链接无法访问";
|
|
12
|
+
en-US "Download link unavailable";
|
|
13
|
+
ja-JP "ダウンロードリンクにアクセスできません";
|
|
14
|
+
}
|
|
15
|
+
map $hai_download_language $hai_download_instruction {
|
|
16
|
+
default "请返回下载页面重新获取链接。若仍无法下载,请联系管理员。";
|
|
17
|
+
en-US "Return to the download page to get a new link. If the download still fails, contact your administrator.";
|
|
18
|
+
ja-JP "ダウンロードページに戻り、新しいリンクを取得してください。解決しない場合は管理者にお問い合わせください。";
|
|
19
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
location @hai_download_unavailable {
|
|
2
|
+
access_log off;
|
|
3
|
+
error_log /dev/null;
|
|
4
|
+
types { }
|
|
5
|
+
default_type text/html;
|
|
6
|
+
charset utf-8;
|
|
7
|
+
add_header Cache-Control "private, no-store" always;
|
|
8
|
+
add_header Referrer-Policy no-referrer always;
|
|
9
|
+
add_header X-Content-Type-Options nosniff always;
|
|
10
|
+
add_header Content-Security-Policy "default-src 'none'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'" always;
|
|
11
|
+
return 404 '<!doctype html>
|
|
12
|
+
<html lang="$hai_download_language">
|
|
13
|
+
<head>
|
|
14
|
+
<meta charset="utf-8">
|
|
15
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
16
|
+
<meta name="robots" content="noindex">
|
|
17
|
+
<meta name="referrer" content="no-referrer">
|
|
18
|
+
<link rel="icon" href="data:,">
|
|
19
|
+
<title>$hai_download_title</title>
|
|
20
|
+
<style>
|
|
21
|
+
* { box-sizing: border-box; }
|
|
22
|
+
body {
|
|
23
|
+
margin: 0;
|
|
24
|
+
min-height: 100vh;
|
|
25
|
+
display: grid;
|
|
26
|
+
place-items: center;
|
|
27
|
+
padding: 24px;
|
|
28
|
+
background: #f1f5f9;
|
|
29
|
+
color: #172033;
|
|
30
|
+
font-family: Inter, system-ui, "Microsoft YaHei", sans-serif;
|
|
31
|
+
line-height: 1.7;
|
|
32
|
+
}
|
|
33
|
+
main {
|
|
34
|
+
width: min(100%, 640px);
|
|
35
|
+
padding: clamp(24px, 6vw, 48px);
|
|
36
|
+
border: 1px solid #dbe3ee;
|
|
37
|
+
border-top: 4px solid #2563eb;
|
|
38
|
+
border-radius: 12px;
|
|
39
|
+
background: #fff;
|
|
40
|
+
}
|
|
41
|
+
h1 { margin: 0 0 16px; font-size: clamp(24px, 5vw, 32px); line-height: 1.4; }
|
|
42
|
+
p { margin: 0; color: #475569; font-size: 16px; }
|
|
43
|
+
</style>
|
|
44
|
+
</head>
|
|
45
|
+
<body><main><h1>$hai_download_title</h1><p>$hai_download_instruction</p></main></body>
|
|
46
|
+
</html>';
|
|
47
|
+
}
|
|
48
|
+
location @hai_spa_fallback {
|
|
49
|
+
error_page 418 = @hai_download_unavailable;
|
|
50
|
+
if ($hai_signed_download) { return 418; }
|
|
51
|
+
try_files /index.html =404;
|
|
52
|
+
}
|
|
@@ -23,7 +23,7 @@ description: "接入或排查 @h-ai/api-client typed API、登录 Token、自动
|
|
|
23
23
|
4. 同步服务端与客户端的刷新、加密和错误处理;切换配置前 close,任务结束释放客户端。
|
|
24
24
|
5. 验证登录、刷新重试、失败、退出与会话恢复。
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
保留服务端错误的 `traceId`,UI 使用公开安全消息,重新翻译后用 `core.error.formatMessage` 保留编号。4xx 和可关联的服务端错误使用 `debug`。客户端自己的网络、协议或未关联的 5xx 失败使用 `error`,记录可用的传输诊断字段。具体见 [日志与错误诊断](../hai-app-create/logging.md)。
|
|
27
27
|
|
|
28
28
|
非 2xx HTTP 响应中的合法失败 HaiResult 保留服务端业务码、消息与 traceId,以真实 HTTP 状态执行脱敏。验证 409 冲突、422 输入错误、429 限流和 5xx,不只测试 HTTP 200 业务失败;UI 包装 Error 时通过 cause 保留 HaiError。
|
|
29
29
|
|
|
@@ -19,6 +19,8 @@ description: "在 hai 应用中新增、修改或修复功能,按需求复用
|
|
|
19
19
|
|
|
20
20
|
沟通、问题状态与文档/配置/截图/测试/模板/调用方同步遵循[沟通与同步维护](collaboration.md)。
|
|
21
21
|
|
|
22
|
+
生成或修改错误处理和日志时,应用 [日志与错误诊断](logging.md) 中的级别、根因与脱敏规则。
|
|
23
|
+
|
|
22
24
|
范围、验收、复用依据和证据按 [工作交接契约](../hai-spec-implement/handoff.md) 贯穿实现、测试和审查;小改动使用简短记录,文档驱动任务沿既有任务记录续跑。
|
|
23
25
|
|
|
24
26
|
业务以用户当前明确要求及其指定文档为准;模板规则、生成代码与测试只描述初始方案。需求改变角色、流程、限额或架构时,在已有授权范围内同步调整冲突实现及过期 AGENTS/skills/README,不要求把需求改回模板。具体判定见 [development.md](development.md#需求与模板的关系)。
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# 日志与错误诊断
|
|
2
|
+
|
|
3
|
+
框架模块、服务端业务代码和浏览器代码统一使用 `core.logger`。用 `core.logger.child({ module, scope })` 标记稳定的来源,英文日志消息说明发生的操作。应用与常规 CLI 操作沿用 Core 日志配置,应用可通过 `_core.yml` 的 `logging.level` 或 `HAI_CORE_LOGGING_LEVEL` 设置阈值。提供 JSON 输出的命令按其机器可读输出契约处理诊断。
|
|
4
|
+
|
|
5
|
+
## 日志级别
|
|
6
|
+
|
|
7
|
+
| 级别 | 使用场景 |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `trace` | 请求和响应摘要、循环细节等按需诊断。请求查询只记录参数数量。 |
|
|
10
|
+
| `debug` | 常规读写的安全摘要、预期的 HTTP 4xx、客户端对已带服务端追踪编号的错误进行关联。 |
|
|
11
|
+
| `info` | 初始化完成、服务就绪和有意义的低频状态变化。 |
|
|
12
|
+
| `warn` | 模块所拥有的业务操作失败、可恢复的外部故障或清理失败。 |
|
|
13
|
+
| `error` | 初始化或连接失败、影响资源状态的关闭失败、未预期异常和服务端 5xx。 |
|
|
14
|
+
| `fatal` | 进程无法继续运行的故障。 |
|
|
15
|
+
|
|
16
|
+
由能看到根因的层记录失败。上层复用错误码和追踪编号,按需要补充诊断摘要。接口和 UI 使用现有的公开错误映射与本地化提示。客户端自己的网络、协议或未处理异常需要独立诊断。操作日志的读写开关控制正常摘要,错误日志由对应级别和 Core 阈值控制。持久化审计遵循审计契约。
|
|
17
|
+
|
|
18
|
+
## 保留根因与关联信息
|
|
19
|
+
|
|
20
|
+
- 对 `HaiResult` 先判断 `success`。业务调用方应得到有区分度的错误码和消息,以及可获得的原始 `error.cause`。把后续失败单独保存在 `error.ext.cleanupError` 等既有诊断字段,保留取消原因和业务分支所需的错误码。HTTP 对外使用安全消息和追踪编号。
|
|
21
|
+
- 日志使用结构化上下文。沿用模块已有的操作名和错误码字段,并按需记录失败阶段、状态和可用的 `traceId` 或 `requestId`。上游请求编号独立记录为 `providerRequestId`。需要堆栈时保留可排查的脱敏异常链。
|
|
22
|
+
- 用明确的字段白名单构造日志。省略密码、token、密钥、连接凭据、完整配置、请求正文和查询值、联系方式、消息主题和正文、签名 URL、对象或文件内容、SQL 绑定值、文档、向量和过滤值。连接地址复用 `core.sanitize.sanitizeUrl`。字段脱敏不能识别自由文本里的全部私密值,外部错误正文应提取有界的错误码、状态和请求编号。
|
|
23
|
+
|
|
24
|
+
## Storage
|
|
25
|
+
|
|
26
|
+
`storage` 默认开启写操作摘要,读操作按需开启。常规操作使用 `debug`,上传、下载、删除等失败返回业务错误并记录 `warn`,初始化、连接或关闭失败记录 `error`。日志省略对象键、签名地址和内容。使用 `HAI_CORE_LOGGING_LEVEL`,旧的 `HAI_STORAGE_OPERATIONLOG_LEVEL` 与 `operationLog.level` 已移除。
|
|
27
|
+
|
|
28
|
+
流式上传保留源读取错误、取消原因和 S3 原始写入错误。分片清理也失败时单独保留清理错误,并记录可用的 S3 操作名和请求编号。条件写入冲突按 `ALREADY_EXISTS` 处理。使用 Storage 时查阅项目中 `hai-storage` 的配置与错误说明。
|
|
29
|
+
|
|
30
|
+
## 验证
|
|
31
|
+
|
|
32
|
+
修改日志或错误处理时,从实际公共入口验证受影响的成功和失败分支。按场景核对日志级别、原始原因、关联编号和脱敏字段。涉及上传、取消或回滚的双重失败,用受控故障验证业务结果和日志均保留首次错误与清理诊断。可使用 `core.logger.observe` 捕获结构化记录。
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
- 服务端校验输入、身份、权限及资源/租户归属;SQL 值参数化、标识符白名单、文件路径防逃逸。不把隐藏按钮当授权,不执行不可信 HTML/AI 内容。
|
|
16
16
|
- 密钥不进入 PUBLIC_/VITE_、浏览器或日志,敏感 token 不写 localStorage;沿现有 Cookie/内存或原生安全存储流程。用户提示准确且脱敏,日志保留英文操作上下文及可关联错误,未知提交不自动重放。
|
|
17
17
|
- 禁止 any、无说明的 as unknown as、console.log、硬编码密钥。注释中文,结构化日志英文且脱敏,用户文本沿现有 i18n 同步全部 locale。
|
|
18
|
+
- 实现或审查错误处理和日志时,核对 [日志与错误诊断](logging.md) 的业务返回、日志级别、字段白名单与追踪编号。
|
|
18
19
|
|
|
19
20
|
## 代码注释与示例
|
|
20
21
|
|
|
@@ -228,9 +228,7 @@ export async function listArticles(params: ListParams): Promise<HaiResult<Pagina
|
|
|
228
228
|
### 服务层规则
|
|
229
229
|
|
|
230
230
|
- 应用领域操作沿现有契约返回 `HaiResult<T>`;纯 getter、工具、工厂与流按实际签名,不统一改造
|
|
231
|
-
-
|
|
232
|
-
- 读操作仅 `debug` 日志
|
|
233
|
-
- 禁止 `console.log`,使用 `core.logger`
|
|
231
|
+
- 需要记录服务层操作时,使用 `core.logger` 和 [日志与错误诊断](logging.md) 约定的安全摘要。传播框架模块的 `HaiResult` 错误时保留原因和关联信息。
|
|
234
232
|
- 服务层不处理 HTTP 响应格式,只返回 HaiResult
|
|
235
233
|
|
|
236
234
|
## 创建数据模型
|
|
@@ -357,7 +355,7 @@ core.init() → crypto.init() → reldb.init() → cache.init() → iam.init()
|
|
|
357
355
|
- [ ] 页面使用 Svelte 5 Runes 语法
|
|
358
356
|
- [ ] API 端点有权限守卫与输入校验
|
|
359
357
|
- [ ] 服务层和调用方遵循实际返回/抛错/流契约,不能以 HTTP 成功替代业务状态成功
|
|
360
|
-
- [ ]
|
|
358
|
+
- [ ] 已验证 [日志与错误诊断](logging.md) 的日志级别、失败原因、关联编号和脱敏字段
|
|
361
359
|
- [ ] 禁止 `console.log`、`any`、硬编码密钥
|
|
362
360
|
- [ ] 用户可见文本走 i18n
|
|
363
361
|
- [ ] 涉及容器交付时,镜像启动及配置/环境变量/数据目录行为已验证
|
|
@@ -60,7 +60,7 @@ typecheck/lint 不能证明越权、租户隔离、事务、错误状态或资
|
|
|
60
60
|
|
|
61
61
|
- 禁止 `any`、无说明的 `as unknown as T`、`console.log`、硬编码密钥;外部 `unknown` 先校验/缩窄。必要第三方断言有真实依据。
|
|
62
62
|
- 遵循当前 ESLint、TypeScript、目录与命名规则,函数返回类型按真实契约标注;不把所有返回类型都强制成 HaiResult。
|
|
63
|
-
-
|
|
63
|
+
- 注释中文,结构化日志英文。按 [日志与错误诊断](../hai-app-create/logging.md) 核对级别、字段白名单、原始原因和重复记录。
|
|
64
64
|
- 用户可见文案沿现有 i18n 入口,同步中英日文;包括错误、空态、降级、校验和状态文案。禁止手改 Paraglide 生成文件;框架组件内置翻译沿公开 Props 使用。
|
|
65
65
|
- 业务逻辑不塞入 UI/hook;优先 early return、按职责拆分复杂函数。遵守实际 lint 的复杂度/长度限制,不为了数字拆出无意义转发链。
|
|
66
66
|
- 循环串行/并发按依赖、事务、限流与资源限制选择;列表分页/流式处理,避免热路径同步 I/O、重复连接和无界并发。
|
|
@@ -192,7 +192,7 @@ logger.info('Module initialized')
|
|
|
192
192
|
|
|
193
193
|
// 创建携带固定上下文的子 logger(自动合并到每条日志)
|
|
194
194
|
const reqLogger = core.logger.child({ requestId: 'req-001' })
|
|
195
|
-
reqLogger.
|
|
195
|
+
reqLogger.debug('Request started') // 日志中自动包含 requestId
|
|
196
196
|
|
|
197
197
|
// 配置输出格式和级别
|
|
198
198
|
core.logger.configure({
|
|
@@ -204,16 +204,7 @@ core.logger.setLevel('debug')
|
|
|
204
204
|
const level = core.logger.getLevel() // 'debug'
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
| 级别 | 适用场景 |
|
|
210
|
-
| ------- | ---------------------------------- |
|
|
211
|
-
| `trace` | 循环内详细调试数据 |
|
|
212
|
-
| `debug` | 函数进入、参数概要、读操作 |
|
|
213
|
-
| `info` | 业务事件(初始化完成、写操作成功) |
|
|
214
|
-
| `warn` | 异常但可恢复(校验失败、重试) |
|
|
215
|
-
| `error` | 操作失败(需人工排查) |
|
|
216
|
-
| `fatal` | 致命错误(服务无法继续) |
|
|
207
|
+
日志级别、业务错误处理和字段选择见 [日志与错误诊断](../hai-app-create/logging.md)。
|
|
217
208
|
|
|
218
209
|
### 国际化 — `core.i18n`
|
|
219
210
|
|
|
@@ -206,8 +206,8 @@ const sharedServer = crypto.transport.createServer({
|
|
|
206
206
|
|
|
207
207
|
使用流程:
|
|
208
208
|
1. 先 `await crypto.init()`。
|
|
209
|
-
2. 服务端显式传入受管 serverKeyRing 和共享 keyStore
|
|
210
|
-
3. 客户端 `createClient({ keyExchangeUrl })`
|
|
209
|
+
2. 服务端显式传入受管 `serverKeyRing` 和共享 `keyStore`。协商响应包含 `serverKeyId`、`serverPublicKey`、`clientId`、`maxPlaintextBytes` 和可选的 `clientKeyTtlSeconds`。自定义适配器读取 `manager.clientKeyTtlSeconds` 填充登记有效期。
|
|
210
|
+
3. 客户端 `createClient({ keyExchangeUrl })` 后,首次使用或登记临近到期时自动协商。并发请求共享握手,协商完成后再发送业务请求。
|
|
211
211
|
4. 所有请求均发送 v2 认证封装;包括 GET/HEAD 和无 input POST,不能只附带 clientId。
|
|
212
212
|
5. 自定义适配器先 await authenticateTransportRequest(manager, request),再用 manager.encryptResponse(verified.data.context, data, status) 关联响应。
|
|
213
213
|
6. 客户端收到 `X-Encrypted: true` 的响应后自动解密;`destroy()` 可清空当前会话。
|
|
@@ -98,6 +98,8 @@ Serv/SvelteKit 后端的策略快照、只读挂载、环境覆盖、代理信
|
|
|
98
98
|
|
|
99
99
|
## 自建对象存储直连
|
|
100
100
|
|
|
101
|
+
签名下载误入静态网站回退或在 SSR/API 网关收到应用 404 时,Nginx 返回独立的 404 提示页。重复失败时,检查生效的 `HAI_STORAGE_PUBLICENDPOINT` 和实际代理路由,再签发新链接验证。升级已有代理规则使用完整交付包,独立静态 Web 镜像从更新后的模板重建。
|
|
102
|
+
|
|
101
103
|
S3 的内部 endpoint 与预签名 publicEndpoint 分开;后者无默认,填用户可访问的 HTTP(S) origin,不含桶名或网站目录。全栈 Web Nginx 及 SSR/API gateway 将实际桶路径原样代理至 storage,不经过 Serv,保留签名 Host/URI/query,关闭对象缓冲和签名日志。桶与网站/API 路径不能重叠;外层反向代理也须转发桶路径,不能把网站 base 加到签名 URL。跨源 CORS 在 S3 配置,私有桶保持签名授权;外部 S3 不生成本地路由,Local 不开放目录。
|
|
102
104
|
|
|
103
105
|
自建保留 bucket/region/prefix/publicEndpoint/publicUrl/operationLog。增加 gateway 或改变这些访问配置需全量基线,增量摘要不一致在更新前拒绝;选中范围不改变完整拓扑规划。应用/Storage 增量刷新保留代理 DNS,恢复使用旧发布拓扑。验证真实 S3+Nginx 大文件、Range、PUT、匿名/篡改/过期拒绝,并核对外层日志和回滚;不能用只检查生成字符串代替网络验证。
|
|
@@ -28,7 +28,7 @@ transport 仅支持 v2:SM2 发送方签名、独立密钥的 Encrypt-then-HMAC
|
|
|
28
28
|
3. 区分返回 HaiResult 的业务操作与抛 Response/redirect/error 的框架控制流,不吞掉控制流。
|
|
29
29
|
4. 对齐 Cookie/CSRF/transport 与服务端配置,验证匿名、登录、权限拒绝和表单失败。
|
|
30
30
|
|
|
31
|
-
默认请求日志支持 prerender
|
|
31
|
+
默认请求日志支持 prerender。查询从独立 `new URL(event.request.url)` 统计参数数量,路径保留 `event.url.pathname`。JSON 正文日志默认关闭,显式启用时从请求副本读取并脱敏。页面业务确实依赖查询时按 SvelteKit 的动态路由条件处理。
|
|
32
32
|
|
|
33
33
|
Kit 自动请求审计与 Serv 一样,仅在请求时发现 audit.isInitialized 才写入;未选 Audit 的站点不因默认 handle 产生未初始化错误。选择 Audit 时检查 init 结果并失败停止启动;显式业务审计仍遵守初始化和事务合同,已就绪模块写入失败必须保留诊断,不能当作可选模块静默跳过。handle 创建早于模块初始化时不能在装配阶段把审计永久禁用。
|
|
34
34
|
|
|
@@ -38,7 +38,7 @@ Kit 自动请求审计与 Serv 一样,仅在请求时发现 audit.isInitialize
|
|
|
38
38
|
|
|
39
39
|
业务容量统一配置 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。 通过 _kit.yml 的 transport.maxPlaintextBytes 或对应 HAI_*_TRANSPORT_MAXPLAINTEXTBYTES 配置并转发到服务端 transport;重建正文保留 signal 并删除旧长度/编码头。
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
HTTP/UI 边界用 `core.error.toPublic` 公开本地化安全消息和 `error.traceId`,重新翻译后用 `core.error.formatMessage` 保留编号。ToastContainer 可展开查看和复制。HTTP 4xx 记录 `debug`,5xx 记录 `error` 并保留安全的服务端诊断。日志字段和跨层关联按 [日志与错误诊断](../hai-app-create/logging.md)。
|
|
42
42
|
|
|
43
43
|
## 按需参考
|
|
44
44
|
|
|
@@ -42,7 +42,7 @@ export const handle: Handle = haiHandle
|
|
|
42
42
|
|
|
43
43
|
### 2. SvelteKit API endpoint
|
|
44
44
|
|
|
45
|
-
业务失败用 `kit.response.fromResult/fromError`,保留安全字段错误、显式 `publicExt` 和 HTTP
|
|
45
|
+
业务失败用 `kit.response.fromResult/fromError`,保留安全字段错误、显式 `publicExt` 和 HTTP 状态。4xx 使用 `debug` 记录错误码、状态和追踪编号,5xx 使用 `error` 记录服务端异常诊断。请求日志仅记录查询参数数量。
|
|
46
46
|
|
|
47
47
|
```ts
|
|
48
48
|
import { kit } from '@h-ai/kit'
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> `@h-ai/reldb` 提供统一的数据库操作接口,支持 SQLite、PostgreSQL、MySQL,包含 DDL、SQL、CRUD 抽象、事务与分页。
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
派生 `BaseReldbCrudRepository` 的自定义 SQL 方法先检查 `await this.ensureReady()`;构造函数启动自动建表不等于仓库就绪,服务 init 必须等待候选仓库的就绪入口再发布。PostgreSQL 自动提交的单条 `CREATE TABLE/INDEX IF NOT EXISTS` 仅对 `23505/pg_class_relname_nsp_index`(建表还包括 `pg_type_typname_nsp_index
|
|
8
|
+
派生 `BaseReldbCrudRepository` 的自定义 SQL 方法先检查 `await this.ensureReady()`;构造函数启动自动建表不等于仓库就绪,服务 init 必须等待候选仓库的就绪入口再发布。PostgreSQL 自动提交的单条 `CREATE TABLE/INDEX IF NOT EXISTS` 仅对 `23505/pg_class_relname_nsp_index`(建表还包括 `pg_type_typname_nsp_index`)目录竞争,以及建表时 `42710/heap_create_with_catalog`、`42710/TypeCreate` 或 `42P07/heap_create_with_catalog` 的目录竞争重执行一次。DDL 和 SQL 入口均保留重试后的错误。事务、业务唯一约束及其他错误不自动重试。初始化连接探测仅对临时 DNS 错误 `EAI_AGAIN` 最多尝试三次,间隔 250/500 ms;不重放业务 SQL。
|
|
9
9
|
|
|
10
10
|
## 运行环境
|
|
11
11
|
|
|
@@ -35,7 +35,7 @@ transport 仅支持 v2:SM2 发送方签名、独立密钥的 Encrypt-then-HMAC
|
|
|
35
35
|
|
|
36
36
|
业务容量统一配置 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。 通过 _serv.yml 的 transport.maxPlaintextBytes 或对应 HAI_*_TRANSPORT_MAXPLAINTEXTBYTES 配置并转发到服务端 transport;重建正文保留 signal 并删除旧长度/编码头。
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Procedure 业务失败按公开错误中的归一化 HTTP 状态分类。4xx 以 `debug` 记录错误码和追踪编号,5xx 或未捕获异常由服务端以 `error` 保留脱敏诊断。对外提示由 `core.error.toPublic` 生成。日志字段与跨层关联按 [日志与错误诊断](../hai-app-create/logging.md)。
|
|
39
39
|
|
|
40
40
|
## 按需参考
|
|
41
41
|
|
|
@@ -25,6 +25,7 @@ description: "实现本地/S3 文件与目录操作、流式读写、checksum
|
|
|
25
25
|
5. 批量删除核对逐项进度,S3 每批最多 1000 项;HTTP 200 不能代替成功判断。unknown 结果先核对业务状态,避免重删并发新对象;dir.delete 不保证隔离并发写入或清除 S3 历史版本。
|
|
26
26
|
6. 自建 Compose 的桶路径由 Web Nginx 或 SSR/API gateway 直达 storage,下载/Range 不经过 Serv,存储端口和控制台不公开。publicEndpoint 可含入口前缀,Nginx 用原始 request_uri 去前缀且保留编码、Host、签名查询,外层代理不能再剥离;入口可在网站目录内,拒绝 API/资源/健康冲突。新增网关、变更桶/公开地址需全量基线,增量及回滚保持原配置。外部 S3 不生成本地路由,Local 不开放目录。验证大文件、Range、过期/篡改/匿名拒绝、根/前缀路径和增量代理 DNS 刷新;签名 URL 不进入日志或截图。
|
|
27
27
|
7. 同源对象可能包含不可信 HTML;默认代理返回 CSP sandbox/default-src none、nosniff、no-referrer、private/no-store,不用于执行网站脚本。外部 S3/CDN 须配置等价策略。自建 bucket/region 为空时由部署补 hai/us-east-1,不能误写成 Storage Schema 默认值。
|
|
28
|
+
8. 写操作默认以 `debug` 记录,业务操作失败返回原错误并记录 `warn`,初始化、连接及关闭失败记录 `error`。正常日志由 Core 级别过滤。调用方按 [日志与错误诊断](../hai-app-create/logging.md) 保留原因和关联编号。
|
|
28
29
|
|
|
29
30
|
## 按需参考
|
|
30
31
|
|
|
@@ -35,12 +35,14 @@ root: ./data/storage
|
|
|
35
35
|
# createBucket: ${HAI_STORAGE_CREATEBUCKET:false}
|
|
36
36
|
# forcePathStyle: false
|
|
37
37
|
# prefix: "${HAI_STORAGE_PREFIX:}"
|
|
38
|
+
# multipart:
|
|
39
|
+
# partSizeBytes: ${HAI_STORAGE_MULTIPART_PARTSIZEBYTES:5242880}
|
|
40
|
+
# queueSize: ${HAI_STORAGE_MULTIPART_QUEUESIZE:2}
|
|
38
41
|
# publicUrl: ''
|
|
39
42
|
operationLog:
|
|
40
43
|
read: false # file.get/head/exists, dir.list, presign.getUrl/publicUrl
|
|
41
|
-
write:
|
|
44
|
+
write: true # file.put/delete/deleteMany/copy, dir.delete, presign.putUrl
|
|
42
45
|
maxLength: 1000
|
|
43
|
-
level: debug # info | debug | trace
|
|
44
46
|
```
|
|
45
47
|
|
|
46
48
|
约定环境变量优先于 YAML,例如 `HAI_STORAGE_ROOT`、
|
|
@@ -52,7 +54,15 @@ MinIO、RustFS 使用同一个 S3 Provider:配置 `type: s3`、S3 API `endpoin
|
|
|
52
54
|
|
|
53
55
|
使用 hai-deploy 的默认自建 S3 配置时,可通过 `hai.json` 的 `deploy.container.s3Engine`(`HAI_DEPLOY_CONTAINER_S3ENGINE`,`rustfs | minio`)选择实现,默认 RustFS。运行环境启用 `HAI_STORAGE_CREATEBUCKET=true` 后由应用初始化 storage 时建桶;部署不再生成独立初始化服务或脚本。自定义外部 S3 默认不建桶,可按凭据权限显式启用。
|
|
54
56
|
|
|
55
|
-
`operationLog`
|
|
57
|
+
`operationLog` 默认记录写操作,读操作需显式开启。操作记录固定为 `debug`,由 Core 日志级别过滤。业务失败返回原错误并记录一次 `warn`,初始化、连接和关闭失败为 `error`。`maxLength` 限制安全摘要的字符数,0 省略摘要。签名直传助手在浏览器记录失败,日志不包含对象键、签名 URL 或文件内容。升级时移除 `operationLog.level` 与 `HAI_STORAGE_OPERATIONLOG_LEVEL`,通过 `HAI_CORE_LOGGING_LEVEL` 设置全局阈值。
|
|
58
|
+
|
|
59
|
+
S3 服务端流式上传使用 `multipart.partSizeBytes` 和 `multipart.queueSize`,默认 5 MiB 和 2 片。大小为 5 MiB 至 5 GiB 的整数,队列大小为正整数。上述两个环境变量在初始化时覆盖相应字段。每个活跃上传的主要缓冲预算约为片大小乘以并发数。
|
|
60
|
+
|
|
61
|
+
S3 流式上传用 `error.cause` 获取首次失败,`error.ext?.s3Operation` 查看失败的 S3 操作。若分片清理也失败,从 `error.ext?.cleanupError` 获取清理错误。告警包含可取得的服务端请求编号。
|
|
62
|
+
|
|
63
|
+
若 `UploadPart` 返回成功但缺少 `ETag`,用 `MissingETag`、分片编号及请求编号定位存储端和网关的响应。
|
|
64
|
+
|
|
65
|
+
处理 `storage.file.put()` 失败时用 `error.code` 分支,底层原因可用时从 `error.cause` 读取。`ifNoneMatch: '*'` 的目标冲突为 `ALREADY_EXISTS`,文件或输入流读取失败为 `UPLOAD_FAILED`,取消保留 `AbortSignal.reason`。告警记录原因摘要、底层错误码及可用的 HTTP 状态。
|
|
56
66
|
|
|
57
67
|
### 2. 初始化与关闭
|
|
58
68
|
|
|
@@ -58,7 +58,7 @@ operationLog:
|
|
|
58
58
|
约定环境变量优先于 YAML,例如 `HAI_VECDB_URL`、
|
|
59
59
|
`HAI_VECDB_APIKEY`、`HAI_VECDB_OPERATIONLOG_LEVEL`。
|
|
60
60
|
|
|
61
|
-
`operationLog` 在集合/向量操作进入真实 Provider
|
|
61
|
+
`operationLog` 在集合/向量操作进入真实 Provider 前输出日志。日志包含操作类型以及条数、维度、topK、是否有过滤条件等摘要。`maxLength` 限制摘要字符数,0 省略摘要。`level` 默认 `debug`。
|
|
62
62
|
|
|
63
63
|
### 2. 初始化与关闭
|
|
64
64
|
|