@tier0/sdk-v2 0.9.10 → 0.10.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 (237) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/LICENSE +21 -21
  3. package/README.md +160 -24
  4. package/dist/cjs/client.d.ts +79 -3
  5. package/dist/cjs/client.js +4 -6
  6. package/dist/cjs/client.js.map +1 -1
  7. package/dist/cjs/cloud-server.d.ts +33 -26
  8. package/dist/cjs/cloud-server.js +102 -100
  9. package/dist/cjs/cloud-server.js.map +1 -1
  10. package/dist/cjs/cloud-transport.d.ts +15 -20
  11. package/dist/cjs/cloud-transport.js +87 -68
  12. package/dist/cjs/cloud-transport.js.map +1 -1
  13. package/dist/cjs/data/bootstrap.js +3 -4
  14. package/dist/cjs/data/bootstrap.js.map +1 -1
  15. package/dist/cjs/data/call.d.ts +1 -3
  16. package/dist/cjs/data/call.js +8 -12
  17. package/dist/cjs/data/call.js.map +1 -1
  18. package/dist/cjs/data/client.d.ts +8 -7
  19. package/dist/cjs/data/client.js +24 -11
  20. package/dist/cjs/data/client.js.map +1 -1
  21. package/dist/cjs/data/collection.d.ts +3 -5
  22. package/dist/cjs/data/collection.js +3 -4
  23. package/dist/cjs/data/collection.js.map +1 -1
  24. package/dist/cjs/data/context.d.ts +5 -11
  25. package/dist/cjs/data/context.js +21 -36
  26. package/dist/cjs/data/context.js.map +1 -1
  27. package/dist/cjs/data/error.js +1 -1
  28. package/dist/cjs/data/error.js.map +1 -1
  29. package/dist/cjs/data/index.d.ts +5 -3
  30. package/dist/cjs/data/index.js +5 -5
  31. package/dist/cjs/data/index.js.map +1 -1
  32. package/dist/cjs/data/relay.d.ts +51 -0
  33. package/dist/cjs/data/relay.js +371 -0
  34. package/dist/cjs/data/relay.js.map +1 -0
  35. package/dist/cjs/data/subscribe.d.ts +22 -38
  36. package/dist/cjs/data/subscribe.js +22 -28
  37. package/dist/cjs/data/subscribe.js.map +1 -1
  38. package/dist/cjs/event-stream.d.ts +28 -0
  39. package/dist/cjs/event-stream.js +222 -0
  40. package/dist/cjs/event-stream.js.map +1 -0
  41. package/dist/cjs/mq/client.d.ts +32 -1
  42. package/dist/cjs/mq/client.js +404 -69
  43. package/dist/cjs/mq/client.js.map +1 -1
  44. package/dist/cjs/mq/index.d.ts +1 -0
  45. package/dist/cjs/mq/index.js +3 -1
  46. package/dist/cjs/mq/index.js.map +1 -1
  47. package/dist/cjs/mq/topic.d.ts +29 -0
  48. package/dist/cjs/mq/topic.js +48 -0
  49. package/dist/cjs/mq/topic.js.map +1 -0
  50. package/dist/cjs/mq/types.d.ts +21 -1
  51. package/dist/cjs/mq/types.js.map +1 -1
  52. package/dist/cjs/openapi/api.generated.d.ts +20 -0
  53. package/dist/cjs/openapi/api.generated.js +11 -0
  54. package/dist/cjs/openapi/api.generated.js.map +1 -1
  55. package/dist/cjs/openapi/client.d.ts +46 -0
  56. package/dist/cjs/openapi/client.js +158 -10
  57. package/dist/cjs/openapi/client.js.map +1 -1
  58. package/dist/cjs/openapi/codecs.generated.d.ts +74 -0
  59. package/dist/cjs/openapi/codecs.generated.js +1 -1
  60. package/dist/cjs/openapi/codecs.generated.js.map +1 -1
  61. package/dist/cjs/openapi/types.generated.d.ts +205 -1
  62. package/dist/cjs/openapi/types.generated.js.map +1 -1
  63. package/dist/cjs/page-runtime.d.ts +48 -0
  64. package/dist/cjs/page-runtime.js +74 -0
  65. package/dist/cjs/page-runtime.js.map +1 -0
  66. package/dist/cjs/platform-proxy.d.ts +17 -0
  67. package/dist/cjs/platform-proxy.js +52 -0
  68. package/dist/cjs/platform-proxy.js.map +1 -0
  69. package/dist/cjs/runtime-context.d.ts +2 -1
  70. package/dist/cjs/runtime-context.js +6 -2
  71. package/dist/cjs/runtime-context.js.map +1 -1
  72. package/dist/cjs/runtime-env.js.map +1 -1
  73. package/dist/cjs/source.d.ts +19 -1
  74. package/dist/cjs/source.js +9 -3
  75. package/dist/cjs/source.js.map +1 -1
  76. package/dist/cjs/stream.js +3 -2
  77. package/dist/cjs/stream.js.map +1 -1
  78. package/dist/cjs/streams/contract.generated.d.ts +7 -1
  79. package/dist/cjs/streams/contract.generated.js.map +1 -1
  80. package/dist/cjs/streams/messages.js +1 -10
  81. package/dist/cjs/streams/messages.js.map +1 -1
  82. package/dist/cjs/streams/requests.d.ts +3 -0
  83. package/dist/cjs/streams/requests.js +5 -2
  84. package/dist/cjs/streams/requests.js.map +1 -1
  85. package/dist/cjs/streams/transport.d.ts +1 -13
  86. package/dist/cjs/streams/transport.js +2 -18
  87. package/dist/cjs/streams/transport.js.map +1 -1
  88. package/dist/cjs/uns-v2/client.d.ts +1 -6
  89. package/dist/cjs/uns-v2/client.js +30 -6
  90. package/dist/cjs/uns-v2/client.js.map +1 -1
  91. package/dist/cjs/uns-v2/data-client.d.ts +5 -2
  92. package/dist/cjs/uns-v2/data-client.js +7 -4
  93. package/dist/cjs/uns-v2/data-client.js.map +1 -1
  94. package/dist/cjs/uns-v2/generated.d.ts +6783 -4655
  95. package/dist/cjs/uns-v2/generated.js +221 -65
  96. package/dist/cjs/uns-v2/generated.js.map +1 -1
  97. package/dist/cjs/uns-v2/sse.d.ts +7 -1
  98. package/dist/cjs/uns-v2/sse.js +12 -2
  99. package/dist/cjs/uns-v2/sse.js.map +1 -1
  100. package/dist/esm/client.d.ts +79 -3
  101. package/dist/esm/client.js +5 -7
  102. package/dist/esm/client.js.map +1 -1
  103. package/dist/esm/cloud-server.d.ts +33 -26
  104. package/dist/esm/cloud-server.js +99 -97
  105. package/dist/esm/cloud-server.js.map +1 -1
  106. package/dist/esm/cloud-transport.d.ts +15 -20
  107. package/dist/esm/cloud-transport.js +86 -67
  108. package/dist/esm/cloud-transport.js.map +1 -1
  109. package/dist/esm/data/bootstrap.js +3 -4
  110. package/dist/esm/data/bootstrap.js.map +1 -1
  111. package/dist/esm/data/call.d.ts +1 -3
  112. package/dist/esm/data/call.js +9 -13
  113. package/dist/esm/data/call.js.map +1 -1
  114. package/dist/esm/data/client.d.ts +8 -7
  115. package/dist/esm/data/client.js +22 -9
  116. package/dist/esm/data/client.js.map +1 -1
  117. package/dist/esm/data/collection.d.ts +3 -5
  118. package/dist/esm/data/collection.js +3 -4
  119. package/dist/esm/data/collection.js.map +1 -1
  120. package/dist/esm/data/context.d.ts +5 -11
  121. package/dist/esm/data/context.js +19 -33
  122. package/dist/esm/data/context.js.map +1 -1
  123. package/dist/esm/data/error.js +1 -1
  124. package/dist/esm/data/error.js.map +1 -1
  125. package/dist/esm/data/index.d.ts +5 -3
  126. package/dist/esm/data/index.js +3 -2
  127. package/dist/esm/data/index.js.map +1 -1
  128. package/dist/esm/data/relay.d.ts +51 -0
  129. package/dist/esm/data/relay.js +368 -0
  130. package/dist/esm/data/relay.js.map +1 -0
  131. package/dist/esm/data/subscribe.d.ts +22 -38
  132. package/dist/esm/data/subscribe.js +22 -27
  133. package/dist/esm/data/subscribe.js.map +1 -1
  134. package/dist/esm/event-stream.d.ts +28 -0
  135. package/dist/esm/event-stream.js +217 -0
  136. package/dist/esm/event-stream.js.map +1 -0
  137. package/dist/esm/mq/client.d.ts +32 -1
  138. package/dist/esm/mq/client.js +404 -69
  139. package/dist/esm/mq/client.js.map +1 -1
  140. package/dist/esm/mq/index.d.ts +1 -0
  141. package/dist/esm/mq/index.js +1 -0
  142. package/dist/esm/mq/index.js.map +1 -1
  143. package/dist/esm/mq/topic.d.ts +29 -0
  144. package/dist/esm/mq/topic.js +44 -0
  145. package/dist/esm/mq/topic.js.map +1 -0
  146. package/dist/esm/mq/types.d.ts +21 -1
  147. package/dist/esm/mq/types.js.map +1 -1
  148. package/dist/esm/openapi/api.generated.d.ts +20 -0
  149. package/dist/esm/openapi/api.generated.js +11 -0
  150. package/dist/esm/openapi/api.generated.js.map +1 -1
  151. package/dist/esm/openapi/client.d.ts +46 -0
  152. package/dist/esm/openapi/client.js +157 -10
  153. package/dist/esm/openapi/client.js.map +1 -1
  154. package/dist/esm/openapi/codecs.generated.d.ts +74 -0
  155. package/dist/esm/openapi/codecs.generated.js +1 -1
  156. package/dist/esm/openapi/codecs.generated.js.map +1 -1
  157. package/dist/esm/openapi/types.generated.d.ts +205 -1
  158. package/dist/esm/openapi/types.generated.js.map +1 -1
  159. package/dist/esm/page-runtime.d.ts +48 -0
  160. package/dist/esm/page-runtime.js +65 -0
  161. package/dist/esm/page-runtime.js.map +1 -0
  162. package/dist/esm/platform-proxy.d.ts +17 -0
  163. package/dist/esm/platform-proxy.js +47 -0
  164. package/dist/esm/platform-proxy.js.map +1 -0
  165. package/dist/esm/runtime-context.d.ts +2 -1
  166. package/dist/esm/runtime-context.js +6 -2
  167. package/dist/esm/runtime-context.js.map +1 -1
  168. package/dist/esm/runtime-env.js.map +1 -1
  169. package/dist/esm/source.d.ts +19 -1
  170. package/dist/esm/source.js +10 -4
  171. package/dist/esm/source.js.map +1 -1
  172. package/dist/esm/stream.js +4 -3
  173. package/dist/esm/stream.js.map +1 -1
  174. package/dist/esm/streams/contract.generated.d.ts +7 -1
  175. package/dist/esm/streams/contract.generated.js.map +1 -1
  176. package/dist/esm/streams/messages.js +1 -10
  177. package/dist/esm/streams/messages.js.map +1 -1
  178. package/dist/esm/streams/requests.d.ts +3 -0
  179. package/dist/esm/streams/requests.js +5 -2
  180. package/dist/esm/streams/requests.js.map +1 -1
  181. package/dist/esm/streams/transport.d.ts +1 -13
  182. package/dist/esm/streams/transport.js +1 -17
  183. package/dist/esm/streams/transport.js.map +1 -1
  184. package/dist/esm/uns-v2/client.d.ts +1 -6
  185. package/dist/esm/uns-v2/client.js +30 -6
  186. package/dist/esm/uns-v2/client.js.map +1 -1
  187. package/dist/esm/uns-v2/data-client.d.ts +5 -2
  188. package/dist/esm/uns-v2/data-client.js +8 -5
  189. package/dist/esm/uns-v2/data-client.js.map +1 -1
  190. package/dist/esm/uns-v2/generated.d.ts +6783 -4655
  191. package/dist/esm/uns-v2/generated.js +221 -65
  192. package/dist/esm/uns-v2/generated.js.map +1 -1
  193. package/dist/esm/uns-v2/sse.d.ts +7 -1
  194. package/dist/esm/uns-v2/sse.js +12 -2
  195. package/dist/esm/uns-v2/sse.js.map +1 -1
  196. package/package.json +25 -12
  197. package/skills/tier0-sdk-v2/SKILL.md +11 -5
  198. package/skills/tier0-sdk-v2/references/integration.md +14 -24
  199. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/SKILL.md +11 -5
  200. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/consistency.md +6 -10
  201. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/errors.md +20 -3
  202. package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/read-write.md +46 -13
  203. package/skills/tier0-sdk-v2/tier0-sdk-v2-members/SKILL.md +2 -2
  204. package/skills/tier0-sdk-v2/tier0-sdk-v2-members/references/app-members.md +5 -1
  205. package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/SKILL.md +25 -0
  206. package/skills/tier0-sdk-v2/tier0-sdk-v2-mq/references/quickstart.md +1 -1
  207. package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/SKILL.md +3 -3
  208. package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/references/send.md +6 -6
  209. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md +4 -4
  210. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/changes.md +2 -2
  211. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/create.md +26 -36
  212. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/delete.md +9 -23
  213. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/protocols.md +12 -29
  214. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/read.md +4 -5
  215. package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/update.md +5 -5
  216. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md +3 -3
  217. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/create.md +23 -9
  218. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/deploy.md +14 -12
  219. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/http-server.md +4 -4
  220. package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/read.md +4 -3
  221. package/skills/tier0-sdk-v2/tier0-sdk-v2-streams/SKILL.md +12 -12
  222. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md +2 -1
  223. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/create.md +2 -2
  224. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/delete.md +22 -1
  225. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/read.md +5 -6
  226. package/dist/cjs/app-identity-contract.generated.d.ts +0 -22
  227. package/dist/cjs/app-identity-contract.generated.js +0 -51
  228. package/dist/cjs/app-identity-contract.generated.js.map +0 -1
  229. package/dist/cjs/runtime.d.ts +0 -13
  230. package/dist/cjs/runtime.js +0 -51
  231. package/dist/cjs/runtime.js.map +0 -1
  232. package/dist/esm/app-identity-contract.generated.d.ts +0 -22
  233. package/dist/esm/app-identity-contract.generated.js +0 -48
  234. package/dist/esm/app-identity-contract.generated.js.map +0 -1
  235. package/dist/esm/runtime.d.ts +0 -13
  236. package/dist/esm/runtime.js +0 -46
  237. package/dist/esm/runtime.js.map +0 -1
@@ -1,12 +1,12 @@
1
1
  # HTTPServer 固定前缀与 Stream 路由
2
2
 
3
- 先用 [Source 创建](../../tier0-sdk-v2-source/references/create.md)保存 `http-api` + `config.role: server`。Source 使用 `http://managed` 和空 options;业务路径在 Stream 注册。
3
+ 先用 [Source 创建](../../tier0-sdk-v2-source/references/create.md)保存 `http-api` + `role: server`。Source 使用 `http://managed` ;业务路径在 Stream 注册。
4
4
 
5
5
  固定前缀为 `/ingest/v1/{workspaceId}/{sourceId}`。下例路由为 `POST /orders/:id`,完整请求路径为 `POST /ingest/v1/{workspaceId}/{sourceId}/orders/A-001`。前缀由部署环境和已认证的工作空间、Source 身份确定,不从请求 body 推断工作空间。Bearer 凭据由 Source 的既有管理合同取得并在调用时注入,不写入脚本。
6
6
 
7
7
  ## 保存原生程序草稿
8
8
 
9
- 使用完整原生 `document`:script 是 `{code,timeoutMs}`,sources 使用 alias。这与 `program` 的 script 字符串形态不同。
9
+ 使用完整原生 `document`:script 是 `{code,timeoutMs}`,sources 使用 alias。这与 `program` 的 script 对象形态不同。
10
10
 
11
11
  ```ts
12
12
  import { createClient, type Tier0Client, type CloudStreamDocument } from '@tier0/sdk-v2';
@@ -18,7 +18,7 @@ export async function createHttpServerStream(
18
18
  if (!/^[1-9][0-9]*$/.test(sourceId)) throw new Error('Source ID 必须是正十进制字符串');
19
19
  const source = await client.source.documents.get({ id: sourceId, view: 'full' });
20
20
  if (!('document' in source.data)) throw new Error('需要完整 Source 文档');
21
- const config = source.data.document.config;
21
+ const config = source.data.document;
22
22
  if (source.data.document.protocol !== 'http-api' || config.role !== 'server') {
23
23
  throw new Error('此入站路由示例需要 HTTP API Server Source');
24
24
  }
@@ -60,7 +60,7 @@ export async function createHttpServerEarlyReplyStream(
60
60
  if (!collectionId) throw new Error('需要实际 Collection ID');
61
61
  const source = await client.source.documents.get({ id: sourceId, view: 'full' });
62
62
  if (!('document' in source.data)) throw new Error('需要完整 Source 文档');
63
- const config = source.data.document.config;
63
+ const config = source.data.document;
64
64
  if (source.data.document.protocol !== 'http-api' || config.role !== 'server') {
65
65
  throw new Error('此入站路由示例需要 HTTP API Server Source');
66
66
  }
@@ -14,9 +14,8 @@ page 从 1 开始,size 最大 200。summary 只需 uns.stream.view 或 uns.str
14
14
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
15
15
 
16
16
  export async function readStream(id: string, client: Tier0Client = createClient()) {
17
- const draft = await client.stream.documents.get({ id });
18
- const observation = await client.stream.observations.get({ id });
19
- return { draft: draft.data, observation: observation.data };
17
+ const current = await client.stream.documents.get({ id, view: 'summary' });
18
+ return { current: current.data };
20
19
  }
21
20
  export async function* listStreams(client: Tier0Client = createClient()) {
22
21
  let page = 1;
@@ -30,6 +29,8 @@ export async function* listStreams(client: Tier0Client = createClient()) {
30
29
  }
31
30
  ```
32
31
 
32
+ 查询摘要只需一次请求。编辑完整草稿时显式使用 `documents.get({ id, view: 'full' })`;只看运行观测时直接 `observations.get({ id })`,不先读取草稿。已有写回执时可直接消费其中的状态和修订。
33
+
33
34
  保存、发布、某次执行成功是三个事实。显示实际 revision/activeVersion/release,不用旧 runs 证明新版本生效。版本列表不保证与普通列表相同分页结构;按其 list/total/page/size 读取,versionId 不是 release 序号。
34
35
 
35
36
  ## 观察本次发布
@@ -1,11 +1,13 @@
1
1
  ---
2
2
  name: tier0-sdk-v2-streams
3
- description: "Tier0 App/Stream requests and live business messages: client.streams.requests describe/invoke/discover, client.streams.messages publish/subscribe, trusted App runtime bootstrap and disposable subscriptions. Use for Stream v3 interactions; UNS history, device MQTT and persisted notifications have their own Skills."
3
+ description: "Tier0 App/Stream requests and live business messages: client.streams.requests describe/invoke/discover, client.streams.messages publish/subscribe on a server client with its own key, and disposable subscriptions. Use for Stream v3 interactions; UNS history, device MQTT and persisted notifications have their own Skills."
4
4
  ---
5
5
 
6
6
  # App / Stream Interactions
7
7
 
8
- Read the [root Skill](../SKILL.md) first. These APIs require an artifact built from the unified SDK implementation: pin its commit and SHA-256 until the corresponding version is published.
8
+ Read the [root Skill](../SKILL.md) first.
9
+
10
+ **In a Tier0 App's server code** the App's key (`TIER0_API_KEY`) can use both. Stream requests and messages are fixed capabilities of every App (`stream.requests.read` / `invoke` / `write`, `stream.messages.publish` / `subscribe`), not configured per App and not approved by an admin. They are still bounded by the workspace plan (a plan without Stream refuses them) and, for requests, by the Stream request grants: the request code must be granted to this App. Message topics come from published Stream manifests: the App may subscribe to a topic a published Stream declares with `api.stream.messages.use({ topic, access: 'publish' })`, and publish to a topic an active Stream subscribes to. There is no per-App topic list. These APIs require an artifact built from the unified SDK implementation: pin its commit and SHA-256 until the corresponding version is published.
9
11
 
10
12
  ## Select the interaction
11
13
 
@@ -16,13 +18,11 @@ Read the [root Skill](../SKILL.md) first. These APIs require an artifact built f
16
18
 
17
19
  Import `client` or `createClient` from `@tier0/sdk-v2`. The same client exposes `uns`, `source`, `stream`, `capabilities`, `files` and `notifications`. The singular `stream` manages documents, programs and runs; plural `streams` performs App requests and live messaging. MQTT stays in the separate `/mq` entry.
18
20
 
19
- ## Trusted App bootstrap
20
-
21
- The SWE host installs `globalThis[Symbol.for('tier0.sdk.app-runtime.v1')]` before the App script. The SDK detects it automatically; App business code must not install a replacement provider or resolve credentials itself. The host's provider returns a `Response` for its authenticated request bridge.
21
+ ## Server only
22
22
 
23
- Browser App code knows only public request codes, logical topics and business payloads. Do not add broker URLs, physical subjects, API keys, JWTs, nkey seeds, workspace/principal headers or message identity claims to App configuration. `@tier0/sdk-v2/runtime` is a trusted host integration entry point, not App setup.
23
+ Use `client.streams` from server code with a client that holds a key: `createClient()` reads `TIER0_API_HOST` / `TIER0_API_KEY`, or pass `apiHost` / `apiKey`. Never put that key in a browser bundle. Browser code does not call the platform directly; it calls the App's own server routes, which use `client.streams`. There is no browser host bridge.
24
24
 
25
- For a standalone Node service, the deployment supplies its existing HTTP credential and real App context. Call `createClient()` without literals; never put these server credentials in a browser bundle.
25
+ Callers know only public request codes, logical topics and business payloads. Do not add broker URLs, physical subjects, JWTs, nkey seeds, workspace/principal headers or message identity claims to configuration; the SDK obtains a short-lived broker ticket per connection.
26
26
 
27
27
  ## Public caller
28
28
 
@@ -31,12 +31,12 @@ import { createClient, type StreamMessageError } from '@tier0/sdk-v2';
31
31
 
32
32
  export async function openOrders(
33
33
  reportError: (error: StreamMessageError) => void,
34
- renderOrderUpdate: (order: { orderId: string }) => void,
34
+ onOrderUpdate: (order: { orderId: string }) => void,
35
35
  ) {
36
- const sdk = createClient(); // automatically uses the trusted App runtime
36
+ const sdk = createClient(); // server: TIER0_API_HOST / TIER0_API_KEY
37
37
  const removeErrorHandler = sdk.streams.messages.onError(reportError);
38
38
  const subscription = await sdk.streams.messages.use<{ orderId: string }>({ topic: 'orders/accepted' })
39
- .subscribe(message => renderOrderUpdate(message.payload));
39
+ .subscribe(message => onOrderUpdate(message.payload));
40
40
  const request = sdk.streams.requests.use<{ orderId: string }, { accepted: boolean }>({ code: 'orders.approve' });
41
41
  return {
42
42
  describe: () => request.describe(),
@@ -56,9 +56,9 @@ Persist one caller-owned idempotency key per business intent. A deliberate recon
56
56
 
57
57
  Messages use a versioned `{ version, messageId, correlationId?, payload }` envelope. Caller-supplied identity in a payload is business data, not authenticated publisher metadata; authorized broker subjects establish identity internally.
58
58
 
59
- The SDK uses native Core NATS over WSS, loaded only when messaging starts. Messages require a browser with WebSocket or Node.js 22+; HTTP-only clients remain usable on Node.js 20.19+. Each initial connection, reconnect and renewal gets a new in-memory user key and a public-key-bound JWT. The old socket closes and its private key is wiped before replacement. No private key leaves the SDK. A successful publish means broker flush, not receiver acknowledgement.
59
+ The SDK uses native Core NATS over WSS, loaded only when messaging starts. Messages require Node.js 22+ (WebSocket); HTTP-only clients remain usable on Node.js 20.19+. Each initial connection, reconnect and renewal gets a new in-memory user key and a public-key-bound JWT. The old socket closes and its private key is wiped before replacement. No private key leaves the SDK. A successful publish means broker flush, not receiver acknowledgement.
60
60
 
61
- Register `messages.onError` (or subscription `onError`) to handle asynchronous broker, decoding and handler failures. After an established session disconnects, publish fails immediately: no offline buffering, write retry or message replay. Credential refresh and reconnection restore subscriptions only. Dispose subscriptions and the owned client when the view/service stops.
61
+ Register `messages.onError` (or subscription `onError`) to handle asynchronous broker, decoding and handler failures. After an established session disconnects, publish fails immediately: no offline buffering, write retry or message replay. Credential refresh and reconnection restore subscriptions only. Dispose subscriptions and the owned client when the service stops.
62
62
 
63
63
  ## Stream-side code
64
64
 
@@ -5,7 +5,7 @@ description: 使用 @tier0/sdk-v2 的 client.uns 完成新架构集合、Schema
5
5
 
6
6
  # UNS 数据操作
7
7
 
8
- UNS 管数据命名空间、集合、Record 和 Sample;外部连接与脚本分别用 [Source](../tier0-sdk-v2-source/SKILL.md)、[Stream](../tier0-sdk-v2-stream/SKILL.md)。服务端 `createClient()` 读取 TIER0_API_HOST / TIER0_API_KEY,或显式传 apiHost/apiKey。数据权限不自动授予管理权限:管理操作中 App 凭证只能调用本 App 集合的 appCollectionsEnsure / SchemaReplace / Archive / Restore;appDataPolicyGet/Update 的调用方必须是持有 uns.write 的登录会话、持有 uns.write 且 full_access、不绑定 App 的 personal / agent Key,或治理会话;运行时 App 凭证不能管理数据授权。
8
+ UNS 管数据命名空间、集合、Record 和 Sample;外部连接与脚本分别用 [Source](../tier0-sdk-v2-source/SKILL.md)、[Stream](../tier0-sdk-v2-stream/SKILL.md)。服务端 `createClient()` 读 TIER0_API_HOST / TIER0_API_KEY(平台里由平台注入 App 的 Key),或显式传 apiHost/apiKey。数据权限不自动授予管理权限:管理操作中 App 凭证只能调用本 App 集合的 appCollectionsEnsure / SchemaReplace / Archive / Restore;appDataPolicyGet/Update 的调用方必须是持有 uns.write 的登录会话、持有 uns.write 且 full_access、不绑定 App 的 personal / agent Key,或治理会话;新增授权(新集合、放宽权限、从 disabled 重新启用)只接受工作区 Owner/Admin 的人工会话或平台导入,其他调用方回 403(reason `app_grant_admin_required` / `app_grant_agent_forbidden`),收窄和移除不受此限;运行时 App 凭证不能管理数据授权。
9
9
 
10
10
  先按[命名空间指导](references/namespace.md)区分凭证:`namespace()` 走 OpenAPI,但当前不对 App Key 开放;App 查询可用集合走 `dataAppContext`,不能改用同样受限的 `appCollectionsList`。Agent / Personal Key 也须满足当前工作空间权限;不要从“使用 SDK / MCP”推定权限。
11
11
 
@@ -19,6 +19,7 @@ UNS 管数据命名空间、集合、Record 和 Sample;外部连接与脚本
19
19
  | 查询集合、筛选/排序记录 | [查询](references/read.md) | dataAppContext、metadataFind/FindOne(非 App 凭证)、collectionDescribe、recordFind |
20
20
  | 改记录、集合名称、扩展 Schema | [修改](references/update.md) | recordUpdateOne、metadataUpdateOne/Many |
21
21
  | 删记录、软删除集合 | [删除](references/delete.md) | recordDeleteOne、metadataDeleteOne/Many |
22
+ | 精确删除选中的历史样本 | [删除](references/delete.md#精确删除历史样本) | sampleFind、sampleDeleteExact(非 App 凭证) |
22
23
  | 永久删除回收站集合 | [删除](references/delete.md) | metadataPurge、jobs |
23
24
  | 恢复集合或记录 | [恢复](references/restore.md) | metadataRestore、recordRestore |
24
25
  | 分页、历史采样、事务、写入结果 | [数据工作流](references/data-workflows.md) | sampleFind、recordTransactionExecute |
@@ -29,8 +29,6 @@ export async function createDeviceCollection(
29
29
  },
30
30
  },
31
31
  };
32
- const preview = await client.uns.metadataInsertOne({ ...request, dryRun: true });
33
- if (preview.data.status !== 'validated') throw new Error('集合预检未通过');
34
32
  const receipt = await client.uns.metadataInsertOne({ ...request, dryRun: false, idempotencyKey: intentKey });
35
33
  if (receipt.data.status !== 'committed') return { state: 'unconfirmed' as const, receipt };
36
34
  const current = await client.uns.metadataFind({ kind: 'collection', filter: { _id: collectionId }, limit: 1 });
@@ -39,6 +37,8 @@ export async function createDeviceCollection(
39
37
  }
40
38
  ```
41
39
 
40
+ 普通创建直接提交,服务端在提交时校验。只有需要展示预检结果时才单独使用 `dryRun: true`,预检不锁定提交条件。示例提交后读取一次,是为了返回服务端补全的集合结构和 revision;仅需创建回执时可省略这次读取。
41
+
42
42
  单条 Record 新增默认返回 insertedId/status/replayed。需要创建后的数据、revision 和时间戳时,传 returnDocument:'after',同一次写入返回 value,无需再查询;可配合 projection,调用者必须同时具有读取权限。幂等重放返回原始创建快照,后续读取最新状态仍用 recordGet/recordFind。dryRun 的 value 是未提交预览。
43
43
 
44
44
  returnDocument 只允许 none(默认)或 after,不支持 before;projection 只能和 after 一起传。新增仍是 insert,已存在的 ID 不会变成更新。after 的 value 包括服务端补入的字段,但只返回当前授权可见的数据:普通数据权限需 uns.write 和 uns.read,App 还要满足集合的 record:write / record:read 及当前员工、行和字段策略。服务端在提交前校验读取权限,重放时也重新校验;旧回执不能绕过已撤销的授权。
@@ -54,10 +54,31 @@ metadataDeleteMany 使用明确 filter 和 maxDocs。默认原子;超过上限
54
54
 
55
55
  恢复范围和授权区别见[恢复](restore.md)。保留的物理索引仍占配额,归档不释放索引空间。
56
56
 
57
- 业务记录使用 recordDeleteOne/Many,传 collectionId 和明确 filter,编辑型流程同时传 expectedRevision。不要把元数据软删除解释成逐条删除该集合的 Record。Sample 的删除是独立的显式时间范围操作,具体影响遵循当前数据 API 契约。
57
+ 业务记录使用 recordDeleteOne/Many,传 collectionId 和明确 filter,编辑型流程同时传 expectedRevision。不要把元数据软删除解释成逐条删除该集合的 Record。Sample 使用独立的精确清单或显式时间范围删除接口;清理选定样本使用下面的 sampleDeleteExact。
58
58
 
59
59
  成功回执已确认本次操作,不再固定读回验证。结果未知时保留原意图键,按对象身份核对;需要展示最新状态时再刷新。版本冲突应重新读取并由调用方处理,不自动覆盖。
60
60
 
61
+ ## 精确删除历史样本
62
+
63
+ Workspace 管理调用方通过 `client.uns.sampleDeleteExact` 删除当前集合内的明确样本清单,最多 200 条,需要 `uns.delete` 权限;MCP 凭证另需 `uns.write` 授权。运行时 App Key 不支持此操作,也没有对应的 App 数据层方法。
64
+
65
+ 从 `sampleFind` 结果复制 `{recordId,id,time}`,保留原始 Unix 毫秒时间;`id` 不能替代完整身份,`receivedAt` 不能替代 `time`。不接受空清单、重复身份、filter 或时间范围。清理重复样本时,由业务判断哪些样本重复、保留哪条,只把多余项放入清单;接口本身不判断重复,也不改变采集逻辑。
66
+
67
+ ```ts
68
+ import { createClient, type Tier0Client, type UnsV2SampleDeleteExactReq } from '@tier0/sdk-v2';
69
+
70
+ export async function deleteSelectedSamples(
71
+ collectionId: string, samples: UnsV2SampleDeleteExactReq['samples'],
72
+ intentKey: string, dryRun = true, client: Tier0Client = createClient(),
73
+ ) {
74
+ return client.uns.sampleDeleteExact({ collectionId, samples, dryRun, idempotencyKey: intentKey });
75
+ }
76
+ ```
77
+
78
+ `dryRun:true` 仅返回当时的匹配数量,不删除或预留样本。执行时使用同一清单和 `dryRun:false`;省略 dryRun 也会执行。返回 `{deletedCount,missingCount,dryRun}`:deletedCount 在预览时是预计删除数,执行时是实际删除数;missingCount 是未匹配到的完整键数。整批精确删除与回执同事务,不修改父 Record 或未列出的样本。
79
+
80
+ 相同执行请求重试复用相同 `idempotencyKey`,修改清单需要新键。SDK 不自动重试;结局未知时按完整键查询核对,遵循错误中的 execution/retry,不改用范围删除或重建集合。`sampleDeleteRange` 仍不向 MCP 开放。
81
+
61
82
  ## 永久删除回收站集合
62
83
 
63
84
  Workspace 管理调用方使用 `metadataPurge`,传 `kind:'collection'` 和 1–200 个明确 `ids`。
@@ -36,13 +36,10 @@ export async function readAppRecords(alias: string, client: Tier0Client = create
36
36
  import { createClient, type Tier0Client } from '@tier0/sdk-v2';
37
37
 
38
38
  export async function readDevices(collectionId: string, client: Tier0Client = createClient()) {
39
- const collection = await client.uns.metadataFind({ kind: 'collection', filter: { _id: collectionId }, limit: 1 });
40
- const definition = collection.data.items[0];
41
- if (!definition) throw new Error('集合不存在或不可见');
42
39
  const records = await client.uns.recordFind({
43
40
  collectionId, filter: { enabled: true }, sort: [['name', 1]], limit: 20,
44
41
  });
45
- return { definition: definition.data, items: records.data.items, pageInfo: records.data.pageInfo };
42
+ return { items: records.data.items, pageInfo: records.data.pageInfo };
46
43
  }
47
44
 
48
45
  export async function listCollections(page = 1, client: Tier0Client = createClient()) {
@@ -54,10 +51,12 @@ export async function listCollections(page = 1, client: Tier0Client = createClie
54
51
 
55
52
  按 pageInfo.hasMore/nextPage 继续元数据分页;不要把第一页当全量。recordFind 的游标循环见[数据工作流](data-workflows.md)。sort 是数组元组。
56
53
 
57
- 以上 metadataFind 示例用于 Workspace 集成(会话、personal / agent Key)。App 凭证不能调用 metadataFind:用 dataAppContext 精确选择授权 alias,集合的 revision、indexStatus、ttl 也在其中。数据授权不等于元数据管理授权。网络/权限错误必须传播,不能用空数组掩盖错误。
54
+ 已知 collectionId 时直接读取记录,由服务端校验集合及操作权限;不先调用 metadataFind、dataAppContext、collectionDescribe 或 ensure。需要选择集合或查看结构时,再单独读取对应上下文。
55
+
56
+ listCollections 的 metadataFind 仅用于 Workspace 集成(会话、personal / agent Key)。App 凭证不能调用 metadataFind;未知 collectionId 时用 dataAppContext 选择已授权集合,集合的 revision、indexStatus、ttl 也在其中。readDevices 只需要目标集合的记录读取权限。网络/权限错误必须传播,不能用空数组掩盖错误。
58
57
 
59
58
  ## 回收集合的历史读取
60
59
 
61
- 按原 collectionId 读取 Record、Sample、count 或 aggregate;既有授权、员工行规则和字段权限仍生效。活跃 Topic 可继续读取其引用的回收集合。活跃 App 的 dataAppContext 保留仍可读的回收集合,但不授予新增能力;回收中的 App 自身不能运行。
60
+ 按原 collectionId 读取 Record、Sample、count 或 aggregate;既有授权和字段权限仍生效。活跃 Topic 可继续读取其引用的回收集合。活跃 App 的 dataAppContext 保留仍可读的回收集合,但不授予新增能力;回收中的 App 自身不能运行。
62
61
 
63
62
  已知 ID 直接读取,不必先恢复集合或查询元数据。数据层也可用 `data.collection({ collectionId })`,不会 ensure、写种子或补授权。只有 Workspace 集成确需回收对象定义时,才用 metadataFind 的 state=deleted 或 all;App Key 仍不调用该接口。[回收规则](delete.md#回收规则)说明写入和恢复边界。
@@ -1,22 +0,0 @@
1
- export declare const APP_REQUEST_IDENTITY_CONTRACT: {
2
- readonly version: "tier0.app-request-identity/v1";
3
- readonly header: "X-Tier0-App-Identity";
4
- readonly type: "tier0-app-request+jwt";
5
- readonly algorithm: "EdDSA";
6
- readonly issuer: "tier0-app-gateway";
7
- readonly audience: "tier0-app-runtime";
8
- readonly maxTokenBytes: 8192;
9
- readonly maxBodyBytes: 65536;
10
- readonly maxURIBytes: 8192;
11
- readonly maxTTLSeconds: 30;
12
- readonly clockSkewSeconds: 5;
13
- readonly maxRoles: 32;
14
- readonly maxRoleBytes: 128;
15
- readonly maxKeys: 8;
16
- readonly keyIDPattern: "^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$";
17
- readonly appIDPattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$";
18
- readonly requiredClaims: readonly ["ver", "iss", "aud", "sub", "workspaceID", "appID", "method", "requestURI", "bodySHA256", "iat", "exp", "jti", "roles"];
19
- readonly methodPattern: "^[A-Z]{1,16}$";
20
- readonly requiredHeaderFields: readonly ["alg", "typ", "kid"];
21
- readonly publicKeyFields: readonly ["kty", "crv", "x", "kid"];
22
- };
@@ -1,51 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.APP_REQUEST_IDENTITY_CONTRACT = void 0;
4
- // Generated from SWE gatewayheader/app-request-identity.v1.json; do not edit.
5
- // Source SHA-256: ac5ec2efb882395e63a46c9ec479de16c09943b88fc0bd906dd77c7f9f4bfaa3
6
- exports.APP_REQUEST_IDENTITY_CONTRACT = {
7
- "version": "tier0.app-request-identity/v1",
8
- "header": "X-Tier0-App-Identity",
9
- "type": "tier0-app-request+jwt",
10
- "algorithm": "EdDSA",
11
- "issuer": "tier0-app-gateway",
12
- "audience": "tier0-app-runtime",
13
- "maxTokenBytes": 8192,
14
- "maxBodyBytes": 65536,
15
- "maxURIBytes": 8192,
16
- "maxTTLSeconds": 30,
17
- "clockSkewSeconds": 5,
18
- "maxRoles": 32,
19
- "maxRoleBytes": 128,
20
- "maxKeys": 8,
21
- "keyIDPattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$",
22
- "appIDPattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
23
- "requiredClaims": [
24
- "ver",
25
- "iss",
26
- "aud",
27
- "sub",
28
- "workspaceID",
29
- "appID",
30
- "method",
31
- "requestURI",
32
- "bodySHA256",
33
- "iat",
34
- "exp",
35
- "jti",
36
- "roles"
37
- ],
38
- "methodPattern": "^[A-Z]{1,16}$",
39
- "requiredHeaderFields": [
40
- "alg",
41
- "typ",
42
- "kid"
43
- ],
44
- "publicKeyFields": [
45
- "kty",
46
- "crv",
47
- "x",
48
- "kid"
49
- ]
50
- };
51
- //# sourceMappingURL=app-identity-contract.generated.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"app-identity-contract.generated.js","sourceRoot":"","sources":["../../src/app-identity-contract.generated.ts"],"names":[],"mappings":";;;AAAA,8EAA8E;AAC9E,mFAAmF;AACtE,QAAA,6BAA6B,GAAG;IAC3C,SAAS,EAAE,+BAA+B;IAC1C,QAAQ,EAAE,sBAAsB;IAChC,MAAM,EAAE,uBAAuB;IAC/B,WAAW,EAAE,OAAO;IACpB,QAAQ,EAAE,mBAAmB;IAC7B,UAAU,EAAE,mBAAmB;IAC/B,eAAe,EAAE,IAAI;IACrB,cAAc,EAAE,KAAK;IACrB,aAAa,EAAE,IAAI;IACnB,eAAe,EAAE,EAAE;IACnB,kBAAkB,EAAE,CAAC;IACrB,UAAU,EAAE,EAAE;IACd,cAAc,EAAE,GAAG;IACnB,SAAS,EAAE,CAAC;IACZ,cAAc,EAAE,mCAAmC;IACnD,cAAc,EAAE,2EAA2E;IAC3F,gBAAgB,EAAE;QAChB,KAAK;QACL,KAAK;QACL,KAAK;QACL,KAAK;QACL,aAAa;QACb,OAAO;QACP,QAAQ;QACR,YAAY;QACZ,YAAY;QACZ,KAAK;QACL,KAAK;QACL,KAAK;QACL,OAAO;KACR;IACD,eAAe,EAAE,eAAe;IAChC,sBAAsB,EAAE;QACtB,KAAK;QACL,KAAK;QACL,KAAK;KACN;IACD,iBAAiB,EAAE;QACjB,KAAK;QACL,KAAK;QACL,GAAG;QACH,KAAK;KACN;CACO,CAAC","sourcesContent":["// Generated from SWE gatewayheader/app-request-identity.v1.json; do not edit.\n// Source SHA-256: ac5ec2efb882395e63a46c9ec479de16c09943b88fc0bd906dd77c7f9f4bfaa3\nexport const APP_REQUEST_IDENTITY_CONTRACT = {\n \"version\": \"tier0.app-request-identity/v1\",\n \"header\": \"X-Tier0-App-Identity\",\n \"type\": \"tier0-app-request+jwt\",\n \"algorithm\": \"EdDSA\",\n \"issuer\": \"tier0-app-gateway\",\n \"audience\": \"tier0-app-runtime\",\n \"maxTokenBytes\": 8192,\n \"maxBodyBytes\": 65536,\n \"maxURIBytes\": 8192,\n \"maxTTLSeconds\": 30,\n \"clockSkewSeconds\": 5,\n \"maxRoles\": 32,\n \"maxRoleBytes\": 128,\n \"maxKeys\": 8,\n \"keyIDPattern\": \"^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$\",\n \"appIDPattern\": \"^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$\",\n \"requiredClaims\": [\n \"ver\",\n \"iss\",\n \"aud\",\n \"sub\",\n \"workspaceID\",\n \"appID\",\n \"method\",\n \"requestURI\",\n \"bodySHA256\",\n \"iat\",\n \"exp\",\n \"jti\",\n \"roles\"\n ],\n \"methodPattern\": \"^[A-Z]{1,16}$\",\n \"requiredHeaderFields\": [\n \"alg\",\n \"typ\",\n \"kid\"\n ],\n \"publicKeyFields\": [\n \"kty\",\n \"crv\",\n \"x\",\n \"kid\"\n ]\n} as const;\n"]}
@@ -1,13 +0,0 @@
1
- /** Trusted host integration; application code uses client.streams without configuration. */
2
- export interface AppRuntime {
3
- readonly appId: string;
4
- /** Authenticated host bridge. Never expose a service key to the browser. */
5
- request(path: string, body: unknown, options: {
6
- signal: AbortSignal;
7
- }): Promise<Response>;
8
- }
9
- /** Internal lifecycle registration, shared across SDK copies in the host page. */
10
- export declare function onAppRuntimeDispose(runtime: AppRuntime, callback: () => void): () => void;
11
- export declare function getAppRuntime(): AppRuntime | undefined;
12
- /** Install before loading App code; disposal removes only this installation. */
13
- export declare function installAppRuntime(runtime: AppRuntime): () => void;
@@ -1,51 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.onAppRuntimeDispose = onAppRuntimeDispose;
4
- exports.getAppRuntime = getAppRuntime;
5
- exports.installAppRuntime = installAppRuntime;
6
- const runtimeKey = Symbol.for('tier0.sdk.app-runtime.v1');
7
- const cleanupKey = Symbol.for('tier0.sdk.app-runtime-cleanup.v1');
8
- /** Internal lifecycle registration, shared across SDK copies in the host page. */
9
- function onAppRuntimeDispose(runtime, callback) {
10
- const target = globalThis;
11
- const callbacks = target[cleanupKey] ??= new Map();
12
- const listeners = callbacks.get(runtime) ?? new Set();
13
- callbacks.set(runtime, listeners);
14
- listeners.add(callback);
15
- return () => {
16
- listeners.delete(callback);
17
- if (!listeners.size)
18
- callbacks.delete(runtime);
19
- };
20
- }
21
- function disposeRuntime(runtime) {
22
- if (!runtime)
23
- return;
24
- const callbacks = globalThis[cleanupKey];
25
- const listeners = callbacks?.get(runtime);
26
- callbacks?.delete(runtime);
27
- if (listeners)
28
- for (const listener of listeners)
29
- listener();
30
- }
31
- function getAppRuntime() {
32
- return globalThis[runtimeKey];
33
- }
34
- /** Install before loading App code; disposal removes only this installation. */
35
- function installAppRuntime(runtime) {
36
- if (!runtime.appId?.trim() || typeof runtime.request !== 'function') {
37
- throw new TypeError('Tier0 SDK: invalid trusted App runtime.');
38
- }
39
- const target = globalThis;
40
- const previous = target[runtimeKey];
41
- target[runtimeKey] = runtime;
42
- if (previous !== runtime)
43
- disposeRuntime(previous);
44
- return () => {
45
- if (target[runtimeKey] === runtime) {
46
- delete target[runtimeKey];
47
- disposeRuntime(runtime);
48
- }
49
- };
50
- }
51
- //# sourceMappingURL=runtime.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":";;AAeA,kDAUC;AAUD,sCAEC;AAGD,8CAcC;AA/CD,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;AAC1D,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAMlE,kFAAkF;AAClF,SAAgB,mBAAmB,CAAC,OAAmB,EAAE,QAAoB;IAC3E,MAAM,MAAM,GAAG,UAA2B,CAAC;IAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,IAAI,GAAG,EAAE,CAAC;IACnD,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,EAAc,CAAC;IAClE,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAClC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,GAAG,EAAE;QACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,IAAI;YAAE,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,OAA+B;IACrD,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,MAAM,SAAS,GAAI,UAA4B,CAAC,UAAU,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,SAAS;QAAE,KAAK,MAAM,QAAQ,IAAI,SAAS;YAAE,QAAQ,EAAE,CAAC;AAC9D,CAAC;AAED,SAAgB,aAAa;IAC3B,OAAQ,UAA4B,CAAC,UAAU,CAAC,CAAC;AACnD,CAAC;AAED,gFAAgF;AAChF,SAAgB,iBAAiB,CAAC,OAAmB;IACnD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACpE,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,MAAM,GAAG,UAA2B,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACpC,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;IAC7B,IAAI,QAAQ,KAAK,OAAO;QAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACnD,OAAO,GAAG,EAAE;QACV,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,OAAO,EAAE,CAAC;YACnC,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC;YAC1B,cAAc,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC;AACJ,CAAC","sourcesContent":["/** Trusted host integration; application code uses client.streams without configuration. */\nexport interface AppRuntime {\n readonly appId: string;\n /** Authenticated host bridge. Never expose a service key to the browser. */\n request(path: string, body: unknown, options: { signal: AbortSignal }): Promise<Response>;\n}\n\nconst runtimeKey = Symbol.for('tier0.sdk.app-runtime.v1');\nconst cleanupKey = Symbol.for('tier0.sdk.app-runtime-cleanup.v1');\ntype RuntimeGlobal = typeof globalThis & {\n [runtimeKey]?: AppRuntime;\n [cleanupKey]?: Map<AppRuntime, Set<() => void>>;\n};\n\n/** Internal lifecycle registration, shared across SDK copies in the host page. */\nexport function onAppRuntimeDispose(runtime: AppRuntime, callback: () => void): () => void {\n const target = globalThis as RuntimeGlobal;\n const callbacks = target[cleanupKey] ??= new Map();\n const listeners = callbacks.get(runtime) ?? new Set<() => void>();\n callbacks.set(runtime, listeners);\n listeners.add(callback);\n return () => {\n listeners.delete(callback);\n if (!listeners.size) callbacks.delete(runtime);\n };\n}\n\nfunction disposeRuntime(runtime: AppRuntime | undefined): void {\n if (!runtime) return;\n const callbacks = (globalThis as RuntimeGlobal)[cleanupKey];\n const listeners = callbacks?.get(runtime);\n callbacks?.delete(runtime);\n if (listeners) for (const listener of listeners) listener();\n}\n\nexport function getAppRuntime(): AppRuntime | undefined {\n return (globalThis as RuntimeGlobal)[runtimeKey];\n}\n\n/** Install before loading App code; disposal removes only this installation. */\nexport function installAppRuntime(runtime: AppRuntime): () => void {\n if (!runtime.appId?.trim() || typeof runtime.request !== 'function') {\n throw new TypeError('Tier0 SDK: invalid trusted App runtime.');\n }\n const target = globalThis as RuntimeGlobal;\n const previous = target[runtimeKey];\n target[runtimeKey] = runtime;\n if (previous !== runtime) disposeRuntime(previous);\n return () => {\n if (target[runtimeKey] === runtime) {\n delete target[runtimeKey];\n disposeRuntime(runtime);\n }\n };\n}\n"]}
@@ -1,22 +0,0 @@
1
- export declare const APP_REQUEST_IDENTITY_CONTRACT: {
2
- readonly version: "tier0.app-request-identity/v1";
3
- readonly header: "X-Tier0-App-Identity";
4
- readonly type: "tier0-app-request+jwt";
5
- readonly algorithm: "EdDSA";
6
- readonly issuer: "tier0-app-gateway";
7
- readonly audience: "tier0-app-runtime";
8
- readonly maxTokenBytes: 8192;
9
- readonly maxBodyBytes: 65536;
10
- readonly maxURIBytes: 8192;
11
- readonly maxTTLSeconds: 30;
12
- readonly clockSkewSeconds: 5;
13
- readonly maxRoles: 32;
14
- readonly maxRoleBytes: 128;
15
- readonly maxKeys: 8;
16
- readonly keyIDPattern: "^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$";
17
- readonly appIDPattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$";
18
- readonly requiredClaims: readonly ["ver", "iss", "aud", "sub", "workspaceID", "appID", "method", "requestURI", "bodySHA256", "iat", "exp", "jti", "roles"];
19
- readonly methodPattern: "^[A-Z]{1,16}$";
20
- readonly requiredHeaderFields: readonly ["alg", "typ", "kid"];
21
- readonly publicKeyFields: readonly ["kty", "crv", "x", "kid"];
22
- };
@@ -1,48 +0,0 @@
1
- // Generated from SWE gatewayheader/app-request-identity.v1.json; do not edit.
2
- // Source SHA-256: ac5ec2efb882395e63a46c9ec479de16c09943b88fc0bd906dd77c7f9f4bfaa3
3
- export const APP_REQUEST_IDENTITY_CONTRACT = {
4
- "version": "tier0.app-request-identity/v1",
5
- "header": "X-Tier0-App-Identity",
6
- "type": "tier0-app-request+jwt",
7
- "algorithm": "EdDSA",
8
- "issuer": "tier0-app-gateway",
9
- "audience": "tier0-app-runtime",
10
- "maxTokenBytes": 8192,
11
- "maxBodyBytes": 65536,
12
- "maxURIBytes": 8192,
13
- "maxTTLSeconds": 30,
14
- "clockSkewSeconds": 5,
15
- "maxRoles": 32,
16
- "maxRoleBytes": 128,
17
- "maxKeys": 8,
18
- "keyIDPattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$",
19
- "appIDPattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
20
- "requiredClaims": [
21
- "ver",
22
- "iss",
23
- "aud",
24
- "sub",
25
- "workspaceID",
26
- "appID",
27
- "method",
28
- "requestURI",
29
- "bodySHA256",
30
- "iat",
31
- "exp",
32
- "jti",
33
- "roles"
34
- ],
35
- "methodPattern": "^[A-Z]{1,16}$",
36
- "requiredHeaderFields": [
37
- "alg",
38
- "typ",
39
- "kid"
40
- ],
41
- "publicKeyFields": [
42
- "kty",
43
- "crv",
44
- "x",
45
- "kid"
46
- ]
47
- };
48
- //# sourceMappingURL=app-identity-contract.generated.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"app-identity-contract.generated.js","sourceRoot":"","sources":["../../src/app-identity-contract.generated.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mFAAmF;AACnF,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,SAAS,EAAE,+BAA+B;IAC1C,QAAQ,EAAE,sBAAsB;IAChC,MAAM,EAAE,uBAAuB;IAC/B,WAAW,EAAE,OAAO;IACpB,QAAQ,EAAE,mBAAmB;IAC7B,UAAU,EAAE,mBAAmB;IAC/B,eAAe,EAAE,IAAI;IACrB,cAAc,EAAE,KAAK;IACrB,aAAa,EAAE,IAAI;IACnB,eAAe,EAAE,EAAE;IACnB,kBAAkB,EAAE,CAAC;IACrB,UAAU,EAAE,EAAE;IACd,cAAc,EAAE,GAAG;IACnB,SAAS,EAAE,CAAC;IACZ,cAAc,EAAE,mCAAmC;IACnD,cAAc,EAAE,2EAA2E;IAC3F,gBAAgB,EAAE;QAChB,KAAK;QACL,KAAK;QACL,KAAK;QACL,KAAK;QACL,aAAa;QACb,OAAO;QACP,QAAQ;QACR,YAAY;QACZ,YAAY;QACZ,KAAK;QACL,KAAK;QACL,KAAK;QACL,OAAO;KACR;IACD,eAAe,EAAE,eAAe;IAChC,sBAAsB,EAAE;QACtB,KAAK;QACL,KAAK;QACL,KAAK;KACN;IACD,iBAAiB,EAAE;QACjB,KAAK;QACL,KAAK;QACL,GAAG;QACH,KAAK;KACN;CACO,CAAC","sourcesContent":["// Generated from SWE gatewayheader/app-request-identity.v1.json; do not edit.\n// Source SHA-256: ac5ec2efb882395e63a46c9ec479de16c09943b88fc0bd906dd77c7f9f4bfaa3\nexport const APP_REQUEST_IDENTITY_CONTRACT = {\n \"version\": \"tier0.app-request-identity/v1\",\n \"header\": \"X-Tier0-App-Identity\",\n \"type\": \"tier0-app-request+jwt\",\n \"algorithm\": \"EdDSA\",\n \"issuer\": \"tier0-app-gateway\",\n \"audience\": \"tier0-app-runtime\",\n \"maxTokenBytes\": 8192,\n \"maxBodyBytes\": 65536,\n \"maxURIBytes\": 8192,\n \"maxTTLSeconds\": 30,\n \"clockSkewSeconds\": 5,\n \"maxRoles\": 32,\n \"maxRoleBytes\": 128,\n \"maxKeys\": 8,\n \"keyIDPattern\": \"^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$\",\n \"appIDPattern\": \"^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$\",\n \"requiredClaims\": [\n \"ver\",\n \"iss\",\n \"aud\",\n \"sub\",\n \"workspaceID\",\n \"appID\",\n \"method\",\n \"requestURI\",\n \"bodySHA256\",\n \"iat\",\n \"exp\",\n \"jti\",\n \"roles\"\n ],\n \"methodPattern\": \"^[A-Z]{1,16}$\",\n \"requiredHeaderFields\": [\n \"alg\",\n \"typ\",\n \"kid\"\n ],\n \"publicKeyFields\": [\n \"kty\",\n \"crv\",\n \"x\",\n \"kid\"\n ]\n} as const;\n"]}
@@ -1,13 +0,0 @@
1
- /** Trusted host integration; application code uses client.streams without configuration. */
2
- export interface AppRuntime {
3
- readonly appId: string;
4
- /** Authenticated host bridge. Never expose a service key to the browser. */
5
- request(path: string, body: unknown, options: {
6
- signal: AbortSignal;
7
- }): Promise<Response>;
8
- }
9
- /** Internal lifecycle registration, shared across SDK copies in the host page. */
10
- export declare function onAppRuntimeDispose(runtime: AppRuntime, callback: () => void): () => void;
11
- export declare function getAppRuntime(): AppRuntime | undefined;
12
- /** Install before loading App code; disposal removes only this installation. */
13
- export declare function installAppRuntime(runtime: AppRuntime): () => void;
@@ -1,46 +0,0 @@
1
- const runtimeKey = Symbol.for('tier0.sdk.app-runtime.v1');
2
- const cleanupKey = Symbol.for('tier0.sdk.app-runtime-cleanup.v1');
3
- /** Internal lifecycle registration, shared across SDK copies in the host page. */
4
- export function onAppRuntimeDispose(runtime, callback) {
5
- const target = globalThis;
6
- const callbacks = target[cleanupKey] ??= new Map();
7
- const listeners = callbacks.get(runtime) ?? new Set();
8
- callbacks.set(runtime, listeners);
9
- listeners.add(callback);
10
- return () => {
11
- listeners.delete(callback);
12
- if (!listeners.size)
13
- callbacks.delete(runtime);
14
- };
15
- }
16
- function disposeRuntime(runtime) {
17
- if (!runtime)
18
- return;
19
- const callbacks = globalThis[cleanupKey];
20
- const listeners = callbacks?.get(runtime);
21
- callbacks?.delete(runtime);
22
- if (listeners)
23
- for (const listener of listeners)
24
- listener();
25
- }
26
- export function getAppRuntime() {
27
- return globalThis[runtimeKey];
28
- }
29
- /** Install before loading App code; disposal removes only this installation. */
30
- export function installAppRuntime(runtime) {
31
- if (!runtime.appId?.trim() || typeof runtime.request !== 'function') {
32
- throw new TypeError('Tier0 SDK: invalid trusted App runtime.');
33
- }
34
- const target = globalThis;
35
- const previous = target[runtimeKey];
36
- target[runtimeKey] = runtime;
37
- if (previous !== runtime)
38
- disposeRuntime(previous);
39
- return () => {
40
- if (target[runtimeKey] === runtime) {
41
- delete target[runtimeKey];
42
- disposeRuntime(runtime);
43
- }
44
- };
45
- }
46
- //# sourceMappingURL=runtime.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;AAC1D,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAMlE,kFAAkF;AAClF,MAAM,UAAU,mBAAmB,CAAC,OAAmB,EAAE,QAAoB;IAC3E,MAAM,MAAM,GAAG,UAA2B,CAAC;IAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,IAAI,GAAG,EAAE,CAAC;IACnD,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,EAAc,CAAC;IAClE,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAClC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,GAAG,EAAE;QACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,IAAI;YAAE,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,OAA+B;IACrD,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,MAAM,SAAS,GAAI,UAA4B,CAAC,UAAU,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,SAAS;QAAE,KAAK,MAAM,QAAQ,IAAI,SAAS;YAAE,QAAQ,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAQ,UAA4B,CAAC,UAAU,CAAC,CAAC;AACnD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAAC,OAAmB;IACnD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACpE,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,MAAM,GAAG,UAA2B,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACpC,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;IAC7B,IAAI,QAAQ,KAAK,OAAO;QAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACnD,OAAO,GAAG,EAAE;QACV,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,OAAO,EAAE,CAAC;YACnC,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC;YAC1B,cAAc,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC;AACJ,CAAC","sourcesContent":["/** Trusted host integration; application code uses client.streams without configuration. */\nexport interface AppRuntime {\n readonly appId: string;\n /** Authenticated host bridge. Never expose a service key to the browser. */\n request(path: string, body: unknown, options: { signal: AbortSignal }): Promise<Response>;\n}\n\nconst runtimeKey = Symbol.for('tier0.sdk.app-runtime.v1');\nconst cleanupKey = Symbol.for('tier0.sdk.app-runtime-cleanup.v1');\ntype RuntimeGlobal = typeof globalThis & {\n [runtimeKey]?: AppRuntime;\n [cleanupKey]?: Map<AppRuntime, Set<() => void>>;\n};\n\n/** Internal lifecycle registration, shared across SDK copies in the host page. */\nexport function onAppRuntimeDispose(runtime: AppRuntime, callback: () => void): () => void {\n const target = globalThis as RuntimeGlobal;\n const callbacks = target[cleanupKey] ??= new Map();\n const listeners = callbacks.get(runtime) ?? new Set<() => void>();\n callbacks.set(runtime, listeners);\n listeners.add(callback);\n return () => {\n listeners.delete(callback);\n if (!listeners.size) callbacks.delete(runtime);\n };\n}\n\nfunction disposeRuntime(runtime: AppRuntime | undefined): void {\n if (!runtime) return;\n const callbacks = (globalThis as RuntimeGlobal)[cleanupKey];\n const listeners = callbacks?.get(runtime);\n callbacks?.delete(runtime);\n if (listeners) for (const listener of listeners) listener();\n}\n\nexport function getAppRuntime(): AppRuntime | undefined {\n return (globalThis as RuntimeGlobal)[runtimeKey];\n}\n\n/** Install before loading App code; disposal removes only this installation. */\nexport function installAppRuntime(runtime: AppRuntime): () => void {\n if (!runtime.appId?.trim() || typeof runtime.request !== 'function') {\n throw new TypeError('Tier0 SDK: invalid trusted App runtime.');\n }\n const target = globalThis as RuntimeGlobal;\n const previous = target[runtimeKey];\n target[runtimeKey] = runtime;\n if (previous !== runtime) disposeRuntime(previous);\n return () => {\n if (target[runtimeKey] === runtime) {\n delete target[runtimeKey];\n disposeRuntime(runtime);\n }\n };\n}\n"]}