@tier0/sdk-v2 0.6.2 → 0.7.2

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 +26 -17
  2. package/dist/cjs/capabilities.d.ts +20 -4
  3. package/dist/cjs/capabilities.js +66 -6
  4. package/dist/cjs/capabilities.js.map +1 -1
  5. package/dist/cjs/client.d.ts +9 -7
  6. package/dist/cjs/client.js +0 -2
  7. package/dist/cjs/client.js.map +1 -1
  8. package/dist/cjs/cloud-transport.d.ts +3 -2
  9. package/dist/cjs/cloud-transport.js +8 -7
  10. package/dist/cjs/cloud-transport.js.map +1 -1
  11. package/dist/cjs/index.d.ts +0 -1
  12. package/dist/cjs/index.js +0 -1
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/openapi/api.generated.d.ts +9 -5
  15. package/dist/cjs/openapi/codecs.generated.d.ts +943 -684
  16. package/dist/cjs/openapi/codecs.generated.js +1 -1
  17. package/dist/cjs/openapi/codecs.generated.js.map +1 -1
  18. package/dist/cjs/openapi/types.generated.d.ts +638 -508
  19. package/dist/cjs/openapi/types.generated.js.map +1 -1
  20. package/dist/cjs/uns-v2/client.js +2 -2
  21. package/dist/cjs/uns-v2/client.js.map +1 -1
  22. package/dist/cjs/uns-v2/generated.d.ts +190 -274
  23. package/dist/cjs/uns-v2/generated.js +24 -48
  24. package/dist/cjs/uns-v2/generated.js.map +1 -1
  25. package/dist/esm/capabilities.d.ts +20 -4
  26. package/dist/esm/capabilities.js +66 -6
  27. package/dist/esm/capabilities.js.map +1 -1
  28. package/dist/esm/client.d.ts +9 -7
  29. package/dist/esm/client.js +0 -2
  30. package/dist/esm/client.js.map +1 -1
  31. package/dist/esm/cloud-transport.d.ts +3 -2
  32. package/dist/esm/cloud-transport.js +8 -7
  33. package/dist/esm/cloud-transport.js.map +1 -1
  34. package/dist/esm/index.d.ts +0 -1
  35. package/dist/esm/index.js +0 -1
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/openapi/api.generated.d.ts +9 -5
  38. package/dist/esm/openapi/codecs.generated.d.ts +943 -684
  39. package/dist/esm/openapi/codecs.generated.js +1 -1
  40. package/dist/esm/openapi/codecs.generated.js.map +1 -1
  41. package/dist/esm/openapi/types.generated.d.ts +638 -508
  42. package/dist/esm/openapi/types.generated.js.map +1 -1
  43. package/dist/esm/uns-v2/client.js +2 -2
  44. package/dist/esm/uns-v2/client.js.map +1 -1
  45. package/dist/esm/uns-v2/generated.d.ts +190 -274
  46. package/dist/esm/uns-v2/generated.js +24 -48
  47. package/dist/esm/uns-v2/generated.js.map +1 -1
  48. package/package.json +5 -8
  49. package/skills/tier0-sdk-v2/SKILL.md +8 -7
  50. package/skills/tier0-sdk-v2/tier0-sdk-v2-agent/SKILL.md +0 -2
  51. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/SKILL.md +2 -0
  52. package/skills/tier0-sdk-v2/tier0-sdk-v2-files/SKILL.md +1 -1
  53. package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/delete.md +1 -1
  54. package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/download.md +1 -1
  55. package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/multipart.md +1 -1
  56. package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/upload.md +2 -2
  57. package/skills/tier0-sdk-v2/tier0-sdk-v2-members/SKILL.md +1 -1
  58. package/skills/tier0-sdk-v2/tier0-sdk-v2-members/references/platform-members.md +1 -1
  59. package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/SKILL.md +2 -2
  60. package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/references/quickstart.md +3 -3
  61. package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/SKILL.md +2 -2
  62. package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/references/send.md +2 -2
  63. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md +3 -3
  64. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/create.md +11 -7
  65. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/protocols.md +4 -4
  66. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/read.md +1 -1
  67. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md +7 -7
  68. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/create.md +15 -12
  69. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/delete.md +9 -16
  70. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/deploy.md +20 -18
  71. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/http-server.md +2 -2
  72. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/lifecycle.md +2 -0
  73. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/read.md +4 -0
  74. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/update.md +5 -7
  75. package/skills/tier0-sdk-v2/tier0-sdk-v2-system/SKILL.md +7 -4
  76. package/skills/tier0-sdk-v2/tier0-sdk-v2-system/references/info.md +0 -2
  77. package/skills/tier0-sdk-v2/tier0-sdk-v2-system/references/whoami.md +1 -1
  78. package/dist/cjs/controls.d.ts +0 -105
  79. package/dist/cjs/controls.js +0 -172
  80. package/dist/cjs/controls.js.map +0 -1
  81. package/dist/esm/controls.d.ts +0 -105
  82. package/dist/esm/controls.js +0 -166
  83. package/dist/esm/controls.js.map +0 -1
  84. package/docs/acceptance-2026-10-22.md +0 -90
  85. package/skills/tier0-sdk-v2/tier0-sdk-v2-controls/SKILL.md +0 -65
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tier0/sdk-v2",
3
- "version": "0.6.2",
3
+ "version": "0.7.2",
4
4
  "description": "Tier0 Cloud new-architecture SDK for TypeScript and JavaScript",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,7 +22,6 @@
22
22
  "dist",
23
23
  "skills",
24
24
  "README.md",
25
- "docs/acceptance-2026-10-22.md",
26
25
  "LICENSE",
27
26
  "NOTICE.md"
28
27
  ],
@@ -156,7 +155,7 @@
156
155
  "scripts": {
157
156
  "sync:contracts": "node scripts/sync-contracts.mjs",
158
157
  "generate": "node scripts/generate-openapi.mjs && node scripts/generate-uns-v2.mjs",
159
- "check:contracts": "node scripts/check-contracts.mjs && node --test scripts/retired-stream-probe.test.mjs scripts/retired-http-push.test.mjs scripts/sync-contracts.test.mjs scripts/live-program-contract.test.mjs scripts/sync-http-run-observations.test.mjs && node scripts/generate-openapi.mjs --check && node scripts/generate-uns-v2.mjs --check",
158
+ "check:contracts": "node scripts/check-contracts.mjs && node --test scripts/retired-stream-probe.test.mjs scripts/retired-http-push.test.mjs scripts/retired-controls.test.mjs scripts/retired-public-labels.test.mjs scripts/platform-schema-projection.test.mjs scripts/data-capability-vector.test.mjs scripts/sync-contracts.test.mjs scripts/live-program-contract.test.mjs scripts/sync-http-run-observations.test.mjs && node scripts/generate-openapi.mjs --check && node scripts/generate-uns-v2.mjs --check",
160
159
  "check:skills": "node scripts/check-skills.mjs && node scripts/check-skill-examples.mjs",
161
160
  "typecheck": "tsc --noEmit && tsc -p tsconfig.tests.json",
162
161
  "build": "node scripts/build.mjs",
@@ -200,7 +199,9 @@
200
199
  "vitest": "^4.1.7",
201
200
  "esbuild": "^0.25.0",
202
201
  "yaml": "^2.8.0",
203
- "zod": "^4.0.0"
202
+ "zod": "^4.0.0",
203
+ "ajv": "^8.20.0",
204
+ "ajv-formats": "^3.0.1"
204
205
  },
205
206
  "agents": {
206
207
  "skills": [
@@ -240,10 +241,6 @@
240
241
  "name": "tier0-sdk-v2-system",
241
242
  "path": "./skills/tier0-sdk-v2/tier0-sdk-v2-system"
242
243
  },
243
- {
244
- "name": "tier0-sdk-v2-controls",
245
- "path": "./skills/tier0-sdk-v2/tier0-sdk-v2-controls"
246
- },
247
244
  {
248
245
  "name": "tier0-sdk-v2-agent",
249
246
  "path": "./skills/tier0-sdk-v2/tier0-sdk-v2-agent"
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: tier0-sdk-v2
3
- description: 使用 @tier0/sdk-v2 开发或迁移 Tier0 云端 TypeScript/JavaScript 应用:Source 数据源、Stream 处理程序、UNS 集合与记录、App 自有数据(@tier0/sdk-v2/data)、通知、文件存储、MQTT、成员、系统身份与能力、Controls 和 Agent,按任务进入对应子 Skill,并处理配置、身份和框架集成。
3
+ description: 使用 @tier0/sdk-v2 开发或迁移 Tier0 云端 TypeScript/JavaScript 应用:Source 数据源、Stream 处理程序、UNS 集合与记录、App 自有数据(@tier0/sdk-v2/data)、通知、文件存储、MQTT、成员、系统身份与能力和 Agent,按任务进入对应子 Skill,并处理配置、身份和框架集成。
4
4
  ---
5
5
 
6
6
  # Tier0 SDK v2 应用集成
7
7
 
8
- 面向应用代码编写;运行时为 Node.js 20.19+。独立包 `@tier0/sdk-v2` 的版本以 package.json 为准(UNS v2 契约 5.0.0),是否可从 npm 安装须检查实际发布状态;未发布时安装仓库构建的 tarball。新参数还需要目标环境部署对应后端,不能只凭 SDK 方法存在判断可用。不要改回旧包或旧 Flow API。
8
+ 面向应用代码编写;运行时为 Node.js 20.19+。独立包 `@tier0/sdk-v2` 的版本以 package.json 为准(UNS v2 契约 5.0.0),是否可从 npm 安装须检查实际发布状态;未发布时安装仓库构建的 tarball。新参数还需要目标环境部署对应后端,不能只凭 SDK 方法存在判断可用。
9
9
 
10
10
  ## 选择业务入口
11
11
 
@@ -20,7 +20,6 @@ description: 使用 @tier0/sdk-v2 开发或迁移 Tier0 云端 TypeScript/JavaSc
20
20
  | 附件、头像、导入导出、生成报告 | `client.files` | [文件](tier0-sdk-v2-files/SKILL.md) |
21
21
  | 实时主题订阅/发布 | `@tier0/sdk-v2/mq`、`client.mqttAuth` | [MQTT](tier0-sdk-v2-mq/SKILL.md) |
22
22
  | Workspace 收件人/成员检索、App 可用成员 | `client.members` | [成员](tier0-sdk-v2-members/SKILL.md) |
23
- | 调用已发布的 Control | `client.controls` | [Controls](tier0-sdk-v2-controls/SKILL.md) |
24
23
  | Agent 作业、运行、分析结果和卡片 | `client.agent` | [Agent](tier0-sdk-v2-agent/SKILL.md) |
25
24
 
26
25
  每个领域 Skill 可单独使用,无需先加载本文件。Source → Stream → UNS 是接入、处理与数据存储三个领域;不是要求每个数据读取场景都创建一套流水线。通知和系统能力独立于这条链路。
@@ -48,7 +47,7 @@ export async function inspectConnection() {
48
47
  | Source、Stream、UNS | 完整 `{ code, msg, requestId, data }` | `UnsV2Error` / `UnsV2OutcomeUnknownError` |
49
48
  | 平台 v2,如 system、members、agent、mqttAuth | 解包后的 `data` | `ApiError` / `TransportError` |
50
49
  | notifications | 直接对象,如 `messageId`、`status` | `ApiError` |
51
- | controls、capabilities | 专属响应对象 | `ControlError` / `CapabilityError` |
50
+ | capabilities | 专属响应对象 | `CapabilityError` |
52
51
 
53
52
  方法存在不等于目标环境已部署或当前 Key 有权限。整数可能为 `bigint`;UNS 任意 JSON 中还可能含 `UnsV2RawNumber`。不要将标识符强制转为 Number;给浏览器返回数据时显式定义精确数字的序列化格式。
54
53
 
@@ -60,9 +59,11 @@ export async function inspectConnection() {
60
59
  - `client.uns.sourceDocumentGet(body)` → `client.source.documents.get(body)`。
61
60
  - `client.uns.streamProgramDeploy(body)` → `client.stream.programs.deploy(body)`。
62
61
  - `client.uns.streamDocumentValidate(body)` → `client.stream.documents.validate(body)`。
63
- - `client.uns.recordFind(body)` 保持不变;Control 使用 `client.controls.use({ code })`。
64
- - 低层 `createUnsV2Client` 保留完整生成契约,供契约工具使用;业务主入口不再把 Source/Stream/Control 混入 `client.uns`。
62
+ - `client.uns.recordFind(body)` 保持不变。
63
+ - 低层 `createUnsV2Client` 保留完整生成契约,供契约工具使用;业务主入口不再把 Source/Stream 管理混入 `client.uns`。
65
64
 
66
65
  React/Vue 示例与验签见 [集成参考](references/integration.md)。完成接入时验证目标入口、真实身份、响应解包和错误分支;SDK 本地测试通过不代表环境联调完成。
67
66
 
68
- 公开 HTTP 入口统一为 `/openapi/v2`。旧的重复操作已退役,不生成兼容调用或回退。Source 配置用 documents.*,Stream 草稿用 documents.*、发布用 programs.deploy;App 数据层仍提供 insertMany/findOneAnd*/distinct 等便捷方法。历史旧写结果未知时先核对业务状态,不能转换路由后盲目重放。
67
+ Stream 请求与消息交互由独立包 `@tier0/sdk` 的 `client.streams.requests` / `client.streams.messages` 提供;本包负责数据访问和 Source/Stream 管理,不重复实现交互 API。Scaffold 分别接入这两个包,不能将本包的 `client.stream` 管理接口当作运行时请求入口。
68
+
69
+ 本包公开 HTTP 入口统一为 `/openapi/v2`。旧的重复操作已退役,不生成兼容调用或回退。Source 配置用 documents.*,Stream 草稿用 documents.*、发布用 programs.deploy;App 数据层仍提供 insertMany/findOneAnd*/distinct 等便捷方法。历史旧写结果未知时先核对业务状态,不能转换路由后盲目重放。
@@ -69,5 +69,3 @@ result.create 的 operationId 由调用方持有;保存超时后可用 `result
69
69
  cards.update 要带读取时的完整 expectedCardSpec;library.update 要带完整 expectedItem 快照。409 表示内容已变化,应重新读取并合并用户意图,不能自动覆盖。具体示例见 [结果与卡片编辑](references/results.md)。
70
70
 
71
71
  结果附件/图片使用 [文件 Skill](../tier0-sdk-v2-files/SKILL.md) 的持久化 filePath,不保存签名 URL 作为长期资源。失败保留 ApiError.status/code/errorCode;写入 outcomeUnknown 时先查询对应资源,不自动重发。
72
-
73
- 旧 Namespace 节点的语义索引和 path 关系接口未纳入 v2,不再提供 nodes/relations 方法。
@@ -21,6 +21,8 @@ description: 使用 @tier0/sdk-v2/data 在 App 服务端声明并读写本 App
21
21
 
22
22
  ## 最小用法
23
23
 
24
+ 新 App 没有集合时是正常空态:`uns.dataAppContext({})` 返回 `dataState: "uninitialized"` 和空集合,不创建任何数据。无需先调用 context 或手工激活数据策略;声明真实业务集合后,第一次数据访问会自动初始化。`dataState: "ready"` 也不代表可访问整个工作空间,仍以返回的集合授权为准。引用已有 WMS 等集合需要明确共享授权,不能创建同名空集合代替。管理员停用返回 `FORBIDDEN`、reason `APP_DATA_POLICY_DISABLED`,不得自动恢复。
25
+
24
26
  ```ts
25
27
  import { z } from 'zod';
26
28
  import { createDataClient } from '@tier0/sdk-v2/data';
@@ -15,7 +15,7 @@ description: 使用 @tier0/sdk-v2 实现 Tier0 应用附件、头像、导入导
15
15
  | 服务端转发、浏览器保存附件 | [下载](references/download.md) |
16
16
  | 删除对象及核验回执 | [删除](references/delete.md) |
17
17
 
18
- 沿用 v1 的业务流程,调用已适配 v2;不提供旧版自动续传/并发助手。
18
+ 文件传输使用 v2 接口;分片顺序上传,中断后由调用方核对会话状态。
19
19
 
20
20
  业务文件使用平台对象存储,数据库保存返回的 filePath。App 本地目录可用于临时处理和构建,但不能替代持久化上传。使用服务端 client.files,API Key 不下发给浏览器或对象存储。
21
21
 
@@ -17,6 +17,6 @@ export async function deleteAttachment(filePath: string, client: Tier0Client = c
17
17
  }
18
18
  ```
19
19
 
20
- 删除前明确目标及业务引用,读取/下载不附带删除。返回已解包的 {deleted};不要复制 v1 把 204/空体也无条件视为成功的逻辑。v2 要按实际回执判断。
20
+ 删除前明确目标及业务引用,读取/下载不附带删除。返回已解包的 {deleted},检查 deleted 确认结果。
21
21
 
22
22
  对象删除不提供 SDK 恢复功能。401/403 处理身份与授权;网络中断/结果未知时先对账,不把错误当“已经不存在”,不自动换身份重试。
@@ -1,6 +1,6 @@
1
1
  # 下载与应用附件保存
2
2
 
3
- v2 方法:`files.download({filePath,…}, {signal}?) → Promise<Response>`。与 v1 不同,返回值本身就是 Response,不再取 result.response。
3
+ v2 方法:`files.download({filePath,…}, {signal}?) → Promise<Response>`。返回值本身就是 Response。
4
4
 
5
5
  v2 先请求文件 URL,再匿名读取对象存储;不沿用带 Key 的重定向下载链。平台认证信息不能转发给存储。
6
6
 
@@ -37,6 +37,6 @@ export async function uploadWithProgress(
37
37
 
38
38
  成功后才持久化 filePath。中断 session 包含 fileKey、uploadId、parts(partNumber/etag)、completionAttempted;session 不是完成回执,不公开到日志或无关用户。
39
39
 
40
- v2 首版顺序上传,无自动重试、并发参数或一键续传。不要复制 v1 的 resumeMultipartUpload、multipartSession 等不存在的助手。部分 PUT 可能成功但回执丢失,不能仅凭本地 parts 判断远端完整状态。跨域存储需要暴露 ETag 响应头。
40
+ 分片顺序上传,无自动重试、并发参数或一键续传。部分 PUT 可能成功但回执丢失,不能仅凭本地 parts 判断远端完整状态。跨域存储需要暴露 ETag 响应头。
41
41
 
42
42
  completionAttempted=true 表示 complete 可能已提交,先对账最终文件,不能直接 abort 或重复 complete。明确放弃未完成会话时才调用 abort;初始化请求本身结果未知且无 session 时,保存错误信息交由平台对账,不猜 uploadId。
@@ -1,6 +1,6 @@
1
1
  # 上传并保存文件引用
2
2
 
3
- 从 v1 的 uploadFile 流程迁移,v2 使用 `client.files.upload(file, options)`;独立入口为 `createFilesClient`(@tier0/sdk-v2/files)。Node.js 20.19+。浏览器只调用应用自己的上传接口,平台 Key 留在服务端。
3
+ 使用 `client.files.upload(file, options)`;独立入口为 `createFilesClient`(@tier0/sdk-v2/files)。Node.js 20.19+。浏览器只调用应用自己的上传接口,平台 Key 留在服务端。
4
4
 
5
5
  | 参数 | 类型 | 必填 | 说明 |
6
6
  | --- | --- | --- | --- |
@@ -24,4 +24,4 @@ export async function uploadAttachment(file: File, client: Tier0Client = createC
24
24
 
25
25
  业务表持久化 filePath;临时签名 URL 不作为长期引用。文件写入和业务记录写入不是原子事务,业务保存失败时记录待清理对象,只在任务授权范围内清理。
26
26
 
27
- 文件大于 100 MiB 时自动分片;阈值不是单文件产品上限,套餐配额/文件类型限制由后端决定。需要进度时显式用 [uploadMultipart](multipart.md)。v2 没有 v1 的 options.multipart/concurrency/retry/resume 控件,不照抄旧参数。
27
+ 文件大于 100 MiB 时自动分片;阈值不是单文件产品上限,套餐配额/文件类型限制由后端决定。需要进度时显式用 [uploadMultipart](multipart.md)。
@@ -7,7 +7,7 @@ description: 使用 @tier0/sdk-v2 查询 Tier0 Workspace 成员、搜索用户
7
7
 
8
8
  参数表、成员选择和有界增量分页见 [Workspace 成员](references/platform-members.md)。v1 的项目成员接口未迁入 v2,不能用 Workspace 列表代替 App 授权名单。
9
9
 
10
- 公开入口有两个:`client.members.listWorkspace` 只用于 Workspace 级的成员选择;需要能使用某个 App 的成员时用 `client.members.listApp`。没有 project 成员迁移别名,也不在客户端推断 App 成员。使用服务端 API Key;平台授权决定可查询范围。
10
+ 公开入口有两个:`client.members.listWorkspace` 只用于 Workspace 级的成员选择;需要能使用某个 App 的成员时用 `client.members.listApp`。App 成员由服务端授权决定。使用服务端 API Key;平台授权决定可查询范围。
11
11
 
12
12
  ## 搜索与展示候选人
13
13
 
@@ -53,4 +53,4 @@ export async function* scanMembers(
53
53
 
54
54
  增量时间包含边界,按 userId/updatedAt 去重,成功完成后再保存水位;跨页没有固定快照保证。只向界面返回实际需要字段。
55
55
 
56
- v1 project-members 不迁移:v2 没有 getCurrentProjectId 或项目成员接口。Workspace 列表只用于 Workspace 级选择,不能冒充某 App 的可访问用户;需要 App 可用成员时用 `members.listApp`(见 [App 可用成员](app-members.md))。无权限时报告配置问题,不以用户手填 ID 绕过。
56
+ Workspace 列表只用于 Workspace 级选择,不能冒充某 App 的可访问用户;需要 App 可用成员时用 `members.listApp`(见 [App 可用成员](app-members.md))。无权限时报告配置问题,不以用户手填 ID 绕过。
@@ -5,7 +5,7 @@ description: 使用 @tier0/sdk-v2/mq 连接 Tier0 MQTT WebSocket Broker,管理
5
5
 
6
6
  # MQTT 实时消息
7
7
 
8
- 连接配置、完整订阅生命周期、通配符、发布及鉴权排查见 [Quickstart](references/quickstart.md)。v1 的旧 UNS 路径/字段规则不适用于新架构;实际 MQTT 映射需按目标环境确认。
8
+ 连接配置、完整订阅生命周期、通配符、发布及鉴权排查见 [Quickstart](references/quickstart.md)。实际 MQTT 主题和消息格式按目标环境确认。
9
9
 
10
10
  `Tier0MQClient` 从独立子入口导入。它面向消息客户端;配置平台采集连接用 Source,运行处理逻辑用 Stream。HTTP SDK 的“不自动重试”不等于 MQTT 禁用重连或 QoS 重投递。
11
11
 
@@ -69,7 +69,7 @@ export async function publishMeasurement(mq: Tier0MQClient, topic: string, value
69
69
  }
70
70
  ```
71
71
 
72
- publish 目前在建立连接并调用 MQTT 库发布后返回,不等待业务执行确认,也不保证已收到 broker PUBACK。需要闭环时使用业务 ACK 主题/关联 ID 或 Control 契约,不能把 Promise resolve 当成设备执行完成。
72
+ publish 目前在建立连接并调用 MQTT 库发布后返回,不等待业务执行确认,也不保证已收到 broker PUBACK。需要闭环时使用业务 ACK 主题/关联 ID 或独立交互 SDK 的 Stream 请求合同,不能把 Promise resolve 当成设备执行完成。
73
73
 
74
74
  订阅内部 QoS 为 1;发布默认 QoS 0、retain=false。业务消费者需考虑重复消息。对象 payload 经 JSON.stringify,不能直接包含 bigint;按协议约定编码精确值,不假设 MQTT 自动使用 UNS 的无损 codec。
75
75
 
@@ -45,7 +45,7 @@ export async function subscribeTelemetry(
45
45
 
46
46
  回调是 (topic,payload),payload 为字符串。subscribe 返回 void,订阅失败通过 error 事件,不把函数返回当 broker SUBACK。此例独占连接;共享连接只退订自己的 handler,不关闭其他消费者。
47
47
 
48
- + 匹配一层,# 匹配多层,订阅范围必须属于任务和主题授权。不能从旧 v1 的 Metric/Action/State 路径、enableHistory 或字段规则推断新 UNS MQTT 映射;先核实目标平台的实际主题和消息契约。App 服务端订阅新 UNS Record 变更用 `@tier0/sdk-v2/data` 的 `data.subscribe`(`records:subscribe` 服务端推送),不是 MQTT 主题。
48
+ + 匹配一层,# 匹配多层,订阅范围必须属于任务和主题授权。主题和消息格式以目标平台的实际契约为准。App 服务端订阅新 UNS Record 变更用 `@tier0/sdk-v2/data` 的 `data.subscribe`(`records:subscribe` 服务端推送),不是 MQTT 主题。
49
49
 
50
50
  ## 发布
51
51
 
@@ -58,7 +58,7 @@ export async function publishEvent(mq: Tier0MQClient, topic: string, eventId: st
58
58
  }
59
59
  ```
60
60
 
61
- payload 必须符合实际主题契约;对象用 JSON.stringify,不可包含 bigint。publish resolve 不证明已收 PUBACK,更不证明设备执行;业务闭环用关联 ID/ACK 或 Control。订阅 QoS 1,发布默认 QoS 0/retain=false,消费端考虑重复消息。
61
+ payload 必须符合实际主题契约;对象用 JSON.stringify,不可包含 bigint。publish resolve 不证明已收 PUBACK,更不证明设备执行;业务闭环用关联 ID/ACK 或独立交互 SDK 的 Stream 请求。订阅 QoS 1,发布默认 QoS 0/retain=false,消费端考虑重复消息。
62
62
 
63
63
  ## 事件、背压和鉴权
64
64
 
@@ -66,4 +66,4 @@ connect/disconnect/error/message/subscriptionDropped 反映客户端状态。isC
66
66
 
67
67
  创建凭据用 client.mqttAuth.create({name}),撤销用 delete({id}),检查 success。回执的 clientID 对应配置 clientId;完整密码只在创建时返回一次,受控保存。
68
68
 
69
- Not authorized/CONNACK 5/重连循环时核对注入的 Key 类型、过期/撤销、授权和 Broker ws/wss 地址。v2 不回退 Enterprise 身份,也不套用旧包升级到 @tier0/sdk@latest 的建议;不因连接失败自动新建凭据。
69
+ Not authorized/CONNACK 5/重连循环时核对注入的 Key 类型、过期/撤销、授权和 Broker ws/wss 地址。v2 不回退 Enterprise 身份;不因连接失败自动新建凭据。
@@ -18,7 +18,7 @@ description: 使用 @tier0/sdk-v2 发送和查询 Tier0 站内通知、Web/Deskt
18
18
  - type 固定 inbox;Swagger 的 string 不代表接受任意类型。
19
19
  - 用人读姓名/邮箱选择收件人,ID 由成员数据解析并保持字符串,不让用户填写 ID。Workspace 成员不等于 App 可访问用户。
20
20
  - title 最多50字符,content 最多800字符。mode 按真实发布环境选择 test/live;test 会创建测试消息,不能当预检。
21
- - App sender 使用 getCurrentAppId() 的真实 APP_ID,v2 不注入 project 上下文,不复制旧 getCurrentProjectId。导航和名称展示按目标前端支持核实。
21
+ - App sender 使用 getCurrentAppId() 的真实 APP_ID,导航和名称展示按目标前端支持核实。
22
22
  - sender/link/meta 是展示提示,不作为授权。新代码不使用废弃 source 字段。
23
23
  - 同一业务事件、收件人、内容使用稳定 idempotencyKey;新事件使用新键,不因超时随机换键。
24
24
 
@@ -37,6 +37,6 @@ Desktop 属于 web,不存在 desktop 渠道。显式单渠道不补齐,重
37
37
 
38
38
  send 返回直接对象 {messageId,status,createdAt},get 返回直接状态对象,没有 data 外层。accepted 表示受理,sent 表示已发送,不是用户已读;failed 检查 errorCode/message。
39
39
 
40
- v2 ApiError 提供 status/errorCode/msg;不要沿用 v1 JSON.parse(error.msg) 的旧解析方式。未知结果先对账;已有 messageId 按 ID 查,没有按 idempotencyKey 查询的 SDK 入口。HTTP SDK 不自动重试。
40
+ ApiError 提供 status/errorCode/msg。未知结果先对账;已有 messageId 按 ID 查,没有按 idempotencyKey 查询的 SDK 入口。HTTP SDK 不自动重试。
41
41
 
42
42
  完整示例与参数边界均在操作参考中。Skill 示例不会自动发送消息,也不授予真实发送权限。
@@ -34,7 +34,7 @@ export async function sendCompletedOrder(
34
34
  }
35
35
  ```
36
36
 
37
- sender.id 来自真实 APP_ID UUID。v2 不注入 project 上下文,也没有 getCurrentProjectId;不要把 Folder/Workspace ID 填进 meta.projectId。旧 UI 的 App 名称解析/打开 App 按钮依赖 appId+projectId,不能将旧导航规则原样承诺到新架构。需带链接时传已验证可访问的业务 https 地址,或确认目标前端支持的相对路由;缺少旧上下文时不猜拼地址。
37
+ sender.id 来自真实 APP_ID UUID。需带链接时传已验证可访问的业务 https 地址,或确认目标前端支持的相对路由。
38
38
 
39
39
  other 发送者应给人读名称,如 `{type:'other',name:'库存同步服务'}`。app 不重复硬编码名称。sender/meta/link 都是展示导航提示,不是授权证明。meta 值为字符串,序列化最多 500 字节;sender.name 最多100字符。source 是废弃别名,不用于新代码。
40
40
 
@@ -56,7 +56,7 @@ other 发送者应给人读名称,如 `{type:'other',name:'库存同步服务'
56
56
 
57
57
  成功为直接 {messageId,status,createdAt},没有 data。accepted 是异步受理,sent 不是已读,详见[查询](get.md)。
58
58
 
59
- v2 的 ApiError 已提供 status/errorCode/msg,不再 JSON.parse(error.msg) 提取旧版原始错误。
59
+ 错误通过 ApiError 的 status/errorCode/msg 判断。
60
60
 
61
61
  | HTTP / errorCode | 处理 |
62
62
  | --- | --- |
@@ -23,16 +23,16 @@ Source 维护连接配置、认证引用与源状态。脚本处理用 [Stream](
23
23
 
24
24
  ## 核心约束
25
25
 
26
- 1. Source 配置统一使用 documents.*,原生文档为 `{name,protocol,config}`,HTTP API 显式指定 `config.role`。HTTP 统一为 `protocol: http-api` + `config.role: client/server`;Client 主动请求,Server 接收入站请求,不能互换。HTTPServer 统一接收入站请求,固定前缀后的路由和响应时机属于 Stream;旧 http_push 不再用于新建。
26
+ 1. Source 配置统一使用 documents.*,原生文档为 `{name,protocol,config}`,HTTP API 显式指定 `config.role`。HTTP 统一为 `protocol: http-api` + `config.role: client/server`;Client 主动请求,Server 接收入站请求,不能互换。HTTPServer 统一接收入站请求,固定前缀后的路由和响应时机属于 Stream。
27
27
  2. 已有 ID 和 revision 时优先用 documents.update 的 patch,避免额外 get;完整替换 document 前读取完整文档,安全列表摘要不能无损回写。原生 ID 是十进制字符串,revision 原样传递,不转 Number。
28
28
  3. 现有 Source 修改、启停、删除都要 expectedRevision。没有任何 Stream 引用时可直接提交;有草稿、活动、历史或不可见引用时仍需 confirmedImpactRevision。先形成精确意图,再读取全部影响分页;回执不可合成、跨意图复用或静默刷新。提供的回执始终严格校验,不自动获取并同意影响。
29
- 4. 配置中保留认证/TLS 引用,不写明文秘密;HTTP Client 新凭据走创建专用 credentials;Server 不携带 Client auth/TLS 配置。
29
+ 4. 配置中保留认证/TLS 引用,不写明文秘密;HTTP Client 新凭据走创建专用 credentials,普通创建省略 credentials.method(服务端默认 REQUEST 基址绑定),真实 method/path/query 由 Stream 定义。Basic/Bearer 显式凭据方法限制精确 URL 和方法,OAuth 旧 GET 保留既有兼容语义,不自动扩大旧授权;Server 不携带 Client auth/TLS 配置。
30
30
  5. desiredState 不代表实际健康,保存配置不代表 Stream 已切换至新 configRevision。运行状态另行读取。
31
31
 
32
32
  ## 返回值与异常
33
33
 
34
34
  所有调用返回完整 code/msg/requestId/data。documents.create/update 的预检返回 validated/sideEffects,提交返回完整 Source view,可直接使用其中的文档和 revision,无需额外 get;批量状态/删除返回 Outcome。只有 committed 且无项错误才可报告提交成功;accepted/jobId 继续查询作业。预检按需使用,不是每次提交的必经步骤。
35
35
 
36
- 需要查看历史用 source.history({id,beforeRevision,size}),按 nextBeforeRevision 继续;探测用 source.probe,其外部系统访问应属于当前任务。连接配置修改使用 documents.update,遵守同一影响确认契约。
36
+ 需要查看历史用 source.history({id,beforeRevision,size}),按 nextBeforeRevision 继续;探测用 source.probe,其外部系统访问应属于当前任务。配置校验或连接探测成功不证明某个 Stream 请求已获授权或采集成功,实际结果看对应发布的 runs。连接配置修改使用 documents.update,遵守同一影响确认契约。
37
37
 
38
38
  UnsV2Error 表示已知拒绝;UnsV2OutcomeUnknownError 表示可能已写入。保存 requestId、原请求和意图键,先查详情/历史/作业对账。取消等待不撤销服务端操作;SDK 不自动重试。权限不足不能解释为资源不存在。
@@ -41,7 +41,9 @@ HTTP Server 同样使用 `protocol: http-api`,角色为 `config.role: server`
41
41
 
42
42
  ## HTTP Client Bearer 凭据
43
43
 
44
- token 从服务端密钥提供者取得,不写入脚本、文档、日志或仓库。
44
+ Source 保存 API 基址和认证;实际请求的 method/path/query 由 Stream 设置。例如 endpoint 使用 `https://inventory.example.com/api/v1`,再由 [Stream 示例](../../tier0-sdk-v2-stream/references/create.md)请求 `GET inventory`。token 从服务端密钥提供者取得,不写入脚本、文档、日志或仓库。
45
+
46
+ 普通创建省略 `credentials.method`,服务端按 `REQUEST` 绑定 Source 基址。REQUEST 是凭据适用范围标记,不是发送给上游的 HTTP 方法;实际 GET 请求仍由执行宿主逐次授权。
45
47
 
46
48
  ```ts
47
49
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
@@ -53,7 +55,7 @@ export async function createAuthenticatedHttpSource(
53
55
  const saved = await client.source.documents.create({
54
56
  dryRun: false, idempotencyKey: intentKey,
55
57
  document: { name, protocol: 'http-api', config: { role: 'client', endpoint, options: {} } },
56
- credentials: { method: 'GET', kind: 'bearer', material: { token } },
58
+ credentials: { kind: 'bearer', material: { token } },
57
59
  });
58
60
  if (!('id' in saved.data)) throw new Error('未返回 Source ID');
59
61
  return { receipt: saved, current: saved.data };
@@ -92,12 +94,14 @@ Server 的固定前缀 `/ingest/v1/{workspaceId}/{sourceId}` 和 Bearer 要求
92
94
 
93
95
  | kind | material | method |
94
96
  | --- | --- | --- |
95
- | basic | username、password | 省略时 REQUEST;可显式绑定受限 HTTP 方法 |
96
- | bearer | token | 省略时 REQUEST;上方 GET 示例保持明确的方法限制 |
97
- | apiKey | headerName、value | 省略或 REQUEST;不接受旧 name/key 形态 |
98
- | oauth2ClientCredentials | tokenUrl、clientId、clientSecret;可选 scope、clientAuthentication | 省略、REQUEST 或 GET |
97
+ | basic | username、password | 省略时 REQUEST;显式方法绑定精确 URL 和该方法 |
98
+ | bearer | token | 省略时 REQUEST;显式方法绑定精确 URL 和该方法 |
99
+ | apiKey | headerName、value | 省略或 REQUEST |
100
+ | oauth2ClientCredentials | tokenUrl、clientId、clientSecret;可选 scope、clientAuthentication | 普通创建省略;旧 GET 保留既有兼容语义 |
101
+
102
+ Basic/Bearer 显式 `credentials.method: 'GET'` 表示凭据只用于所绑定精确 URL 的 GET,不表示该基址下所有 GET 都可使用:绑定 `/api/v1` 不授权 `/api/v1/inventory?limit=5000`。仅在任务明确需要该限制时传入;已有绑定保持原限制,不自动迁移或在拒绝后回退 REQUEST。
99
103
 
100
- OAuth 的 `clientAuthentication` 支持 `client_secret_post`(默认)和 `client_secret_basic`。REQUEST 表示绑定 Source 基址,实际路径和方法仍由执行宿主逐次授权;显式方法的已有绑定不能解释成 REQUEST 的基址范围。vendor SESSION 合同独立保留,不是此 inline 创建的 method,也不新增独立公开凭据 API。
104
+ OAuth 的 `clientAuthentication` 支持 `client_secret_post`(默认)和 `client_secret_basic`;method 接受省略、REQUEST 或旧 GET,旧 GET 保留现有兼容语义,不能把 Basic/Bearer 的精确 URL 规则跨认证类型套用。普通创建仍省略 method。vendor SESSION 合同独立保留,不是此 inline 创建的 method,也不新增独立公开凭据 API。
101
105
 
102
106
  ```ts
103
107
  import { createClient, type Tier0Client, type CloudSourceCreateCredentials } from '@tier0/sdk-v2';
@@ -1,6 +1,6 @@
1
1
  # 协议与连接配置
2
2
 
3
- 先调用 `source.protocols.list({})`。协议枚举存在不等于目标环境驱动或凭据解析器已就绪。HTTP Source 统一使用 `protocol: 'http-api'`,通过文档的 `config.role: 'client' | 'server'` 区分主动请求和入站服务,与 Enterprise 的一协议两角色模型一致。角色和协议能力以目标环境目录为准;旧 `http` 不作为新建示例。
3
+ 先调用 `source.protocols.list({})`。协议枚举存在不等于目标环境驱动或凭据解析器已就绪。HTTP Source 统一使用 `protocol: 'http-api'`,通过文档的 `config.role: 'client' | 'server'` 区分主动请求和入站服务,与 Enterprise 的一协议两角色模型一致。角色和协议能力以目标环境目录为准。
4
4
 
5
5
  | 配置字段 | 类型 | 必填 | 说明 |
6
6
  | --- | --- | --- | --- |
@@ -11,7 +11,7 @@
11
11
  | auth.credentialRef | string | 有认证时 | 已存在且可用的凭据引用 |
12
12
  | tls.caRef / clientIdentityRef | string | 否 | 已存在的 CA/客户端身份引用 |
13
13
 
14
- 以下只构造文档,不执行创建;实际地址、主题、设备 unitId 由任务上下文提供。提交前用 documents.create 的 dryRun 校验。
14
+ 以下只构造文档,不执行创建;实际地址、主题、设备 unitId 由任务上下文提供。需要预览配置问题时使用 documents.create 的 dryRun;正式创建本身执行校验。
15
15
 
16
16
  ```ts
17
17
  import { createClient, type CloudSourceDocument } from '@tier0/sdk-v2';
@@ -35,8 +35,8 @@ HTTP Client 的 options 支持 headers 和 parameters;headers 可包含目录
35
35
 
36
36
  SQL options 包含 tlsMode(verify-full/disable)和 queries(资源名→固定 SQL);脚本不能替换任意 SQL。OPC UA、SAP、Teamcenter 等按能力和服务端校验配置,不从 HTTP 模板生造字段。不要为通过校验自动移除认证或关闭 TLS。
37
37
 
38
- HTTP Client 示例不能用于 Server。HTTPServer 通过 `source.documents.*` 配置监听源,固定前缀为 `/ingest/v1/{workspaceId}/{sourceId}`;Stream 注册相对业务路由和处理函数,见 [HTTPServer Stream](../../tier0-sdk-v2-stream/references/http-server.md)。旧 `http_push` 不再作为独立模式创建;响应时机在 Stream 层处理。
38
+ HTTP Client 示例不能用于 Server。HTTPServer 通过 `source.documents.*` 配置监听源,固定前缀为 `/ingest/v1/{workspaceId}/{sourceId}`;Stream 注册相对业务路由和处理函数,见 [HTTPServer Stream](../../tier0-sdk-v2-stream/references/http-server.md)。响应时机在 Stream 层处理。
39
39
 
40
40
  Cloud 的角色位于 `config.role`;Enterprise 投影的顶层 `role` 不能直接抄入 Cloud 管理文档。Server 配置见[创建](create.md),以 `http://managed` 和空 options 保存,不从 Client 模板推导。
41
41
 
42
- HTTP Client 的单条 inline 认证支持 basic / bearer / apiKey / oauth2ClientCredentials,method 省略时由服务端按 REQUEST 绑定 Source 基址;显式方法限制保持不变。APIKey 材料为 headerName/value,OAuth 可提供 clientAuthentication。见[创建](create.md)。
42
+ HTTP Client 的单条 inline 认证支持 basic / bearer / apiKey / oauth2ClientCredentials。普通创建省略 credentials.method,由服务端按 REQUEST 绑定 Source 基址;实际 method/path/query 在 Stream 设置。Basic/Bearer 显式凭据方法同时限制精确 URL,不覆盖基址下的子路径;存量绑定保持限制,不自动扩大权限。APIKey 材料为 headerName/value,OAuth 可提供 clientAuthentication,旧 OAuth GET 保留既有兼容语义。见[创建](create.md)。
@@ -7,7 +7,7 @@
7
7
  | source.runtime.get | /openapi/v2/uns/sources/runtime/get | id(必填) | 运行状态 |
8
8
  | source.observations.get | /openapi/v2/uns/sources/observations/get | items:id、expectedRevision | 指定源和修订的观测 |
9
9
 
10
- page 从 1 开始,size 1–200。列表默认安全摘要。get 省略 view 保持旧的 full 行为;summary 需要 uns.source.view 或 uns.source.manage,full 需要 uns.source.manage;API Key 读取完整文档还必须是 full_access(includeDocument:true 同样适用)。未知 revision 时可读取 summary;要完整替换 document 或查看配置时读取 full。已持有写回执中的 ID/revision 时,可直接提交 patch,无需为了编辑再 get;服务端仍会检查版本冲突。摘要不能用于重建完整配置。 对已知旧版配置,安全读取投影可能移除退休的 configVersion 标记;这不代表历史已经迁移或可以运行。写入仍使用当前无版本配置,不向请求补回旧标记或协议别名。
10
+ page 从 1 开始,size 1–200。列表默认安全摘要。get 省略 view 时返回 full;summary 需要 uns.source.view 或 uns.source.manage,full 需要 uns.source.manage;API Key 读取完整文档还必须是 full_access(includeDocument:true 同样适用)。未知 revision 时可读取 summary;要完整替换 document 或查看配置时读取 full。已持有写回执中的 ID/revision 时,可直接提交 patch,无需为了编辑再 get;服务端仍会检查版本冲突。摘要不能用于重建完整配置。
11
11
 
12
12
  ```ts
13
13
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
@@ -14,9 +14,9 @@ description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和
14
14
  | 新建并绑定 HTTP Client Source | [创建](references/create.md) | documents.create({program}) |
15
15
  | HTTPServer 固定前缀与业务路由 | [HTTPServer](references/http-server.md) | documents.create({document})、api.stream.onRequest、ctx.reply |
16
16
  | 列表、完整文档、运行记录 | [查询](references/read.md) | programs.list、documents.get、observations.get、runs.list |
17
- | 修改草稿、脚本和绑定 | [修改](references/update.md) | documents.validate/update |
17
+ | 修改草稿、脚本和绑定 | [修改](references/update.md) | documents.update(需要预览时 validate) |
18
18
  | 发布、停用、版本回滚 | [部署](references/deploy.md) | programs.deploy/rollback、documents.disable |
19
- | 删除并核验归档 | [删除](references/delete.md) | programs.delete |
19
+ | 删除 | [删除](references/delete.md) | programs.delete |
20
20
  | 隔离样例测试、流程衔接 | [生命周期](references/lifecycle.md) | sampleTest |
21
21
 
22
22
  ## 两种文档形态
@@ -26,20 +26,20 @@ description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和
26
26
  | Runtime program | name、script 字符串、sourceBindings、timeoutMs | documents.create/update/validate({program}) |
27
27
  | 云端原生文档 | name、model、script 对象、sources、entries | documents.create/get/update/validate |
28
28
 
29
- 程序必须是完整 `module.exports = api => { ... }`,执行器 API 是 api.sources/api.uns/api.stream,与 npm 包的 client.source 不同。Runtime sourceBindings 为 sourceId/configRevision/acquisition;原生 sources 还使用 alias/resources。连接凭据不进脚本或 acquisition,秘密材料由 Source 执行宿主管理,不通过脚本读取、记录或返回。定时入口使用 api.stream.every,不传播旧注册别名;npm 的 client.controls 管理入口不作为 Goja 的 Stream 注册参数。
29
+ 程序必须是完整 `module.exports = api => { ... }`,执行器 API 是 api.sources/api.uns/api.stream,与 npm 包的 client.source 不同。Runtime sourceBindings 为 sourceId/configRevision/acquisition;原生 sources 还使用 alias/resources。连接凭据不进脚本或 acquisition,秘密材料由 Source 执行宿主管理,不通过脚本读取、记录或返回。定时入口使用 api.stream.every,不传播旧注册别名;App 请求与消息交互由独立 @tier0/sdk 的 client.streams.requests/messages 提供,不作为 Goja 注册参数。
30
30
 
31
31
  ## 核心约束
32
32
 
33
33
  1. documents.get({id,view:"summary"}) 返回安全摘要,不含可回写脚本;完整编辑使用 documents.get 或上次 documents.create/update 返回的完整文档。保留未修改的 sources/entries/script 字段。
34
34
  2. create/update 保存草稿,不自动发布;documents 没有 deploy,云端 program 发布使用 programs.deploy。不能将已保存报告为已运行。
35
35
  3. 所有更新/部署/删除携带当前 expectedRevision。原生停用另需 expectedActiveRelease,避免停掉他人刚发布的版本。
36
- 4. versionId 从 versions.list 取得,不把 release 序号当 ID。expectedSourceRevision 仅用于恰好一个依赖源,不代表多个源的修订。
37
- 5. resources=[] 是空冻结资源集,不是通配符。写入本身由服务端校验,需要预览时单独 validate;当前云端程序 timeoutMs 上限 30000。旧 runtime.capabilities 查询已退役,不作为管理或执行前置检查,不为此增加 Control scope 或逐 Key 控制码授权。
36
+ 4. versionId 使用已知发布回执的 activeVersion,或从 versions.list 选定,不把 release 序号当 ID。expectedSourceRevision 仅用于恰好一个依赖源,不代表多个源的修订。
37
+ 5. resources=[] 是空冻结资源集,不是通配符。写入本身由服务端校验,需要预览时单独 validate;当前云端程序 timeoutMs 上限 30000。
38
38
  6. HTTPServer 响应时机在 Stream:普通返回等处理/提交完成;HTTP onRequest 内 await ctx.reply 可先回复一次再继续,仍受超时/并发/权限约束,断线不取消但 shutdown 可取消,不保证崩溃重放。
39
39
  7. 仅执行用户要求的生命周期步骤;修改脚本不自动授予发布、停用或删除权限。
40
40
 
41
41
  ## 成功与异常
42
42
 
43
- 响应保留 code/msg/requestId/data。创建/更新回执的 revision 可直接用于发布;programs 发布回执的 activeRelease 是同次事务保存的正整数发布序号,无需前后 get。programs 回执和查询结果无活跃发布时省略 activeRelease,activeVersion 保留字符串 0 的兼容语义。校验要检查 valid,样例要检查 completed/failed,删除要检查 deleted;发布后按回执的 activeRelease 筛选 runs.list 才能确认该版本运行。样例 writePreview 不代表线上数据写入。
43
+ 响应保留 code/msg/requestId/data。创建/更新回执的 revision 可直接用于发布;programs 发布回执的 activeRelease 是同次事务保存的正整数发布序号,无需前后 get。programs 回执和查询结果无活跃发布时省略 activeRelease,activeVersion 为字符串 0。校验要检查 valid,样例要检查 completed/failed,删除要检查 deleted;发布后按回执的 activeRelease 筛选 runs.list 才能确认该版本运行。样例 writePreview 不代表线上数据写入。
44
44
 
45
- UnsV2OutcomeUnknownError、发布超时或取消后保留原路由、载荷和幂等键;允许恢复时原样重发取得原回执,不用新键重复发布。历史回执可能缺少 activeRelease,不得用当前 head 替代。版本冲突先比较当前草稿,不能忽略 expectedRevision。不同写入意图使用不同键;本地 SDK 测试不能代替目标环境联调。
45
+ UnsV2OutcomeUnknownError、发布超时或取消后保留原路由、载荷和幂等键;允许恢复时原样重发取得原回执,不用新键重复发布。回执缺少 activeRelease 时不得用当前 head 替代。版本冲突先比较当前草稿,不能忽略 expectedRevision。不同写入意图使用不同键;本地 SDK 测试不能代替目标环境联调。
@@ -13,29 +13,30 @@
13
13
 
14
14
  ## HTTP Client Source 绑定示例
15
15
 
16
- 先按[Source 查询](../../tier0-sdk-v2-source/references/read.md)选定真实 HTTP Client Source。脚本的 api.sources 属于平台执行器,与应用中的 client.source 不同。sourceId 保持字符串,configRevision 从完整源读取。省略 `config.role` 时按正式协议目录默认为 client;Server 走入站语义,不能创建为主动请求程序。
16
+ 先按[Source 查询](../../tier0-sdk-v2-source/references/read.md)选定真实 HTTP Client Source。脚本的 api.sources 属于平台执行器,与应用中的 client.source 不同。sourceId 保持字符串,configRevision 使用 Source 创建、更新回执或完整查询得到的修订。已有回执时直接传入 source;没有快照时再调用 source.documents.get({id,view:"full"}) 并检查 data.document。省略 `config.role` 时按正式协议目录默认为 client;Server 走入站语义,不能创建为主动请求程序。
17
+
18
+ Source 负责基址和认证,Stream 负责请求的 method/path/query。以下示例与 [Source Bearer 创建](../../tier0-sdk-v2-source/references/create.md#http-client-bearer-凭据)配合:Source endpoint 为 `https://inventory.example.com/api/v1`,凭据使用默认基址绑定;实际请求是 `GET https://inventory.example.com/api/v1/inventory?limit=5000`。已有 Source 的凭据若只绑定精确 URL `/api/v1` 的 GET,不能用于此子路径;不要通过改写请求为 REQUEST 或自动扩大凭据授权来绕过拒绝。
17
19
 
18
20
  ```ts
19
- import { createClient, type Tier0Client, type RuntimeStreamDefinition } from '@tier0/sdk-v2';
21
+ import { createClient, type Tier0Client, type RuntimeStreamDefinition, type CloudSourceDocumentView } from '@tier0/sdk-v2';
20
22
 
21
23
  export async function createHttpStream(
22
- sourceId: string, name: string, intentKey: string, client: Tier0Client = createClient(),
24
+ source: CloudSourceDocumentView, name: string, intentKey: string, client: Tier0Client = createClient(),
23
25
  ) {
26
+ const sourceId = source.id;
24
27
  if (!/^[1-9][0-9]*$/.test(sourceId)) throw new Error('Source ID 必须是正十进制字符串');
25
- const source = await client.source.documents.get({ id: sourceId, view: 'full' });
26
- if (!('document' in source.data)) throw new Error('需要完整 Source 文档');
27
- if (source.data.document.protocol !== 'http-api' || 'sourceType' in source.data.document.config ||
28
- (source.data.document.config.role ?? 'client') !== 'client') {
28
+ if (source.document.protocol !== 'http-api' || 'sourceType' in source.document.config ||
29
+ (source.document.config.role ?? 'client') !== 'client') {
29
30
  throw new Error('此主动请求示例需要 HTTP API Client Source');
30
31
  }
31
32
  const document: RuntimeStreamDefinition = {
32
33
  name, timeoutMs: 5000,
33
- sourceBindings: [{ sourceId, configRevision: source.data.revision, acquisition: {} }],
34
+ sourceBindings: [{ sourceId, configRevision: source.revision, acquisition: {} }],
34
35
  script: [
35
36
  'module.exports = api => {',
36
37
  ' const upstream = api.sources.use({ id: ' + JSON.stringify(sourceId) + ', resources: [] });',
37
38
  ' api.stream.every({ id: "tick", intervalMs: 60000 }, async () => {',
38
- ' const response = await upstream.request({ method: "GET", path: "orders" });',
39
+ ' const response = await upstream.request({ method: "GET", path: "inventory", query: { limit: "5000" } });',
39
40
  ' return response.data;',
40
41
  ' });',
41
42
  '};',
@@ -49,10 +50,12 @@ export async function createHttpStream(
49
50
  }
50
51
  ```
51
52
 
52
- 将 path="orders"、60 秒周期改为业务实际值。示例保存草稿,不部署,也不将返回值自动写入 UNS;需要写入集合时按执行器能力定义 api.uns 操作。resources=[] 是空冻结资源集,不是通配授权。源地址和凭据留在 Source,不能拷进 acquisition 或脚本。
53
+ 将 path="inventory"、query 和 60 秒周期改为业务实际值。示例保存草稿,不部署,也不将返回值自动写入 UNS;需要写入集合时按执行器能力定义 api.uns 操作。resources=[] 是空冻结资源集,不是通配授权。源地址和凭据留在 Source,不能拷进 acquisition 或脚本。
54
+
55
+ 创建 data 为 CloudStreamDocumentView 或预检结果,实际保存返回 id、revision 和完整 document;预检不生成 ID。需要展示预检时单独调用 documents.validate({program});普通保存无需先校验再保存。当前后端创建/校验需要注册 Worker 可用。TEMPORARILY_UNAVAILABLE 不代表脚本一定错误。
53
56
 
54
- 创建 data 为 CloudStreamDocumentView 或预检结果,实际保存返回 id、revision 和完整 document;预检不生成 ID。需要展示预检时单独调用 documents.validate({program});普通保存无需先校验再保存。当前后端创建/校验需要注册 Worker 可用。TEMPORARILY_UNAVAILABLE 不代表脚本一定错误;不要自动改用旧 Flow。
57
+ validate 检查配置、程序和可确定的绑定问题,不执行任意业务分支,也不证明上游可达。尤其是运行时拼接的 path/query,仍需在授权范围内执行代表性采集,并检查本次发布的 runs 与业务结果;一次成功也只覆盖实际执行的请求。Source 连接探测和 isolated-sample 都不能替代真实采集验证。
55
58
 
56
- programs.create 已退役,创建统一使用 documents.create。历史创建结局未知时先按已知 ID 或业务标识核对状态,不能将旧请求或幂等键改投 documents.create 重做。
59
+ 创建结局未知时先按已知 ID 或业务标识核对状态;允许重试时保留原请求与幂等键。
57
60
 
58
61
  原生编辑器形态 `documents.create({dryRun, document})` 的 document 为 name/model/script对象/sources/entries,script 为 `{code,timeoutMs}`,sources 用 alias/sourceId/configRevision/resources/acquisition。不要把上面的 script 字符串直接塞入原生文档。
@@ -5,31 +5,24 @@
5
5
  | 字段 | 类型 | 必填 | 说明 |
6
6
  | --- | --- | --- | --- |
7
7
  | id | string | 是 | 十进制字符串 |
8
- | expectedRevision | integer | 建议提供 | 当前 get 返回修订 |
8
+ | expectedRevision | integer | 建议提供 | 当前回执或查询的修订 |
9
9
  | dryRun | boolean | 是 | true 预检;false 提交 |
10
10
  | idempotencyKey | string | 否 | 最多 128 字符 |
11
11
 
12
- 先读取明确目标并评估活跃发布/调用依赖。停止运行与删除是两个操作,删除请求不自动授予对 Source/UNS 数据的清理权限。
12
+ 使用已确认目标的回执或查询快照,评估活跃发布/调用依赖。停止运行与删除是两个操作,删除请求不自动授予对 Source/UNS 数据的清理权限。
13
13
 
14
14
  ```ts
15
- import { createClient, type Tier0Client } from '@tier0/sdk-v2';
15
+ import { createClient, type Tier0Client, type CloudStreamStopView } from '@tier0/sdk-v2';
16
16
 
17
- export async function deleteStream(id: string, intentKey: string, client: Tier0Client = createClient()) {
18
- const { data: current } = await client.stream.documents.get({ id });
17
+ export async function deleteStream(
18
+ current: Pick<CloudStreamStopView, 'id' | 'revision'>, intentKey: string, client: Tier0Client = createClient(),
19
+ ) {
19
20
  const receipt = await client.stream.programs.delete({
20
- id, expectedRevision: current.revision, dryRun: false, idempotencyKey: intentKey,
21
+ id: current.id, expectedRevision: current.revision, dryRun: false, idempotencyKey: intentKey,
21
22
  });
22
23
  if (!('deleted' in receipt.data) || receipt.data.deleted !== true) throw new Error('未确认删除');
23
- let page = 1;
24
- while (true) {
25
- const { data } = await client.stream.programs.list({ archived: true, page, size: 200 });
26
- const archived = data.list.find(item => item.id === id);
27
- if (archived) return { receipt, archived };
28
- if (!data.hasMore) return { receipt, archived: undefined };
29
- if (typeof data.nextPage !== 'number' || data.nextPage <= page) throw new Error('无有效下一页');
30
- page = data.nextPage;
31
- }
24
+ return { receipt, current: receipt.data };
32
25
  }
33
26
  ```
34
27
 
35
- 成功 data 为 `{id,revision,deleted:true}`;预检为 `{validated:true,sideEffects:false}`。归档列表额外核验,未查到时报告“删除有回执,读回未确认”。不要捕获所有 get 异常并返回删除成功。并发冲突重新评估,不用无版本保护的请求覆盖。
28
+ 成功 data 为 `{id,revision,deleted:true}`;预检为 `{validated:true,sideEffects:false}`。默认以 deleted 回执确认本次删除,无需遍历归档列表。需要独立审计时再按页查询 programs.list({archived:true,page,size}),找不到不能伪造读回确认。不要捕获所有 get 异常并返回删除成功。并发冲突重新评估,不用无版本保护的请求覆盖。