@tier0/sdk-v2 0.9.10 → 0.10.1

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 (238) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/LICENSE +21 -21
  3. package/README.md +162 -24
  4. package/dist/cjs/client.d.ts +83 -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 +21 -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 +75 -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 +206 -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 +83 -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 +21 -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 +75 -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 +206 -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 +14 -12
  222. package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md +3 -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/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/update.md +11 -0
  227. package/dist/cjs/app-identity-contract.generated.d.ts +0 -22
  228. package/dist/cjs/app-identity-contract.generated.js +0 -51
  229. package/dist/cjs/app-identity-contract.generated.js.map +0 -1
  230. package/dist/cjs/runtime.d.ts +0 -13
  231. package/dist/cjs/runtime.js +0 -51
  232. package/dist/cjs/runtime.js.map +0 -1
  233. package/dist/esm/app-identity-contract.generated.d.ts +0 -22
  234. package/dist/esm/app-identity-contract.generated.js +0 -48
  235. package/dist/esm/app-identity-contract.generated.js.map +0 -1
  236. package/dist/esm/runtime.d.ts +0 -13
  237. package/dist/esm/runtime.js +0 -46
  238. 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,15 @@
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.
11
+
12
+ Builder configures request grants using the management operations exposed by the current MCP contract: `/openapi/v2/uns/stream-requests/grants/get` and `/openapi/v2/uns/stream-requests/grants/set`, and `/openapi/v2/uns/app-stream-access/list`. Use the injected system key's current `stream.requests.manage` permission; its bound App is build context, so it may manage target Apps in the same workspace. Granted actions cannot exceed the manager's current permissions. Read the grant snapshot before updating or revoking, and reconcile state after conflicts or unknown outcomes. App runtime keys cannot manage grants. These management operations are separate from `client.streams` execution; do not invent a `client.uns` grant method.
9
13
 
10
14
  ## Select the interaction
11
15
 
@@ -16,13 +20,11 @@ Read the [root Skill](../SKILL.md) first. These APIs require an artifact built f
16
20
 
17
21
  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
22
 
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.
23
+ ## Server only
22
24
 
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.
25
+ 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
26
 
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.
27
+ 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
28
 
27
29
  ## Public caller
28
30
 
@@ -31,12 +33,12 @@ import { createClient, type StreamMessageError } from '@tier0/sdk-v2';
31
33
 
32
34
  export async function openOrders(
33
35
  reportError: (error: StreamMessageError) => void,
34
- renderOrderUpdate: (order: { orderId: string }) => void,
36
+ onOrderUpdate: (order: { orderId: string }) => void,
35
37
  ) {
36
- const sdk = createClient(); // automatically uses the trusted App runtime
38
+ const sdk = createClient(); // server: TIER0_API_HOST / TIER0_API_KEY
37
39
  const removeErrorHandler = sdk.streams.messages.onError(reportError);
38
40
  const subscription = await sdk.streams.messages.use<{ orderId: string }>({ topic: 'orders/accepted' })
39
- .subscribe(message => renderOrderUpdate(message.payload));
41
+ .subscribe(message => onOrderUpdate(message.payload));
40
42
  const request = sdk.streams.requests.use<{ orderId: string }, { accepted: boolean }>({ code: 'orders.approve' });
41
43
  return {
42
44
  describe: () => request.describe(),
@@ -56,9 +58,9 @@ Persist one caller-owned idempotency key per business intent. A deliberate recon
56
58
 
57
59
  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
60
 
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.
61
+ 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
62
 
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.
63
+ 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
64
 
63
65
  ## Stream-side code
64
66
 
@@ -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 / service-system Key,或治理会话。内置 Builder 以自身系统身份主动为同一工作区的 App 关联已有集合,当前绑定 App 不限制授权目标,不查询对话用户的角色、不要求其确认;外部 Key 按自身权限执行。新增、扩大、收窄和移除授权走同一管理校验,受工作区、目标 App、当前资源权限和提交前凭据复验约束,没有 Agent 身份禁令或平台导入特例。
9
9
 
10
10
  先按[命名空间指导](references/namespace.md)区分凭证:`namespace()` 走 OpenAPI,但当前不对 App Key 开放;App 查询可用集合走 `dataAppContext`,不能改用同样受限的 `appCollectionsList`。Agent / Personal Key 也须满足当前工作空间权限;不要从“使用 SDK / MCP”推定权限。
11
11
 
@@ -17,8 +17,10 @@ UNS 管数据命名空间、集合、Record 和 Sample;外部连接与脚本
17
17
  | --- | --- | --- |
18
18
  | 创建集合、定义 Schema、新增记录 | [创建](references/create.md) | metadataInsertOne/Many、recordInsertOne |
19
19
  | 查询集合、筛选/排序记录 | [查询](references/read.md) | dataAppContext、metadataFind/FindOne(非 App 凭证)、collectionDescribe、recordFind |
20
+ | 把已有集合授权给 App | [修改](references/update.md#已有集合授权给-app) | appDataPolicyGet、appDataPolicyUpdate |
20
21
  | 改记录、集合名称、扩展 Schema | [修改](references/update.md) | recordUpdateOne、metadataUpdateOne/Many |
21
22
  | 删记录、软删除集合 | [删除](references/delete.md) | recordDeleteOne、metadataDeleteOne/Many |
23
+ | 精确删除选中的历史样本 | [删除](references/delete.md#精确删除历史样本) | sampleFind、sampleDeleteExact(非 App 凭证) |
22
24
  | 永久删除回收站集合 | [删除](references/delete.md) | metadataPurge、jobs |
23
25
  | 恢复集合或记录 | [恢复](references/restore.md) | metadataRestore、recordRestore |
24
26
  | 分页、历史采样、事务、写入结果 | [数据工作流](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#回收规则)说明写入和恢复边界。
@@ -60,3 +60,14 @@ export async function renameDevice(
60
60
  return { state: 'committed' as const, receipt, current: after.data.items[0] };
61
61
  }
62
62
  ```
63
+
64
+ ## 已有集合授权给 App
65
+
66
+ 这是 Builder 的管理操作,使用内置 MCP 注入的系统身份;不从 App 运行时取得管理 Key,也不需要对话用户具有 Owner/Admin 角色或再次确认。外部 personal / agent Key 按自身当前权限调用同一接口。Builder 可为同一工作区内的 App 管理授权,当前绑定 App 仅是构建上下文。服务端校验工作区、目标 App 状态和所授资源权限,App 运行时凭证不能管理授权。
67
+
68
+ - 先发现并确认真实的 `collectionId`、结构和当前目标 `appId`;保留已有集合所属 App、目录和数据,不创建同名空集合代替。
69
+ - 调用 `appDataPolicyGet({ appId })` 读取当前策略及 `revision`。使用 `appDataPolicyUpdate` 的 `changes` 增量提交,以 `action: 'upsert'`、实际 `collectionId` 和业务所需 `permissions` 关联集合;`alias` 可省略,不能同时传 `collections`。`upsert` 指定该集合的完整目标权限,其他集合授权保留。
70
+ - 传入读到的 `expectedRevision`、现有 `status` 和本次操作的独立 `idempotencyKey`,执行时 `dryRun: false`。策略已 `disabled` 时,关联不应顺便重新启用;恢复策略是另一个明确管理动作。
71
+ - 检查写入回执 `data.status === 'committed'`,再读取策略核对集合与权限已生效。随后使用 App 运行时的 `dataAppContext` 确认有效授权,并用真实 App 凭证读取已有记录;需要写入时按实际业务验证写入结果。管理身份能查到数据不代表 App 已获授权。
72
+
73
+ `expectedRevision` 冲突时重读策略并重新计算改动;403 保留原错误,不换凭证或复制集合绕过。结果为 `unknown` 时先读回核对,未确认结果前不自动重试。对话确认不是后端权限凭据,也不需要新增确认字段。
@@ -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"]}