@tier0/sdk-v2 0.6.3 → 0.8.0

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 (91) hide show
  1. package/README.md +36 -10
  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/data/bootstrap.js +5 -5
  12. package/dist/cjs/data/bootstrap.js.map +1 -1
  13. package/dist/cjs/data/define.d.ts +6 -0
  14. package/dist/cjs/data/define.js +11 -1
  15. package/dist/cjs/data/define.js.map +1 -1
  16. package/dist/cjs/data/schema.d.ts +1 -0
  17. package/dist/cjs/data/schema.js +7 -0
  18. package/dist/cjs/data/schema.js.map +1 -1
  19. package/dist/cjs/index.d.ts +0 -1
  20. package/dist/cjs/index.js +0 -1
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/openapi/api.generated.d.ts +9 -5
  23. package/dist/cjs/openapi/codecs.generated.d.ts +943 -684
  24. package/dist/cjs/openapi/codecs.generated.js +1 -1
  25. package/dist/cjs/openapi/codecs.generated.js.map +1 -1
  26. package/dist/cjs/openapi/types.generated.d.ts +638 -508
  27. package/dist/cjs/openapi/types.generated.js.map +1 -1
  28. package/dist/cjs/uns-v2/client.js +2 -2
  29. package/dist/cjs/uns-v2/client.js.map +1 -1
  30. package/dist/cjs/uns-v2/generated.d.ts +183 -253
  31. package/dist/cjs/uns-v2/generated.js +16 -19
  32. package/dist/cjs/uns-v2/generated.js.map +1 -1
  33. package/dist/esm/capabilities.d.ts +20 -4
  34. package/dist/esm/capabilities.js +66 -6
  35. package/dist/esm/capabilities.js.map +1 -1
  36. package/dist/esm/client.d.ts +9 -7
  37. package/dist/esm/client.js +0 -2
  38. package/dist/esm/client.js.map +1 -1
  39. package/dist/esm/cloud-transport.d.ts +3 -2
  40. package/dist/esm/cloud-transport.js +8 -7
  41. package/dist/esm/cloud-transport.js.map +1 -1
  42. package/dist/esm/data/bootstrap.js +5 -5
  43. package/dist/esm/data/bootstrap.js.map +1 -1
  44. package/dist/esm/data/define.d.ts +6 -0
  45. package/dist/esm/data/define.js +9 -0
  46. package/dist/esm/data/define.js.map +1 -1
  47. package/dist/esm/data/schema.d.ts +1 -0
  48. package/dist/esm/data/schema.js +8 -1
  49. package/dist/esm/data/schema.js.map +1 -1
  50. package/dist/esm/index.d.ts +0 -1
  51. package/dist/esm/index.js +0 -1
  52. package/dist/esm/index.js.map +1 -1
  53. package/dist/esm/openapi/api.generated.d.ts +9 -5
  54. package/dist/esm/openapi/codecs.generated.d.ts +943 -684
  55. package/dist/esm/openapi/codecs.generated.js +1 -1
  56. package/dist/esm/openapi/codecs.generated.js.map +1 -1
  57. package/dist/esm/openapi/types.generated.d.ts +638 -508
  58. package/dist/esm/openapi/types.generated.js.map +1 -1
  59. package/dist/esm/uns-v2/client.js +2 -2
  60. package/dist/esm/uns-v2/client.js.map +1 -1
  61. package/dist/esm/uns-v2/generated.d.ts +183 -253
  62. package/dist/esm/uns-v2/generated.js +16 -19
  63. package/dist/esm/uns-v2/generated.js.map +1 -1
  64. package/package.json +5 -7
  65. package/skills/tier0-sdk-v2/SKILL.md +14 -4
  66. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/SKILL.md +3 -0
  67. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/consistency.md +3 -3
  68. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/errors.md +1 -1
  69. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/modeling.md +6 -1
  70. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/read-write.md +3 -1
  71. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/schema-evolution.md +6 -4
  72. package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/SKILL.md +1 -1
  73. package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/references/quickstart.md +1 -1
  74. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md +2 -2
  75. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/create.md +10 -6
  76. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/protocols.md +1 -1
  77. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md +1 -1
  78. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/create.md +12 -2
  79. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/http-server.md +1 -1
  80. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/lifecycle.md +2 -0
  81. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/read.md +6 -0
  82. package/skills/tier0-sdk-v2/tier0-sdk-v2-system/SKILL.md +7 -2
  83. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/create.md +1 -1
  84. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/namespace.md +4 -0
  85. package/dist/cjs/controls.d.ts +0 -105
  86. package/dist/cjs/controls.js +0 -172
  87. package/dist/cjs/controls.js.map +0 -1
  88. package/dist/esm/controls.d.ts +0 -105
  89. package/dist/esm/controls.js +0 -166
  90. package/dist/esm/controls.js.map +0 -1
  91. package/skills/tier0-sdk-v2/tier0-sdk-v2-controls/SKILL.md +0 -65
package/README.md CHANGED
@@ -2,16 +2,24 @@
2
2
 
3
3
  Tier0 云端新架构的独立 TypeScript / JavaScript SDK。新仓库、新 npm 包,不覆盖 `@tier0/sdk`。
4
4
 
5
- 要求 Node.js 20.19+。HTTP API 统一使用 `/openapi/v2`,Source、Stream、UNS 按领域提供入口;浏览器 HTTP、MQTT、React、Vue 和服务端身份验签分别提供独立入口。
5
+ `0.8.0` 新增不兼容变更:Collection 声明必须同时提供业务名称 `name`(例如「生产工单」)和稳定程序标识 `alias`(例如 `production_orders`)。`name` 是唯一展示名称,不支持 `displayName`;重复 ensure 保留用户改名,同目录重名直接报错。高层声明与底层生成类型已统一,使用前需确认后端已包含 `business-name/1` 契约。新架构版本通过 npm `next` 标签发布。
6
6
 
7
- 当前契约版本与后端提交见 [契约来源](contracts/upstream.json)。安装 SDK 后仍需确认目标环境已部署相应后端。
7
+ `0.7.x` 包含不兼容变更:移除旧 Controls 入口、生成操作、DTO 和错误类,不保留别名。Stream 请求与消息交互使用独立 `@tier0/sdk`;本包继续负责数据和 Source/Stream 管理。能力发现不再以可选交互合同阻断 Namespace,未知核心合同仍严格拒绝。V2 的 `execution` / `retry` 和结果未知语义保持不变。
8
+
9
+ `0.6.0` 的 HTTP Source 只保留 `protocol: http-api`,通过 `config.role: client | server` 区分主动请求与入站服务。旧 `http` / `http_push` 配置需要迁移;响应时机属于 Stream,不再建立独立异步 Source。同步 singlemodel 合同后,Source 配置不再带 configVersion,Stream 输入不再带 sdkVersion;保留完整 module.exports 程序与原生 script 对象/Runtime program 字符串两种既有形态,不能将旧 transform 函数体直接改名迁入。
10
+
11
+ `0.4.0` 版本变更:相对 0.3.x 移除已退役的 Stream 就绪探针且不保留别名,改用服务端现有统一权限,不再配置逐 Key Control scopes/codes。0.3.0 起统一使用 OpenAPI v2 并退役重复及旧接口;与 0.2.x 存在不兼容变更,迁移方式见下方“本次接口退役”。对应 UNS v2 契约 5.0.0,与 0.1.0 不兼容(新错误模型 `execution` / `retry`、封顶计数、删除 `recordChangesPoll` 等)。Collection 支持 int、float、double 和 datetime 声明;格式注解不新增数值范围或日期格式校验,Sample 外层 time 保持不变。使用时需确认目标环境已部署对应后端。要求 Node.js 20.19+。浏览器 HTTP、MQTT、React、Vue 和服务端身份验签分别提供独立入口。
12
+
13
+ 合同快照的准确 Backend 提交和输入摘要见 contracts/upstream.json;使用前需确认目标环境已部署相应合同。请求统一权限、旧探针退役门禁、Source discovery 的副作用分类及不自动重试语义保持不变。
14
+
15
+ 既有接口收敛:平台接口统一迁移到 `/openapi/v2`;移除 21 个重复 UNS 入口和旧 Agent nodes/relations 方法。完善 Source 操作、Stream 发布回执及 UNS 创建快照的使用说明,保留精确发布编号和完整文档访问规则。
8
16
 
9
17
  ## 安装与初始化
10
18
 
11
19
  维护者发布前在本仓库运行 `npm ci`、`npm run check`,并验证生成的 `.tgz`。业务项目安装当前发布版本:
12
20
 
13
21
  ```sh
14
- npm install @tier0/sdk-v2
22
+ npm install @tier0/sdk-v2@0.8.0
15
23
  ```
16
24
 
17
25
  ```ts
@@ -41,7 +49,6 @@ const user = await tier0.system.whoami();
41
49
  | `tier0.mqttAuth` | 创建、删除 MQTT 凭证 |
42
50
  | `tier0.agent` | `analyses`、`canvases`、`cards`、`jobs`、`jobRuns`、`library`、`results` |
43
51
  | `tier0.capabilities` | 当前凭证可见的能力发现;就绪状态由服务端判断 |
44
- | `tier0.controls` | Control 发现、描述、执行及结果未知错误 |
45
52
  | `tier0.api` | 44 个平台 OpenAPI v2 的完整生成接口;通常优先使用上面的领域入口 |
46
53
  | `@tier0/sdk-v2/mq` | MQTT WebSocket 客户端与 broker 地址工具;不进入根入口依赖图 |
47
54
  | `@tier0/sdk-v2/source` | `createSourceClient()`,独立 Source 客户端 |
@@ -52,18 +59,33 @@ const user = await tier0.system.whoami();
52
59
  | `@tier0/sdk-v2/data` | App 数据层:`defineCollection()` 声明集合(含 TTL)、`createDataClient()` 首次访问时 ensure,Mongo 风格读写、带总数分页与封顶计数、原子批量与 `transact`、`subscribe` 变更订阅、员工数据主体透传;自动幂等键、并发上限与按 `retry.safe` 重试;仅服务端,需要 `zod` 4 |
53
60
  | `@tier0/sdk-v2/data/define` | 集合声明与类型:`defineCollection()`、`Doc` / `NewDoc` 等、`compileCollection()`、`validateDocument()`;可进浏览器包,组件和 route 的客户端代码只从这里取声明和类型 |
54
61
 
55
- Workspace 成员不等于能使用某个 App 的成员;App 成员选择使用 `members.listApp`。
62
+ 集合声明必须分别提供稳定程序标识 `alias` 和业务名称 `name`,例如 `alias: 'production_orders'`、`name: '生产工单'`。目录、数据和引用直接用 name 展示,不提供 displayName 或名称回退;name 为 1–63 个 Unicode 字符,无首尾空白,不含 `/` 或空字符。ensure 按 alias 关联集合,仅首次创建设置 name,不覆盖用户改名。名称冲突时选择有区分度的业务名称,不拼随机后缀。
63
+
64
+ 不保留 UNS v1、旧 Flow、`getCurrentProjectId()`、project 成员查询或 `/gw/reload`。Workspace 成员不等于能使用某个 App 的成员,不可用前者在客户端猜测 App 权限。
65
+
66
+ ## 本次接口退役
67
+
68
+ HTTP 调用统一使用 `/openapi/v2`。21 个重复 UNS 公共入口及生成方法直接移除,没有旧路由回退;升级 SDK 时需同时部署对应后端。
69
+
70
+ - Source 的 list/get/create/update、connection.update 改用 documents.*;Stream 的 programs.get/create/update/validate/disable 改用 documents.*,停用同时携带 expectedRevision 与 expectedActiveRelease。
71
+ - 低层 findOneAnd* 改用 updateOne/replaceOne/deleteOne 的 returnDocument;批量新增用 bulkWrite 的 insertOne 项;元数据单条读取用 metadataFind + limit:1,去重用 aggregate。
72
+ - App 数据层的 insertMany、findOneAnd*、distinct 等便捷方法保留,由 SDK 映射到当前入口;insertMany 仍是单次原子请求,最多 200 项。
73
+ - Agent 的旧 nodes.searchSemantic/indexSync 和 relations.list/teach 没有 v2 契约,不再导出。旧 Controls 便捷入口、操作、DTO 和错误类不再导出,也没有兼容别名。
74
+
75
+ 升级前应核对旧写请求的最终结果,包括集合初始化 seed。退役入口不再可调用,不能将未知结果的旧请求或幂等键直接改投新入口重做。当前入口的重试仍保留原路径、原键和原载荷。
76
+
77
+ `client.capabilities.discover()` 使用 `POST /openapi/v2/capabilities/discover` 和空对象,返回直接 JSON。Cloud / Enterprise 使用同一发现合同,只消费 Namespace、Source、Stream 管理能力,不以 App 交互域的版本标签作为前置条件。Source / Stream 的 `operations` 分别描述读取、配置、运行等操作,保留 `reasonCode`、`checkedAt`、`validUntil` 和 `requiresResourceCheck`;领域整体不可用时,读取或安全停用仍可能可用。证明到期后重新发现,实际操作仍需服务端检查具体资源权限和依赖。发现不代表设备在线或操作已成功,不自动重试。
56
78
 
57
79
  ## Source、Stream 与 UNS 分域
58
80
 
59
- Source 负责连接外部系统,Stream 负责处理与运行,UNS 负责命名空间与业务数据。公开操作由固定的上游契约生成,业务入口按领域组织;Control 使用 `tier0.controls` 的专属契约。目录、Topic、集合基础 CRUD 统一使用 `metadata*`,查询、批量操作、软删除及恢复见 UNS Skill。
81
+ Source 负责连接外部系统,Stream 负责处理与运行,UNS 负责命名空间与业务数据。公开操作由固定的上游契约生成,业务入口按领域组织。Stream 请求与消息交互使用独立包 `@tier0/sdk` 的 `client.streams.requests` / `client.streams.messages`;Scaffold 分别接入交互 SDK 和本数据 SDK。本包不重复提供 Stream 交互 API。目录、Topic、集合基础 CRUD 统一使用 `metadata*`,查询、批量操作、软删除及恢复见 UNS Skill。
60
82
 
61
83
  ```ts
62
84
  const sources = await tier0.source.documents.list({ page: 1, size: 20 });
63
85
  const programs = await tier0.stream.programs.list({ page: 1, size: 20 });
64
86
  ```
65
87
 
66
- HTTP Source 统一使用 `protocol: 'http-api'`,显式设置 `config.role: 'client'`(主动请求)或 `config.role: 'server'`(接收入站请求),与 Enterprise 一协议两角色保持一致;Cloud 管理文档的角色位于 config 内。Server 不能作为 Client 发起主动请求。HTTPServer 使用固定前缀 `/ingest/v1/{workspaceId}/{sourceId}`,业务路由注册在 Stream;普通返回在处理和提交完成后回复;HTTP `onRequest` 可通过一次 `await ctx.reply(...)` 先回复再继续,仍受超时、并发和权限限制,回复后不随客户端断线取消但可由 shutdown 取消,不保证崩溃重放。202 状态本身不证明处理完成。示例见 [HTTPServer Stream Skill](skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/http-server.md)。使用 `source.protocols.list({})` 核对目标环境支持,再通过现有 `source.documents.*` 管理配置。HTTP Client 单条 inline 创建支持 Basic、Bearer、APIKey、OAuth 四类认证,凭据默认绑定 Source 基址 REQUEST,显式方法继续保留限制;独立 credentialCreate 仍为 coreOnly。SDK 不新增猜测的 HTTP In API;npm 管理 SDK 与执行器中的 Goja Stream 脚本 API 分开使用。
88
+ HTTP Source 统一使用 `protocol: 'http-api'`,显式设置 `config.role: 'client'`(主动请求)或 `config.role: 'server'`(接收入站请求),与 Enterprise 一协议两角色保持一致;Cloud 管理文档的角色位于 config 内。Server 不能作为 Client 发起主动请求。HTTPServer 使用固定前缀 `/ingest/v1/{workspaceId}/{sourceId}`,业务路由注册在 Stream;普通返回在处理和提交完成后回复;HTTP `onRequest` 可通过一次 `await ctx.reply(...)` 先回复再继续,仍受超时、并发和权限限制,回复后不随客户端断线取消但可由 shutdown 取消,不保证崩溃重放。202 状态本身不证明处理完成。示例见 [HTTPServer Stream Skill](skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/http-server.md)。使用 `source.protocols.list({})` 核对目标环境支持,再通过现有 `source.documents.*` 管理配置。HTTP Client 单条 inline 创建支持 Basic、Bearer、APIKey、OAuth 四类认证;普通创建省略 credentials.method,由服务端默认 REQUEST 基址绑定,真实 method/path/query 在 Stream 定义。Basic/Bearer 显式凭据方法同时限制精确 URL,OAuth 旧 GET 保留既有兼容语义,存量限制不自动扩大;独立 credentialCreate 仍为 coreOnly。SDK 不新增猜测的 HTTP In API;npm 管理 SDK 与执行器中的 Goja Stream 脚本 API 分开使用。
67
89
 
68
90
  Source/Stream 仍保留 `{ code, msg, requestId, data }` 响应以及 `UnsV2Error` 错误类型。Source 配置统一使用 `source.documents`;Stream 草稿统一通过 `stream.documents` 创建、读取、校验和修改,输入 `program` 与 `document` 二选一。发布和回滚仍走 `stream.programs`。保存、部署、运行成功分别判断。
69
91
 
@@ -71,7 +93,9 @@ Source/Stream 仍保留 `{ code, msg, requestId, data }` 响应以及 `UnsV2Erro
71
93
  - Stream 创建/更新回执的 revision 可直接用于发布;[发布回执](skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/deploy.md) 的 activeRelease 用于观察这次发布,无需前后各查询一次。
72
94
  - 单条 Record 新增可用 [returnDocument:'after'](skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/create.md) 同次取得创建快照;[App 数据层](skills/tier0-sdk-v2/tier0-sdk-v2-data/references/read-write.md) 支持相同选择及投影类型。
73
95
 
74
- 随包提供 Skill:总入口 [tier0-sdk-v2](skills/tier0-sdk-v2/SKILL.md) 下嵌套 11 个领域子 Skill(`skills/tier0-sdk-v2/tier0-sdk-v2-<领域>/`),每个仍可独立发现,包含完整流程、参数边界、错误处理与可类型检查的示例:[Source](skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md)、[Stream](skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md)、[UNS](skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md)、[通知](skills/tier0-sdk-v2/tier0-sdk-v2-notifications/SKILL.md)、[系统](skills/tier0-sdk-v2/tier0-sdk-v2-system/SKILL.md)、[文件](skills/tier0-sdk-v2/tier0-sdk-v2-files/SKILL.md)、[MQTT](skills/tier0-sdk-v2/tier0-sdk-v2-mq/SKILL.md)、[成员](skills/tier0-sdk-v2/tier0-sdk-v2-members/SKILL.md)、[Controls](skills/tier0-sdk-v2/tier0-sdk-v2-controls/SKILL.md)、[Agent](skills/tier0-sdk-v2/tier0-sdk-v2-agent/SKILL.md)、[App 数据](skills/tier0-sdk-v2/tier0-sdk-v2-data/SKILL.md)。复杂流程的参考文档随 Skill 一起打包。在 Tier0 Console 上传时,把整个 `skills/tier0-sdk-v2/` 目录打成一个 zip。
96
+ 从最初提交迁移:`uns.sourceList` → `source.documents.list`;`uns.sourceDocumentGet` → `source.documents.get`;`uns.streamProgramDeploy` → `stream.programs.deploy`;`uns.streamDocumentValidate` → `stream.documents.validate`。这些管理方法已移出主入口的 `uns`。底层 `createUnsV2Client()` 仍提供完整生成契约供契约工具使用;数据专用客户端可用 `createUnsDataClient()`。
97
+
98
+ 随包提供 Skill:总入口 [tier0-sdk-v2](skills/tier0-sdk-v2/SKILL.md) 下嵌套 10 个领域子 Skill(`skills/tier0-sdk-v2/tier0-sdk-v2-<领域>/`),每个仍可独立发现,包含完整流程、参数边界、错误处理与可类型检查的示例:[Source](skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md)、[Stream](skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md)、[UNS](skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md)、[通知](skills/tier0-sdk-v2/tier0-sdk-v2-notifications/SKILL.md)、[系统](skills/tier0-sdk-v2/tier0-sdk-v2-system/SKILL.md)、[文件](skills/tier0-sdk-v2/tier0-sdk-v2-files/SKILL.md)、[MQTT](skills/tier0-sdk-v2/tier0-sdk-v2-mq/SKILL.md)、[成员](skills/tier0-sdk-v2/tier0-sdk-v2-members/SKILL.md)、[Agent](skills/tier0-sdk-v2/tier0-sdk-v2-agent/SKILL.md)、[App 数据](skills/tier0-sdk-v2/tier0-sdk-v2-data/SKILL.md)。复杂流程的参考文档随 Skill 一起打包。在 Tier0 Console 上传时,把整个 `skills/tier0-sdk-v2/` 目录打成一个 zip。
75
99
 
76
100
  ## UNS 数据访问
77
101
 
@@ -89,13 +113,15 @@ await tier0.uns.recordFind(
89
113
  );
90
114
  ```
91
115
 
116
+ 能力发现只校验本包的 Namespace/Source/Stream 管理合同,不要求全局交互标签;其他 SDK 的可选交互能力不阻断 Namespace。核心合同未知仍拒绝,不将方法存在当作授权或运行就绪。
117
+
92
118
  实际集合 ID 和有效权限从平台配置/数据上下文取得。管理操作中,App 凭证只能调用本 App 集合的 `appCollectionsEnsure` / `appCollectionsSchemaReplace` / `appCollectionsArchive` / `appCollectionsRestore`;SDK 中存在 `metadataInsertOne` 等其他管理方法,不表示 App 凭证有对应权限。App 数据授权 `appDataPolicyGet` / `appDataPolicyUpdate` 的调用方必须是:持有 `uns.write` 的登录会话、持有 `uns.write` 且 full_access、不绑定 App 的 personal / agent Key,或治理会话;运行时 App 凭证不能管理授权。Core-only 后台接口不导出到公开 SDK。
93
119
 
94
- UNS 保留 `{ code, msg, requestId, data }` 完整响应。平台 v2 包装接口返回已解包的 `data`,通知/能力发现返回直接对象,Control 外观解包 UNS 回执并保留直接结果对象。业务错误即使 HTTP 为 200 也会抛出 `ApiError`。
120
+ UNS 保留 `{ code, msg, requestId, data }` 完整响应。平台 v2 包装接口返回已解包的 `data`,通知/能力发现返回直接对象。业务错误即使 HTTP 为 200 也会抛出 `ApiError`。
95
121
 
96
122
  `int64` 和平台整数字段使用 `number | bigint`:安全范围内返回 number,超出范围返回 bigint。UNS 任意 JSON 中无法无损表示的数字用 `UnsV2RawNumber`;传回 SDK 可保持原值。对外输出 JSON 时自行确定 bigint/精确数字的表示,不要直接 `JSON.stringify` 包含这些值的对象。
97
123
 
98
- `createClient()` 的 HTTP 操作不自动重试。UNS v2 错误带 `execution`(`notStarted` / `rolledBack` / `committed` / `unknown`)与 `retry: { safe, afterMs? }`:`safe` 表示可以用同一请求(同一幂等键)重发。`execution` 为 `unknown` 时抛出 `UnsV2OutcomeUnknownError`;它与 `ControlResultUnknownError`、`ApiError.outcomeUnknown` 一样表示写操作可能已执行,先读回对账,按业务意图保留原幂等键,不自动生成新键重放。查询与写入均可受配置超时约束。App 数据层 `@tier0/sdk-v2/data` 另有自己的策略:每次调用从开始算最多 25 秒(含排队与重试)、每进程最多 6 个并发请求、写入自动生成幂等键、按 `retry.safe` 最多自动重试 2 次;`runWithRequestContext(request, …)` 传入请求本身时,请求中止后排队中的调用不再发出。
124
+ `createClient()` 的 HTTP 操作不自动重试。UNS v2 错误带 `execution`(`notStarted` / `rolledBack` / `committed` / `unknown`)与 `retry: { safe, afterMs? }`:`safe` 表示可以用同一请求(同一幂等键)重发。`execution` 为 `unknown` 时抛出 `UnsV2OutcomeUnknownError`;它与 `ApiError.outcomeUnknown` 一样表示写操作可能已执行,先读回对账,按业务意图保留原幂等键,不自动生成新键重放。查询与写入均可受配置超时约束。App 数据层 `@tier0/sdk-v2/data` 另有自己的策略:每次调用从开始算最多 25 秒(含排队与重试)、每进程最多 6 个并发请求、写入自动生成幂等键、按 `retry.safe` 最多自动重试 2 次;`runWithRequestContext(request, …)` 传入请求本身时,请求中止后排队中的调用不再发出。
99
125
 
100
126
  ## 通知
101
127
 
@@ -1,20 +1,36 @@
1
1
  import { type CloudTransportConfig } from './cloud-transport.js';
2
2
  import { type HttpClient } from './openapi/client.js';
3
- export type CapabilityCode = 'namespace.v2' | 'source' | 'stream' | 'control.v1' | 'control.invoke.v1';
3
+ export type CapabilityCode = 'namespace.v2' | 'source' | 'stream';
4
4
  export type CapabilityState = 'disabled' | 'not_supported' | 'unavailable' | 'readiness_unknown' | 'ready';
5
5
  export type CapabilityAvailability = 'unavailable' | 'unknown' | 'available';
6
- export interface PublicCapability {
6
+ export interface CapabilityDiagnostics {
7
+ reasonCode?: string;
8
+ checkedAt?: string;
9
+ validUntil?: string;
10
+ retryAfterMs?: number;
11
+ }
12
+ export interface CapabilityOperation extends CapabilityDiagnostics {
13
+ operation: string;
14
+ releaseEnabled: boolean;
15
+ enabled: boolean;
16
+ allowed: boolean;
17
+ state: CapabilityState;
18
+ availability: CapabilityAvailability;
19
+ requiresResourceCheck: boolean;
20
+ }
21
+ export interface PublicCapability extends CapabilityDiagnostics {
7
22
  code: CapabilityCode;
8
23
  /** Public release and workspace gates; does not establish runtime readiness. */
9
24
  releaseEnabled: boolean;
10
25
  /** Server-assessed implementation/readiness, never inferred from releaseEnabled. */
11
26
  enabled: boolean;
12
- /** Authorization summary, not a grant for every individual Control code. */
27
+ /** Authorization summary, not authorization for an individual operation. */
13
28
  allowed: boolean;
14
29
  state: CapabilityState;
15
30
  /** Not device online status or execution/ACK confirmation. */
16
31
  availability: CapabilityAvailability;
17
32
  contractVersions: string[];
33
+ operations?: CapabilityOperation[];
18
34
  }
19
35
  export interface CapabilityDeprecation {
20
36
  contract: string;
@@ -22,7 +38,7 @@ export interface CapabilityDeprecation {
22
38
  sunsetAt?: string;
23
39
  }
24
40
  export interface CapabilityDiscoverResponse {
25
- product: 'cloud';
41
+ product: 'cloud' | 'enterprise';
26
42
  /** Trusted server configuration only; absent when unconfigured. */
27
43
  productVersion?: string;
28
44
  contractVersion: '1.0';
@@ -19,8 +19,6 @@ const contracts = {
19
19
  'namespace.v2': ['openapi/v2'],
20
20
  'source': ['openapi/v2'],
21
21
  'stream': ['openapi/v2'],
22
- 'control.v1': ['openapi/v1', 'control/v1'],
23
- 'control.invoke.v1': ['openapi/v1', 'control/v1'],
24
22
  };
25
23
  function record(value) {
26
24
  return value !== null && typeof value === 'object' && !Array.isArray(value);
@@ -31,6 +29,67 @@ function text(value) {
31
29
  function strings(value) {
32
30
  return Array.isArray(value) && value.every(text) && new Set(value).size === value.length;
33
31
  }
32
+ function diagnostics(value, fail) {
33
+ const result = {};
34
+ for (const field of ['reasonCode', 'checkedAt', 'validUntil']) {
35
+ if (value[field] === undefined)
36
+ continue;
37
+ if (!text(value[field]))
38
+ return fail();
39
+ if (field !== 'reasonCode' && (!/^\d{4}-\d\d-\d\d[Tt]\d\d:\d\d:\d\d(?:\.\d+)?(?:[Zz]|[+-]\d\d:\d\d)$/.test(value[field]) ||
40
+ !Number.isFinite(Date.parse(value[field]))))
41
+ return fail();
42
+ result[field] = value[field];
43
+ }
44
+ if (value.retryAfterMs !== undefined) {
45
+ if (typeof value.retryAfterMs !== 'number' || !Number.isSafeInteger(value.retryAfterMs) || value.retryAfterMs < 0)
46
+ return fail();
47
+ result.retryAfterMs = value.retryAfterMs;
48
+ }
49
+ if (result.validUntil !== undefined && (value.state !== 'ready' || result.checkedAt === undefined ||
50
+ Date.parse(result.validUntil) <= Date.parse(result.checkedAt)))
51
+ return fail();
52
+ return result;
53
+ }
54
+ const sourceOperations = ['read', 'configure', 'test', 'discover', 'enable', 'disable'];
55
+ const streamOperations = ['read', 'configure', 'validate', 'deploy', 'execute', 'disable'];
56
+ const resourceOperations = {
57
+ source: ['test', 'discover', 'enable'],
58
+ stream: ['deploy', 'execute'],
59
+ };
60
+ function operationFields(value, code, fail) {
61
+ if (value.operations === undefined)
62
+ return {};
63
+ if (!Array.isArray(value.operations))
64
+ return fail();
65
+ const operations = [];
66
+ const supported = code === 'source' ? sourceOperations : code === 'stream' ? streamOperations : [];
67
+ const seen = new Set();
68
+ for (const item of value.operations) {
69
+ if (!record(item) || !text(item.operation))
70
+ return fail();
71
+ if (!supported.includes(item.operation))
72
+ continue;
73
+ if (seen.has(item.operation))
74
+ return fail();
75
+ seen.add(item.operation);
76
+ const ready = item.state === 'ready';
77
+ const expected = ready ? 'available' : item.state === 'readiness_unknown' ? 'unknown' : 'unavailable';
78
+ if (typeof item.releaseEnabled !== 'boolean' || typeof item.enabled !== 'boolean' || typeof item.allowed !== 'boolean' ||
79
+ typeof item.requiresResourceCheck !== 'boolean' ||
80
+ (resourceOperations[code]?.includes(item.operation) && !item.requiresResourceCheck) ||
81
+ (value.releaseEnabled === false && item.releaseEnabled !== false) ||
82
+ !['disabled', 'not_supported', 'unavailable', 'readiness_unknown', 'ready'].includes(item.state) ||
83
+ item.availability !== expected || item.enabled !== ready ||
84
+ (ready && (!item.releaseEnabled || !item.allowed)) ||
85
+ (item.state === 'disabled' ? item.releaseEnabled : !item.releaseEnabled))
86
+ return fail();
87
+ operations.push({ operation: item.operation, releaseEnabled: item.releaseEnabled, enabled: item.enabled,
88
+ allowed: item.allowed, state: item.state, availability: item.availability,
89
+ requiresResourceCheck: item.requiresResourceCheck, ...diagnostics(item, fail) });
90
+ }
91
+ return { operations };
92
+ }
34
93
  /** Validate and explicitly project the frozen contract; unknown capabilities/extension fields are ignored. */
35
94
  function discovery(value, status) {
36
95
  const fail = (version = false) => {
@@ -45,9 +104,8 @@ function discovery(value, status) {
45
104
  !Array.isArray(value.capabilities) || !Array.isArray(value.deprecations) ||
46
105
  (value.productVersion !== undefined && !text(value.productVersion)))
47
106
  return fail();
48
- if (value.product !== 'cloud' || value.contractVersion !== '1.0' ||
49
- !value.apiContractVersions.includes('openapi/v2') ||
50
- !value.sdkContractVersions.includes('control/v1'))
107
+ if (!['cloud', 'enterprise'].includes(value.product) || value.contractVersion !== '1.0' ||
108
+ !value.apiContractVersions.includes('openapi/v2'))
51
109
  return fail(true);
52
110
  const capabilities = [];
53
111
  const seen = new Set();
@@ -77,6 +135,8 @@ function discovery(value, status) {
77
135
  code, releaseEnabled: item.releaseEnabled, enabled: item.enabled, allowed: item.allowed,
78
136
  state: item.state, availability: item.availability,
79
137
  contractVersions: [...item.contractVersions],
138
+ ...diagnostics(item, fail),
139
+ ...operationFields(item, code, fail),
80
140
  });
81
141
  }
82
142
  const deprecations = [];
@@ -91,7 +151,7 @@ function discovery(value, status) {
91
151
  });
92
152
  }
93
153
  return {
94
- product: 'cloud', ...(value.productVersion === undefined ? {} : { productVersion: value.productVersion }),
154
+ product: value.product, ...(value.productVersion === undefined ? {} : { productVersion: value.productVersion }),
95
155
  contractVersion: '1.0', apiContractVersions: [...value.apiContractVersions],
96
156
  sdkContractVersions: [...value.sdkContractVersions],
97
157
  capabilities, deprecations,
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["import { CloudTransport, CloudTransportError, type CloudTransportConfig } from './cloud-transport.js';\nimport { getClient, type HttpClient } from './openapi/client.js';\n\nexport type CapabilityCode = 'namespace.v2' | 'source' | 'stream' | 'control.v1' | 'control.invoke.v1';\nexport type CapabilityState = 'disabled' | 'not_supported' | 'unavailable' | 'readiness_unknown' | 'ready';\nexport type CapabilityAvailability = 'unavailable' | 'unknown' | 'available';\n\nexport interface PublicCapability {\n code: CapabilityCode;\n /** Public release and workspace gates; does not establish runtime readiness. */\n releaseEnabled: boolean;\n /** Server-assessed implementation/readiness, never inferred from releaseEnabled. */\n enabled: boolean;\n /** Authorization summary, not a grant for every individual Control code. */\n allowed: boolean;\n state: CapabilityState;\n /** Not device online status or execution/ACK confirmation. */\n availability: CapabilityAvailability;\n contractVersions: string[];\n}\n\nexport interface CapabilityDeprecation {\n contract: string;\n replacement?: string;\n sunsetAt?: string;\n}\n\nexport interface CapabilityDiscoverResponse {\n product: 'cloud';\n /** Trusted server configuration only; absent when unconfigured. */\n productVersion?: string;\n contractVersion: '1.0';\n apiContractVersions: string[];\n /** Public SDK contract labels, not npm package versions. */\n sdkContractVersions: string[];\n capabilities: PublicCapability[];\n deprecations: CapabilityDeprecation[];\n}\n\nexport interface CapabilityErrorInfo {\n status?: number;\n /** Gateway string code (including unknown future codes), or an SDK-local CAPABILITY_* code. */\n errorCode: string;\n}\n\nexport class CapabilityError extends Error {\n readonly status?: number;\n readonly errorCode: string;\n readonly retryable = false;\n\n constructor(message: string, info: CapabilityErrorInfo) {\n super(message);\n this.name = 'CapabilityError';\n this.status = info.status;\n this.errorCode = info.errorCode;\n }\n}\n\nconst contracts: Record<CapabilityCode, string[]> = {\n 'namespace.v2': ['openapi/v2'],\n 'source': ['openapi/v2'],\n 'stream': ['openapi/v2'],\n 'control.v1': ['openapi/v1', 'control/v1'],\n 'control.invoke.v1': ['openapi/v1', 'control/v1'],\n};\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\nfunction text(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\nfunction strings(value: unknown): value is string[] {\n return Array.isArray(value) && value.every(text) && new Set(value).size === value.length;\n}\n\n/** Validate and explicitly project the frozen contract; unknown capabilities/extension fields are ignored. */\nfunction discovery(value: unknown, status: number): CapabilityDiscoverResponse {\n const fail = (version = false): never => {\n throw new CapabilityError(version ? 'Unsupported capability contract version.' : 'Invalid capability discovery response.', {\n status, errorCode: version ? 'CAPABILITY_UNSUPPORTED_VERSION' : 'CAPABILITY_PROTOCOL_ERROR',\n });\n };\n if (!record(value)) return fail();\n if (!text(value.product) || !text(value.contractVersion) ||\n !strings(value.apiContractVersions) || !strings(value.sdkContractVersions) ||\n !Array.isArray(value.capabilities) || !Array.isArray(value.deprecations) ||\n (value.productVersion !== undefined && !text(value.productVersion))) return fail();\n if (value.product !== 'cloud' || value.contractVersion !== '1.0' ||\n !value.apiContractVersions.includes('openapi/v2') ||\n !value.sdkContractVersions.includes('control/v1')) return fail(true);\n\n const capabilities: PublicCapability[] = [];\n const seen = new Set<string>();\n for (const item of value.capabilities) {\n if (!record(item) || !text(item.code)) return fail();\n if (!Object.prototype.hasOwnProperty.call(contracts, item.code)) continue;\n const code = item.code as CapabilityCode;\n if (seen.has(code)) return fail();\n seen.add(code);\n if (typeof item.releaseEnabled !== 'boolean' || typeof item.enabled !== 'boolean' || typeof item.allowed !== 'boolean' ||\n !['disabled', 'not_supported', 'unavailable', 'readiness_unknown', 'ready'].includes(item.state as string) ||\n !['unavailable', 'unknown', 'available'].includes(item.availability as string) || !strings(item.contractVersions)) return fail();\n if (contracts[code].some(version =>\n !(item.contractVersions as string[]).includes(version) ||\n (version.startsWith('openapi/') && !(value.apiContractVersions as string[]).includes(version)))) return fail(true);\n const ready = item.state === 'ready';\n const expectedAvailability = ready ? 'available' : item.state === 'readiness_unknown' ? 'unknown' : 'unavailable';\n if (item.enabled !== ready || item.availability !== expectedAvailability ||\n (ready && (!item.releaseEnabled || !item.allowed)) ||\n (item.state === 'disabled' ? item.releaseEnabled : !item.releaseEnabled)) return fail();\n capabilities.push({\n code, releaseEnabled: item.releaseEnabled, enabled: item.enabled, allowed: item.allowed,\n state: item.state as CapabilityState, availability: item.availability as CapabilityAvailability,\n contractVersions: [...item.contractVersions],\n });\n }\n const deprecations: CapabilityDeprecation[] = [];\n for (const item of value.deprecations) {\n if (!record(item) || !text(item.contract) ||\n (item.replacement !== undefined && !text(item.replacement)) ||\n (item.sunsetAt !== undefined && !text(item.sunsetAt))) return fail();\n deprecations.push({ contract: item.contract,\n ...(item.replacement === undefined ? {} : { replacement: item.replacement as string }),\n ...(item.sunsetAt === undefined ? {} : { sunsetAt: item.sunsetAt as string }),\n });\n }\n return {\n product: 'cloud', ...(value.productVersion === undefined ? {} : { productVersion: value.productVersion as string }),\n contractVersion: '1.0', apiContractVersions: [...value.apiContractVersions],\n sdkContractVersions: [...value.sdkContractVersions],\n capabilities, deprecations,\n };\n}\n\nexport class CapabilitiesClient {\n private readonly transport: CloudTransport;\n\n constructor(resolveClient: () => HttpClient = getClient, config: CloudTransportConfig = {}) {\n this.transport = new CloudTransport(resolveClient, config);\n }\n\n /** Workspace comes exclusively from the authenticated key. One POST, no automatic retries or caching. */\n async discover(): Promise<CapabilityDiscoverResponse> {\n if (arguments.length !== 0) throw new TypeError('Tier0 SDK: capability discovery accepts no arguments.');\n let response: Awaited<ReturnType<CloudTransport['post']>>;\n try {\n response = await this.transport.post('/openapi/v2/capabilities/discover', {});\n } catch (error) {\n if (!(error instanceof CloudTransportError)) throw error;\n throw new CapabilityError('Capability discovery HTTP exchange failed.', {\n status: error.status, errorCode: `CAPABILITY_${error.kind}`,\n });\n }\n const { value, status, ok } = response;\n if (!ok) {\n if (!record(value) || !text(value.errorCode) || typeof value.message !== 'string') {\n throw new CapabilityError('Invalid capability error response.', { status, errorCode: 'CAPABILITY_PROTOCOL_ERROR' });\n }\n throw new CapabilityError(value.message, { status, errorCode: value.errorCode });\n }\n return discovery(value, status);\n }\n}\n\n/** Uses configureClient()/runtime environment, resolving the host and workspace key on every call. */\nexport const capabilities = new CapabilitiesClient();\n"]}
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["import { CloudTransport, CloudTransportError, type CloudTransportConfig } from './cloud-transport.js';\nimport { getClient, type HttpClient } from './openapi/client.js';\n\nexport type CapabilityCode = 'namespace.v2' | 'source' | 'stream';\nexport type CapabilityState = 'disabled' | 'not_supported' | 'unavailable' | 'readiness_unknown' | 'ready';\nexport type CapabilityAvailability = 'unavailable' | 'unknown' | 'available';\n\nexport interface CapabilityDiagnostics {\n reasonCode?: string;\n checkedAt?: string;\n validUntil?: string;\n retryAfterMs?: number;\n}\n\nexport interface CapabilityOperation extends CapabilityDiagnostics {\n operation: string;\n releaseEnabled: boolean;\n enabled: boolean;\n allowed: boolean;\n state: CapabilityState;\n availability: CapabilityAvailability;\n requiresResourceCheck: boolean;\n}\n\nexport interface PublicCapability extends CapabilityDiagnostics {\n code: CapabilityCode;\n /** Public release and workspace gates; does not establish runtime readiness. */\n releaseEnabled: boolean;\n /** Server-assessed implementation/readiness, never inferred from releaseEnabled. */\n enabled: boolean;\n /** Authorization summary, not authorization for an individual operation. */\n allowed: boolean;\n state: CapabilityState;\n /** Not device online status or execution/ACK confirmation. */\n availability: CapabilityAvailability;\n contractVersions: string[];\n operations?: CapabilityOperation[];\n}\n\nexport interface CapabilityDeprecation {\n contract: string;\n replacement?: string;\n sunsetAt?: string;\n}\n\nexport interface CapabilityDiscoverResponse {\n product: 'cloud' | 'enterprise';\n /** Trusted server configuration only; absent when unconfigured. */\n productVersion?: string;\n contractVersion: '1.0';\n apiContractVersions: string[];\n /** Public SDK contract labels, not npm package versions. */\n sdkContractVersions: string[];\n capabilities: PublicCapability[];\n deprecations: CapabilityDeprecation[];\n}\n\nexport interface CapabilityErrorInfo {\n status?: number;\n /** Gateway string code (including unknown future codes), or an SDK-local CAPABILITY_* code. */\n errorCode: string;\n}\n\nexport class CapabilityError extends Error {\n readonly status?: number;\n readonly errorCode: string;\n readonly retryable = false;\n\n constructor(message: string, info: CapabilityErrorInfo) {\n super(message);\n this.name = 'CapabilityError';\n this.status = info.status;\n this.errorCode = info.errorCode;\n }\n}\n\nconst contracts: Record<CapabilityCode, string[]> = {\n 'namespace.v2': ['openapi/v2'],\n 'source': ['openapi/v2'],\n 'stream': ['openapi/v2'],\n};\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\nfunction text(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\nfunction strings(value: unknown): value is string[] {\n return Array.isArray(value) && value.every(text) && new Set(value).size === value.length;\n}\n\n\nfunction diagnostics(value: Record<string, unknown>, fail: () => never): CapabilityDiagnostics {\n const result: CapabilityDiagnostics = {};\n for (const field of ['reasonCode', 'checkedAt', 'validUntil'] as const) {\n if (value[field] === undefined) continue;\n if (!text(value[field])) return fail();\n if (field !== 'reasonCode' && (!/^\\d{4}-\\d\\d-\\d\\d[Tt]\\d\\d:\\d\\d:\\d\\d(?:\\.\\d+)?(?:[Zz]|[+-]\\d\\d:\\d\\d)$/.test(value[field]) ||\n !Number.isFinite(Date.parse(value[field])))) return fail();\n result[field] = value[field];\n }\n if (value.retryAfterMs !== undefined) {\n if (typeof value.retryAfterMs !== 'number' || !Number.isSafeInteger(value.retryAfterMs) || value.retryAfterMs < 0) return fail();\n result.retryAfterMs = value.retryAfterMs;\n }\n if (result.validUntil !== undefined && (value.state !== 'ready' || result.checkedAt === undefined ||\n Date.parse(result.validUntil) <= Date.parse(result.checkedAt))) return fail();\n return result;\n}\n\nconst sourceOperations = ['read', 'configure', 'test', 'discover', 'enable', 'disable'];\nconst streamOperations = ['read', 'configure', 'validate', 'deploy', 'execute', 'disable'];\nconst resourceOperations: Partial<Record<CapabilityCode, readonly string[]>> = {\n source: ['test', 'discover', 'enable'],\n stream: ['deploy', 'execute'],\n};\n\nfunction operationFields(value: Record<string, unknown>, code: CapabilityCode, fail: () => never): { operations?: CapabilityOperation[] } {\n if (value.operations === undefined) return {};\n if (!Array.isArray(value.operations)) return fail();\n const operations: CapabilityOperation[] = [];\n const supported = code === 'source' ? sourceOperations : code === 'stream' ? streamOperations : [];\n const seen = new Set<string>();\n for (const item of value.operations) {\n if (!record(item) || !text(item.operation)) return fail();\n if (!supported.includes(item.operation)) continue;\n if (seen.has(item.operation)) return fail();\n seen.add(item.operation);\n const ready = item.state === 'ready';\n const expected = ready ? 'available' : item.state === 'readiness_unknown' ? 'unknown' : 'unavailable';\n if (typeof item.releaseEnabled !== 'boolean' || typeof item.enabled !== 'boolean' || typeof item.allowed !== 'boolean' ||\n typeof item.requiresResourceCheck !== 'boolean' ||\n (resourceOperations[code]?.includes(item.operation) && !item.requiresResourceCheck) ||\n (value.releaseEnabled === false && item.releaseEnabled !== false) ||\n !['disabled', 'not_supported', 'unavailable', 'readiness_unknown', 'ready'].includes(item.state as string) ||\n item.availability !== expected || item.enabled !== ready ||\n (ready && (!item.releaseEnabled || !item.allowed)) ||\n (item.state === 'disabled' ? item.releaseEnabled : !item.releaseEnabled)) return fail();\n operations.push({operation: item.operation, releaseEnabled: item.releaseEnabled, enabled: item.enabled,\n allowed: item.allowed, state: item.state as CapabilityState, availability: item.availability as CapabilityAvailability,\n requiresResourceCheck: item.requiresResourceCheck, ...diagnostics(item, fail)});\n }\n return { operations };\n}\n\n/** Validate and explicitly project the frozen contract; unknown capabilities/extension fields are ignored. */\nfunction discovery(value: unknown, status: number): CapabilityDiscoverResponse {\n const fail = (version = false): never => {\n throw new CapabilityError(version ? 'Unsupported capability contract version.' : 'Invalid capability discovery response.', {\n status, errorCode: version ? 'CAPABILITY_UNSUPPORTED_VERSION' : 'CAPABILITY_PROTOCOL_ERROR',\n });\n };\n if (!record(value)) return fail();\n if (!text(value.product) || !text(value.contractVersion) ||\n !strings(value.apiContractVersions) || !strings(value.sdkContractVersions) ||\n !Array.isArray(value.capabilities) || !Array.isArray(value.deprecations) ||\n (value.productVersion !== undefined && !text(value.productVersion))) return fail();\n if (!['cloud', 'enterprise'].includes(value.product) || value.contractVersion !== '1.0' ||\n !value.apiContractVersions.includes('openapi/v2')) return fail(true);\n\n const capabilities: PublicCapability[] = [];\n const seen = new Set<string>();\n for (const item of value.capabilities) {\n if (!record(item) || !text(item.code)) return fail();\n if (!Object.prototype.hasOwnProperty.call(contracts, item.code)) continue;\n const code = item.code as CapabilityCode;\n if (seen.has(code)) return fail();\n seen.add(code);\n if (typeof item.releaseEnabled !== 'boolean' || typeof item.enabled !== 'boolean' || typeof item.allowed !== 'boolean' ||\n !['disabled', 'not_supported', 'unavailable', 'readiness_unknown', 'ready'].includes(item.state as string) ||\n !['unavailable', 'unknown', 'available'].includes(item.availability as string) || !strings(item.contractVersions)) return fail();\n if (contracts[code].some(version =>\n !(item.contractVersions as string[]).includes(version) ||\n (version.startsWith('openapi/') && !(value.apiContractVersions as string[]).includes(version)))) return fail(true);\n const ready = item.state === 'ready';\n const expectedAvailability = ready ? 'available' : item.state === 'readiness_unknown' ? 'unknown' : 'unavailable';\n if (item.enabled !== ready || item.availability !== expectedAvailability ||\n (ready && (!item.releaseEnabled || !item.allowed)) ||\n (item.state === 'disabled' ? item.releaseEnabled : !item.releaseEnabled)) return fail();\n capabilities.push({\n code, releaseEnabled: item.releaseEnabled, enabled: item.enabled, allowed: item.allowed,\n state: item.state as CapabilityState, availability: item.availability as CapabilityAvailability,\n contractVersions: [...item.contractVersions],\n ...diagnostics(item, fail),\n ...operationFields(item, code, fail),\n });\n }\n const deprecations: CapabilityDeprecation[] = [];\n for (const item of value.deprecations) {\n if (!record(item) || !text(item.contract) ||\n (item.replacement !== undefined && !text(item.replacement)) ||\n (item.sunsetAt !== undefined && !text(item.sunsetAt))) return fail();\n deprecations.push({ contract: item.contract,\n ...(item.replacement === undefined ? {} : { replacement: item.replacement as string }),\n ...(item.sunsetAt === undefined ? {} : { sunsetAt: item.sunsetAt as string }),\n });\n }\n return {\n product: value.product as CapabilityDiscoverResponse['product'], ...(value.productVersion === undefined ? {} : { productVersion: value.productVersion as string }),\n contractVersion: '1.0', apiContractVersions: [...value.apiContractVersions],\n sdkContractVersions: [...value.sdkContractVersions],\n capabilities, deprecations,\n };\n}\n\nexport class CapabilitiesClient {\n private readonly transport: CloudTransport;\n\n constructor(resolveClient: () => HttpClient = getClient, config: CloudTransportConfig = {}) {\n this.transport = new CloudTransport(resolveClient, config);\n }\n\n /** Workspace comes exclusively from the authenticated key. One POST, no automatic retries or caching. */\n async discover(): Promise<CapabilityDiscoverResponse> {\n if (arguments.length !== 0) throw new TypeError('Tier0 SDK: capability discovery accepts no arguments.');\n let response: Awaited<ReturnType<CloudTransport['post']>>;\n try {\n response = await this.transport.post('/openapi/v2/capabilities/discover', {});\n } catch (error) {\n if (!(error instanceof CloudTransportError)) throw error;\n throw new CapabilityError('Capability discovery HTTP exchange failed.', {\n status: error.status, errorCode: `CAPABILITY_${error.kind}`,\n });\n }\n const { value, status, ok } = response;\n if (!ok) {\n if (!record(value) || !text(value.errorCode) || typeof value.message !== 'string') {\n throw new CapabilityError('Invalid capability error response.', { status, errorCode: 'CAPABILITY_PROTOCOL_ERROR' });\n }\n throw new CapabilityError(value.message, { status, errorCode: value.errorCode });\n }\n return discovery(value, status);\n }\n}\n\n/** Uses configureClient()/runtime environment, resolving the host and workspace key on every call. */\nexport const capabilities = new CapabilitiesClient();\n"]}
@@ -1,5 +1,4 @@
1
1
  import { type ClientConfig } from './openapi/client.js';
2
- import { ControlsClient } from './controls.js';
3
2
  import { CapabilitiesClient } from './capabilities.js';
4
3
  import { FilesClient } from './files.js';
5
4
  import type { CloudTransportConfig } from './cloud-transport.js';
@@ -199,7 +198,6 @@ export declare function createClient(config?: Tier0ClientConfig): Readonly<{
199
198
  };
200
199
  files: FilesClient;
201
200
  capabilities: CapabilitiesClient;
202
- controls: ControlsClient;
203
201
  source: Readonly<{
204
202
  delete: (request: import("./index.js").CloudSourceDeleteReq, options?: import("./openapi/client.js").RequestOptions) => Promise<import("./index.js").CloudSourceDeleteResponse>;
205
203
  validate: (request: import("./index.js").UnsV2SourceValidateReq, options?: import("./openapi/client.js").RequestOptions) => Promise<import("./index.js").UnsV2SourceValidateResponse>;
@@ -375,13 +373,17 @@ export declare function createClient(config?: Tier0ClientConfig): Readonly<{
375
373
  };
376
374
  capabilities: {
377
375
  discover: (options?: import("./openapi/client.js").RequestOptions) => Promise<{
378
- apiContractVersions: string[];
379
- capabilities: import("./index.js").components["schemas"]["PublicCapability"][];
380
- contractVersion: string;
381
- deprecations: import("./index.js").components["schemas"]["CapabilityDeprecation"][];
382
- product: string;
376
+ product: "cloud" | "enterprise";
383
377
  productVersion?: string;
378
+ contractVersion: "1.0";
379
+ apiContractVersions: string[];
384
380
  sdkContractVersions: string[];
381
+ capabilities: import("./index.js").components["schemas"]["CapabilityDiscoverycapability"][] & (unknown & unknown & unknown & unknown & unknown);
382
+ deprecations: {
383
+ contract: string;
384
+ replacement?: string;
385
+ sunsetAt?: string;
386
+ }[];
385
387
  }>;
386
388
  };
387
389
  agent: {
@@ -7,7 +7,6 @@ const client_js_2 = require("./uns-v2/client.js");
7
7
  const data_client_js_1 = require("./uns-v2/data-client.js");
8
8
  const source_js_1 = require("./source.js");
9
9
  const stream_js_1 = require("./stream.js");
10
- const controls_js_1 = require("./controls.js");
11
10
  const capabilities_js_1 = require("./capabilities.js");
12
11
  const files_js_1 = require("./files.js");
13
12
  /** Use a fresh instance per incoming request when supplying employee data delegation. */
@@ -25,7 +24,6 @@ function createClient(config = {}) {
25
24
  agent: api.agent,
26
25
  files: new files_js_1.FilesClient(http),
27
26
  capabilities: new capabilities_js_1.CapabilitiesClient(resolve, snapshot),
28
- controls: new controls_js_1.ControlsClient(resolve, snapshot),
29
27
  source: (0, source_js_1.bindSourceClient)(raw),
30
28
  stream: (0, stream_js_1.bindStreamClient)(raw),
31
29
  uns: (0, data_client_js_1.bindUnsDataClient)(raw),
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":";;AAaA,oCAoBC;AAjCD,mDAAoE;AACpE,iEAA2D;AAC3D,kDAAuD;AACvD,4DAA4D;AAC5D,2CAA+C;AAC/C,2CAA+C;AAC/C,+CAA+C;AAC/C,uDAAuD;AACvD,yCAAyC;AAIzC,yFAAyF;AACzF,SAAgB,YAAY,CAAC,SAA4B,EAAE;IACzD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,IAAI,sBAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,IAAA,gCAAa,EAAC,IAAI,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAA,6BAAiB,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACjD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,KAAK,EAAE,IAAI,sBAAW,CAAC,IAAI,CAAC;QAC5B,YAAY,EAAE,IAAI,oCAAkB,CAAC,OAAO,EAAE,QAAQ,CAAC;QACvD,QAAQ,EAAE,IAAI,4BAAc,CAAC,OAAO,EAAE,QAAQ,CAAC;QAC/C,MAAM,EAAE,IAAA,4BAAgB,EAAC,GAAG,CAAC;QAC7B,MAAM,EAAE,IAAA,4BAAgB,EAAC,GAAG,CAAC;QAC7B,GAAG,EAAE,IAAA,kCAAiB,EAAC,GAAG,CAAC;QAC3B,GAAG;KACJ,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { HttpClient, type ClientConfig } from './openapi/client.js';\nimport { createOpenAPI } from './openapi/api.generated.js';\nimport { createUnsV2Client } from './uns-v2/client.js';\nimport { bindUnsDataClient } from './uns-v2/data-client.js';\nimport { bindSourceClient } from './source.js';\nimport { bindStreamClient } from './stream.js';\nimport { ControlsClient } from './controls.js';\nimport { CapabilitiesClient } from './capabilities.js';\nimport { FilesClient } from './files.js';\nimport type { CloudTransportConfig } from './cloud-transport.js';\n\nexport interface Tier0ClientConfig extends ClientConfig, CloudTransportConfig {}\n/** Use a fresh instance per incoming request when supplying employee data delegation. */\nexport function createClient(config: Tier0ClientConfig = {}) {\n const snapshot = Object.freeze({ ...config });\n const http = new HttpClient(snapshot);\n const api = createOpenAPI(http);\n const resolve = () => http;\n const raw = createUnsV2Client(resolve, snapshot);\n return Object.freeze({\n system: api.system,\n members: api.members,\n notifications: api.notifications,\n mqttAuth: api.mqttAuth,\n agent: api.agent,\n files: new FilesClient(http),\n capabilities: new CapabilitiesClient(resolve, snapshot),\n controls: new ControlsClient(resolve, snapshot),\n source: bindSourceClient(raw),\n stream: bindStreamClient(raw),\n uns: bindUnsDataClient(raw),\n api,\n });\n}\nexport type Tier0Client = ReturnType<typeof createClient>;\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":";;AAYA,oCAmBC;AA/BD,mDAAoE;AACpE,iEAA2D;AAC3D,kDAAuD;AACvD,4DAA4D;AAC5D,2CAA+C;AAC/C,2CAA+C;AAC/C,uDAAuD;AACvD,yCAAyC;AAIzC,yFAAyF;AACzF,SAAgB,YAAY,CAAC,SAA4B,EAAE;IACzD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,IAAI,sBAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,IAAA,gCAAa,EAAC,IAAI,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAA,6BAAiB,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACjD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,KAAK,EAAE,IAAI,sBAAW,CAAC,IAAI,CAAC;QAC5B,YAAY,EAAE,IAAI,oCAAkB,CAAC,OAAO,EAAE,QAAQ,CAAC;QACvD,MAAM,EAAE,IAAA,4BAAgB,EAAC,GAAG,CAAC;QAC7B,MAAM,EAAE,IAAA,4BAAgB,EAAC,GAAG,CAAC;QAC7B,GAAG,EAAE,IAAA,kCAAiB,EAAC,GAAG,CAAC;QAC3B,GAAG;KACJ,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { HttpClient, type ClientConfig } from './openapi/client.js';\nimport { createOpenAPI } from './openapi/api.generated.js';\nimport { createUnsV2Client } from './uns-v2/client.js';\nimport { bindUnsDataClient } from './uns-v2/data-client.js';\nimport { bindSourceClient } from './source.js';\nimport { bindStreamClient } from './stream.js';\nimport { CapabilitiesClient } from './capabilities.js';\nimport { FilesClient } from './files.js';\nimport type { CloudTransportConfig } from './cloud-transport.js';\n\nexport interface Tier0ClientConfig extends ClientConfig, CloudTransportConfig {}\n/** Use a fresh instance per incoming request when supplying employee data delegation. */\nexport function createClient(config: Tier0ClientConfig = {}) {\n const snapshot = Object.freeze({ ...config });\n const http = new HttpClient(snapshot);\n const api = createOpenAPI(http);\n const resolve = () => http;\n const raw = createUnsV2Client(resolve, snapshot);\n return Object.freeze({\n system: api.system,\n members: api.members,\n notifications: api.notifications,\n mqttAuth: api.mqttAuth,\n agent: api.agent,\n files: new FilesClient(http),\n capabilities: new CapabilitiesClient(resolve, snapshot),\n source: bindSourceClient(raw),\n stream: bindStreamClient(raw),\n uns: bindUnsDataClient(raw),\n api,\n });\n}\nexport type Tier0Client = ReturnType<typeof createClient>;\n"]}
@@ -1,4 +1,5 @@
1
1
  import { type HttpClient, type RequestOptions } from './openapi/client.js';
2
+ import { type UnsV2OperationName, type UnsV2StreamOperationName } from './uns-v2/generated.js';
2
3
  export interface CloudTransportConfig {
3
4
  /** Whole HTTP exchange including the response body, in milliseconds; default 60,000. */
4
5
  transportTimeoutMs?: number;
@@ -33,7 +34,7 @@ export declare class CloudTransport {
33
34
  private readonly unsV2MaxResponseBytes;
34
35
  constructor(resolveClient?: () => HttpClient, config?: CloudTransportConfig);
35
36
  /** `retryAfter`: the raw `Retry-After` header, for answers without a UNS error body. */
36
- postText(path: string, body: string, options?: RequestOptions): Promise<{
37
+ postText(path: string, body: string, options?: RequestOptions, operation?: UnsV2OperationName): Promise<{
37
38
  text: string;
38
39
  status: number;
39
40
  ok: boolean;
@@ -50,7 +51,7 @@ export declare class CloudTransport {
50
51
  getEventStream(path: string, options?: {
51
52
  lastEventId?: string;
52
53
  signal?: AbortSignal;
53
- }): Promise<{
54
+ }, operation?: UnsV2StreamOperationName): Promise<{
54
55
  status: number;
55
56
  stream: ReadableStream<Uint8Array>;
56
57
  close(): void;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CloudTransport = exports.CloudTransportError = exports.UNS_V2_MAX_RESPONSE_BYTES = exports.UNS_V2_MAX_REQUEST_BYTES = exports.UNS_V2_APP_DATA_SUBJECT_HEADER = exports.DEFAULT_CLOUD_TRANSPORT_TIMEOUT_MS = void 0;
4
4
  const client_js_1 = require("./openapi/client.js");
5
+ const generated_js_1 = require("./uns-v2/generated.js");
5
6
  exports.DEFAULT_CLOUD_TRANSPORT_TIMEOUT_MS = 60_000;
6
7
  /** Header carrying `unsV2AppDataSubject`; the trusted App Gateway sets it on each business request. */
7
8
  exports.UNS_V2_APP_DATA_SUBJECT_HEADER = 'X-Tier0-App-Data-Subject';
@@ -46,16 +47,15 @@ class CloudTransport {
46
47
  this.#unsV2AppDataSubject = subject;
47
48
  }
48
49
  /** `retryAfter`: the raw `Retry-After` header, for answers without a UNS error body. */
49
- async postText(path, body, options = {}) {
50
+ async postText(path, body, options = {}, operation) {
50
51
  options.signal?.throwIfAborted();
51
52
  const client = this.resolveClient();
52
53
  const url = `${client.getBaseURL()}${path}`;
53
54
  const key = client.getApiKey();
54
55
  const headers = { 'Content-Type': 'application/json' };
55
- // Control routes also live under UNS v2, but must never receive data delegation.
56
- // Keep this per-client proof out of shared HTTP headers and Control requests.
57
- if (path.startsWith('/openapi/v2/uns/') &&
58
- !path.startsWith('/openapi/v2/uns/controls/') &&
56
+ // The registered operation determines data delegation, never a route blacklist.
57
+ if (operation !== undefined && Object.hasOwn(generated_js_1.UNS_V2_OPERATIONS, operation) &&
58
+ generated_js_1.UNS_V2_OPERATIONS[operation].scope.startsWith('uns:') &&
59
59
  this.#unsV2AppDataSubject !== undefined) {
60
60
  headers[exports.UNS_V2_APP_DATA_SUBJECT_HEADER] = this.#unsV2AppDataSubject;
61
61
  }
@@ -153,13 +153,14 @@ class CloudTransport {
153
153
  * An open stream belongs to the caller: `close()` ends it and drops the
154
154
  * link to `signal`, which also ends it.
155
155
  */
156
- async getEventStream(path, options = {}) {
156
+ async getEventStream(path, options = {}, operation) {
157
157
  options.signal?.throwIfAborted();
158
158
  const client = this.resolveClient();
159
159
  const url = `${client.getBaseURL()}${path}`;
160
160
  const key = client.getApiKey();
161
161
  const headers = { Accept: 'text/event-stream' };
162
- if (path.startsWith('/openapi/v2/uns/') && this.#unsV2AppDataSubject !== undefined) {
162
+ if (operation !== undefined && Object.hasOwn(generated_js_1.UNS_V2_STREAM_OPERATIONS, operation) &&
163
+ generated_js_1.UNS_V2_STREAM_OPERATIONS[operation].scope.startsWith('uns:') && this.#unsV2AppDataSubject !== undefined) {
163
164
  headers[exports.UNS_V2_APP_DATA_SUBJECT_HEADER] = this.#unsV2AppDataSubject;
164
165
  }
165
166
  if (options.lastEventId !== undefined)