@segmentstream/ontology 0.0.0-stage → 0.92.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 (483) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +2 -0
  3. package/README.md +1655 -2
  4. package/dist/action.d.ts +193 -0
  5. package/dist/action.js +41 -0
  6. package/dist/agent-chat.d.ts +44 -0
  7. package/dist/agent-chat.js +91 -0
  8. package/dist/agent-task-contract.d.ts +64 -0
  9. package/dist/agent-task-contract.js +15 -0
  10. package/dist/agent-task.d.ts +39 -0
  11. package/dist/agent-task.js +112 -0
  12. package/dist/analyze.d.ts +215 -0
  13. package/dist/analyze.js +2438 -0
  14. package/dist/app-feedback.d.ts +167 -0
  15. package/dist/app-feedback.js +176 -0
  16. package/dist/authoring-input.d.ts +3 -0
  17. package/dist/authoring-input.js +107 -0
  18. package/dist/authoring-names.d.ts +4 -0
  19. package/dist/authoring-names.js +13 -0
  20. package/dist/authoring-records.d.ts +35 -0
  21. package/dist/authoring-records.js +264 -0
  22. package/dist/authoring.d.ts +15 -0
  23. package/dist/authoring.js +331 -0
  24. package/dist/bin/check.d.ts +30 -0
  25. package/dist/bin/check.js +99 -0
  26. package/dist/bin/load.d.ts +48 -0
  27. package/dist/bin/load.js +139 -0
  28. package/dist/bin/main.d.ts +31 -0
  29. package/dist/bin/main.js +121 -0
  30. package/dist/bin/migrate.d.ts +57 -0
  31. package/dist/bin/migrate.js +170 -0
  32. package/dist/bin/output.d.ts +31 -0
  33. package/dist/bin/output.js +84 -0
  34. package/dist/bin.d.ts +2 -0
  35. package/dist/bin.js +31 -0
  36. package/dist/blob.d.ts +52 -0
  37. package/dist/blob.js +87 -0
  38. package/dist/channel-session.d.ts +16 -0
  39. package/dist/channel-session.js +16 -0
  40. package/dist/chat.d.ts +43 -0
  41. package/dist/chat.js +34 -0
  42. package/dist/confirmation.d.ts +46 -0
  43. package/dist/confirmation.js +41 -0
  44. package/dist/connection.d.ts +213 -0
  45. package/dist/connection.js +289 -0
  46. package/dist/deployment.d.ts +35 -0
  47. package/dist/deployment.js +76 -0
  48. package/dist/diagnostics.d.ts +27 -0
  49. package/dist/diagnostics.js +106 -0
  50. package/dist/emails.d.ts +70 -0
  51. package/dist/emails.js +221 -0
  52. package/dist/entity.d.ts +331 -0
  53. package/dist/entity.js +153 -0
  54. package/dist/errors.d.ts +154 -0
  55. package/dist/errors.js +109 -0
  56. package/dist/feedback-config.d.ts +24 -0
  57. package/dist/feedback-config.js +126 -0
  58. package/dist/files.d.ts +39 -0
  59. package/dist/files.js +4 -0
  60. package/dist/groups.d.ts +95 -0
  61. package/dist/groups.js +280 -0
  62. package/dist/index.d.ts +109 -0
  63. package/dist/index.js +70 -0
  64. package/dist/internal/diagnostics.js +594 -0
  65. package/dist/legacy.d.ts +160 -0
  66. package/dist/legacy.js +270 -0
  67. package/dist/manifest-compatibility.d.ts +8 -0
  68. package/dist/manifest-compatibility.js +87 -0
  69. package/dist/manifest.d.ts +3329 -0
  70. package/dist/manifest.js +757 -0
  71. package/dist/me.d.ts +46 -0
  72. package/dist/me.js +109 -0
  73. package/dist/metric-filters.d.ts +48 -0
  74. package/dist/metric-filters.js +252 -0
  75. package/dist/metric-routes.d.ts +132 -0
  76. package/dist/metric-routes.js +498 -0
  77. package/dist/metric.d.ts +172 -0
  78. package/dist/metric.js +132 -0
  79. package/dist/migrate/apply.d.ts +94 -0
  80. package/dist/migrate/apply.js +526 -0
  81. package/dist/migrate/errors.d.ts +46 -0
  82. package/dist/migrate/errors.js +38 -0
  83. package/dist/migrate/index.d.ts +10 -0
  84. package/dist/migrate/index.js +7 -0
  85. package/dist/migrate/model.d.ts +2311 -0
  86. package/dist/migrate/model.js +148 -0
  87. package/dist/migrate/plan.d.ts +51 -0
  88. package/dist/migrate/plan.js +1856 -0
  89. package/dist/migrate/preview.d.ts +13 -0
  90. package/dist/migrate/preview.js +65 -0
  91. package/dist/migrate/storage.d.ts +226 -0
  92. package/dist/migrate/storage.js +774 -0
  93. package/dist/model-metrics.d.ts +22 -0
  94. package/dist/model-metrics.js +545 -0
  95. package/dist/names.d.ts +49 -0
  96. package/dist/names.js +110 -0
  97. package/dist/navigation-artifact.d.ts +13 -0
  98. package/dist/navigation-artifact.js +11 -0
  99. package/dist/navigation-catalog.d.ts +55 -0
  100. package/dist/navigation-catalog.js +297 -0
  101. package/dist/nitro-navigation.d.ts +3 -0
  102. package/dist/nitro-navigation.js +64 -0
  103. package/dist/nitro-workflows.d.ts +108 -0
  104. package/dist/nitro-workflows.js +286 -0
  105. package/dist/nitro.d.ts +40 -0
  106. package/dist/nitro.js +50 -0
  107. package/dist/ontology.d.ts +41 -0
  108. package/dist/ontology.js +46 -0
  109. package/dist/permissions.d.ts +198 -0
  110. package/dist/permissions.js +272 -0
  111. package/dist/property.d.ts +188 -0
  112. package/dist/property.js +301 -0
  113. package/dist/query.d.ts +245 -0
  114. package/dist/query.js +615 -0
  115. package/dist/relationship.d.ts +99 -0
  116. package/dist/relationship.js +33 -0
  117. package/dist/render.d.ts +81 -0
  118. package/dist/render.js +512 -0
  119. package/dist/replication/baseline.d.ts +51 -0
  120. package/dist/replication/baseline.js +215 -0
  121. package/dist/replication/bigquery.d.ts +37 -0
  122. package/dist/replication/bigquery.js +211 -0
  123. package/dist/replication/coverage.d.ts +14 -0
  124. package/dist/replication/coverage.js +53 -0
  125. package/dist/replication/evolution.d.ts +25 -0
  126. package/dist/replication/evolution.js +184 -0
  127. package/dist/replication/identities.d.ts +6 -0
  128. package/dist/replication/identities.js +47 -0
  129. package/dist/replication/legacy-baseline.d.ts +27 -0
  130. package/dist/replication/legacy-baseline.js +109 -0
  131. package/dist/replication/legacy-store.d.ts +19 -0
  132. package/dist/replication/legacy-store.js +63 -0
  133. package/dist/replication/lineage.d.ts +36 -0
  134. package/dist/replication/lineage.js +72 -0
  135. package/dist/replication/migrate.d.ts +21 -0
  136. package/dist/replication/migrate.js +84 -0
  137. package/dist/replication/model.d.ts +52 -0
  138. package/dist/replication/model.js +99 -0
  139. package/dist/replication/scans.d.ts +34 -0
  140. package/dist/replication/scans.js +158 -0
  141. package/dist/replication/schema.d.ts +11 -0
  142. package/dist/replication/schema.js +226 -0
  143. package/dist/replication/shadow-schema.d.ts +4 -0
  144. package/dist/replication/shadow-schema.js +61 -0
  145. package/dist/replication/shadow.d.ts +127 -0
  146. package/dist/replication/shadow.js +614 -0
  147. package/dist/replication/source-replacement.d.ts +33 -0
  148. package/dist/replication/source-replacement.js +76 -0
  149. package/dist/replication/store.d.ts +36 -0
  150. package/dist/replication/store.js +382 -0
  151. package/dist/replication/transaction.d.ts +23 -0
  152. package/dist/replication/transaction.js +88 -0
  153. package/dist/role.d.ts +61 -0
  154. package/dist/role.js +76 -0
  155. package/dist/runtime/action-deadlocks.d.ts +21 -0
  156. package/dist/runtime/action-deadlocks.js +130 -0
  157. package/dist/runtime/action-transactions.d.ts +35 -0
  158. package/dist/runtime/action-transactions.js +54 -0
  159. package/dist/runtime/agent-counters.d.ts +26 -0
  160. package/dist/runtime/agent-counters.js +98 -0
  161. package/dist/runtime/agent-tasks.d.ts +63 -0
  162. package/dist/runtime/agent-tasks.js +120 -0
  163. package/dist/runtime/agents.d.ts +15 -0
  164. package/dist/runtime/agents.js +457 -0
  165. package/dist/runtime/batch-diagnostics.d.ts +22 -0
  166. package/dist/runtime/batch-diagnostics.js +89 -0
  167. package/dist/runtime/batch.d.ts +52 -0
  168. package/dist/runtime/batch.js +534 -0
  169. package/dist/runtime/channel-session-revocation.d.ts +3 -0
  170. package/dist/runtime/channel-session-revocation.js +5 -0
  171. package/dist/runtime/channel-sessions.d.ts +4 -0
  172. package/dist/runtime/channel-sessions.js +61 -0
  173. package/dist/runtime/confirmations.d.ts +29 -0
  174. package/dist/runtime/confirmations.js +57 -0
  175. package/dist/runtime/cursor.d.ts +23 -0
  176. package/dist/runtime/cursor.js +100 -0
  177. package/dist/runtime/deployment.d.ts +7 -0
  178. package/dist/runtime/deployment.js +4 -0
  179. package/dist/runtime/errors.d.ts +118 -0
  180. package/dist/runtime/errors.js +109 -0
  181. package/dist/runtime/federation-tables.d.ts +2 -0
  182. package/dist/runtime/federation-tables.js +20 -0
  183. package/dist/runtime/federation.d.ts +42 -0
  184. package/dist/runtime/federation.js +222 -0
  185. package/dist/runtime/files.d.ts +39 -0
  186. package/dist/runtime/files.js +44 -0
  187. package/dist/runtime/generated-actions.d.ts +37 -0
  188. package/dist/runtime/generated-actions.js +307 -0
  189. package/dist/runtime/history.d.ts +91 -0
  190. package/dist/runtime/history.js +77 -0
  191. package/dist/runtime/ids.d.ts +6 -0
  192. package/dist/runtime/ids.js +39 -0
  193. package/dist/runtime/member-tables.d.ts +8 -0
  194. package/dist/runtime/member-tables.js +33 -0
  195. package/dist/runtime/member-writes.d.ts +78 -0
  196. package/dist/runtime/member-writes.js +202 -0
  197. package/dist/runtime/metric-query.d.ts +19 -0
  198. package/dist/runtime/metric-query.js +411 -0
  199. package/dist/runtime/model.d.ts +67 -0
  200. package/dist/runtime/model.js +150 -0
  201. package/dist/runtime/new-user-hook.d.ts +6 -0
  202. package/dist/runtime/new-user-hook.js +37 -0
  203. package/dist/runtime/oauth.d.ts +9 -0
  204. package/dist/runtime/oauth.js +299 -0
  205. package/dist/runtime/pipeline.d.ts +155 -0
  206. package/dist/runtime/pipeline.js +597 -0
  207. package/dist/runtime/postgres-tls.d.ts +10 -0
  208. package/dist/runtime/postgres-tls.js +14 -0
  209. package/dist/runtime/principals.d.ts +302 -0
  210. package/dist/runtime/principals.js +1307 -0
  211. package/dist/runtime/reads.d.ts +55 -0
  212. package/dist/runtime/reads.js +313 -0
  213. package/dist/runtime/records.d.ts +42 -0
  214. package/dist/runtime/records.js +245 -0
  215. package/dist/runtime/resolve-agent-identity.d.ts +6 -0
  216. package/dist/runtime/resolve-agent-identity.js +181 -0
  217. package/dist/runtime/service-binding.d.ts +18 -0
  218. package/dist/runtime/service-binding.js +266 -0
  219. package/dist/runtime/sign-in-links.d.ts +68 -0
  220. package/dist/runtime/sign-in-links.js +147 -0
  221. package/dist/runtime/sql-runtime.d.ts +131 -0
  222. package/dist/runtime/sql-runtime.js +362 -0
  223. package/dist/runtime/statement.d.ts +18 -0
  224. package/dist/runtime/statement.js +31 -0
  225. package/dist/runtime/user-identities.d.ts +66 -0
  226. package/dist/runtime/user-identities.js +106 -0
  227. package/dist/runtime/user-identity-sql.d.ts +86 -0
  228. package/dist/runtime/user-identity-sql.js +297 -0
  229. package/dist/runtime/user-roles.d.ts +16 -0
  230. package/dist/runtime/user-roles.js +32 -0
  231. package/dist/runtime/validation.d.ts +16 -0
  232. package/dist/runtime/validation.js +26 -0
  233. package/dist/runtime/where.d.ts +57 -0
  234. package/dist/runtime/where.js +404 -0
  235. package/dist/runtime/workflow-admission.d.ts +49 -0
  236. package/dist/runtime/workflow-admission.js +92 -0
  237. package/dist/runtime/workflow-argument-codec.d.ts +10 -0
  238. package/dist/runtime/workflow-argument-codec.js +120 -0
  239. package/dist/runtime/workflow-arguments.d.ts +17 -0
  240. package/dist/runtime/workflow-arguments.js +99 -0
  241. package/dist/runtime/workflow-starts.d.ts +203 -0
  242. package/dist/runtime/workflow-starts.js +493 -0
  243. package/dist/runtime/workflow-users.d.ts +9 -0
  244. package/dist/runtime/workflow-users.js +17 -0
  245. package/dist/runtime/workload.d.ts +25 -0
  246. package/dist/runtime/workload.js +24 -0
  247. package/dist/runtime/writes.d.ts +108 -0
  248. package/dist/runtime/writes.js +491 -0
  249. package/dist/runtime-source.d.ts +22 -0
  250. package/dist/runtime-source.js +28 -0
  251. package/dist/runtime.d.ts +310 -0
  252. package/dist/runtime.js +31 -0
  253. package/dist/server.d.ts +23 -0
  254. package/dist/server.js +107 -0
  255. package/dist/service/agent/attachments.d.ts +33 -0
  256. package/dist/service/agent/attachments.js +228 -0
  257. package/dist/service/agent/authentication.d.ts +22 -0
  258. package/dist/service/agent/authentication.js +58 -0
  259. package/dist/service/agent/confirmations.d.ts +5 -0
  260. package/dist/service/agent/confirmations.js +73 -0
  261. package/dist/service/agent/conversation-routes.d.ts +14 -0
  262. package/dist/service/agent/conversation-routes.js +45 -0
  263. package/dist/service/agent/conversations.d.ts +40 -0
  264. package/dist/service/agent/conversations.js +69 -0
  265. package/dist/service/agent/files.d.ts +12 -0
  266. package/dist/service/agent/files.js +69 -0
  267. package/dist/service/agent/protocol.d.ts +90 -0
  268. package/dist/service/agent/protocol.js +114 -0
  269. package/dist/service/agent/server.d.ts +28 -0
  270. package/dist/service/agent/server.js +374 -0
  271. package/dist/service/agent/task-caller.d.ts +21 -0
  272. package/dist/service/agent/task-caller.js +35 -0
  273. package/dist/service/agent/task-start.d.ts +53 -0
  274. package/dist/service/agent/task-start.js +161 -0
  275. package/dist/service/agent/tasks.d.ts +40 -0
  276. package/dist/service/agent/tasks.js +155 -0
  277. package/dist/service/api.d.ts +50 -0
  278. package/dist/service/api.js +288 -0
  279. package/dist/service/authentication.d.ts +227 -0
  280. package/dist/service/authentication.js +767 -0
  281. package/dist/service/caller-context.d.ts +24 -0
  282. package/dist/service/caller-context.js +6 -0
  283. package/dist/service/catalog.d.ts +42 -0
  284. package/dist/service/catalog.js +66 -0
  285. package/dist/service/channel/provider.d.ts +10 -0
  286. package/dist/service/channel/provider.js +1 -0
  287. package/dist/service/channel/providers/telegram.d.ts +18 -0
  288. package/dist/service/channel/providers/telegram.js +108 -0
  289. package/dist/service/channel/sessions.d.ts +5 -0
  290. package/dist/service/channel/sessions.js +53 -0
  291. package/dist/service/channel/sign-in.d.ts +7 -0
  292. package/dist/service/channel/sign-in.js +78 -0
  293. package/dist/service/chat/archive.d.ts +64 -0
  294. package/dist/service/chat/archive.js +62 -0
  295. package/dist/service/chat/attribution.d.ts +26 -0
  296. package/dist/service/chat/attribution.js +28 -0
  297. package/dist/service/chat/delivery.d.ts +18 -0
  298. package/dist/service/chat/delivery.js +251 -0
  299. package/dist/service/chat/diagnostics.d.ts +2 -0
  300. package/dist/service/chat/diagnostics.js +35 -0
  301. package/dist/service/chat/envelope.d.ts +96 -0
  302. package/dist/service/chat/envelope.js +39 -0
  303. package/dist/service/chat/idempotency.d.ts +19 -0
  304. package/dist/service/chat/idempotency.js +37 -0
  305. package/dist/service/chat/providers/telegram.d.ts +36 -0
  306. package/dist/service/chat/providers/telegram.js +133 -0
  307. package/dist/service/chat/reads.d.ts +25 -0
  308. package/dist/service/chat/reads.js +75 -0
  309. package/dist/service/chat/resolve.d.ts +34 -0
  310. package/dist/service/chat/resolve.js +150 -0
  311. package/dist/service/chat/routes.d.ts +23 -0
  312. package/dist/service/chat/routes.js +75 -0
  313. package/dist/service/chat/schemas.d.ts +43 -0
  314. package/dist/service/chat/schemas.js +31 -0
  315. package/dist/service/config.d.ts +218 -0
  316. package/dist/service/config.js +265 -0
  317. package/dist/service/connection-stream.d.ts +10 -0
  318. package/dist/service/connection-stream.js +191 -0
  319. package/dist/service/connections.d.ts +60 -0
  320. package/dist/service/connections.js +271 -0
  321. package/dist/service/decisions.d.ts +35 -0
  322. package/dist/service/decisions.js +63 -0
  323. package/dist/service/descriptions.d.ts +8 -0
  324. package/dist/service/descriptions.js +20 -0
  325. package/dist/service/discovery-schemas.d.ts +92 -0
  326. package/dist/service/discovery-schemas.js +59 -0
  327. package/dist/service/discovery-search.d.ts +30 -0
  328. package/dist/service/discovery-search.js +95 -0
  329. package/dist/service/discovery.d.ts +37 -0
  330. package/dist/service/discovery.js +436 -0
  331. package/dist/service/docs.d.ts +9 -0
  332. package/dist/service/docs.js +197 -0
  333. package/dist/service/errors.d.ts +145 -0
  334. package/dist/service/errors.js +704 -0
  335. package/dist/service/federation-provider.d.ts +36 -0
  336. package/dist/service/federation-provider.js +110 -0
  337. package/dist/service/federation-server.d.ts +20 -0
  338. package/dist/service/federation-server.js +249 -0
  339. package/dist/service/federation-status.d.ts +40 -0
  340. package/dist/service/federation-status.js +151 -0
  341. package/dist/service/handlers.d.ts +18 -0
  342. package/dist/service/handlers.js +287 -0
  343. package/dist/service/mcp/confirmation.d.ts +68 -0
  344. package/dist/service/mcp/confirmation.js +178 -0
  345. package/dist/service/mcp/find-input.d.ts +12 -0
  346. package/dist/service/mcp/find-input.js +122 -0
  347. package/dist/service/mcp/input-schema.d.ts +6 -0
  348. package/dist/service/mcp/input-schema.js +126 -0
  349. package/dist/service/mcp/listing.d.ts +26 -0
  350. package/dist/service/mcp/listing.js +92 -0
  351. package/dist/service/mcp/metric-tools.d.ts +85 -0
  352. package/dist/service/mcp/metric-tools.js +258 -0
  353. package/dist/service/mcp/request-log.d.ts +5 -0
  354. package/dist/service/mcp/request-log.js +53 -0
  355. package/dist/service/mcp/runtime-policy.d.ts +27 -0
  356. package/dist/service/mcp/runtime-policy.js +62 -0
  357. package/dist/service/mcp/server.d.ts +52 -0
  358. package/dist/service/mcp/server.js +861 -0
  359. package/dist/service/mcp/tools.d.ts +99 -0
  360. package/dist/service/mcp/tools.js +938 -0
  361. package/dist/service/member-file-routes.d.ts +22 -0
  362. package/dist/service/member-file-routes.js +52 -0
  363. package/dist/service/member-files.d.ts +245 -0
  364. package/dist/service/member-files.js +258 -0
  365. package/dist/service/metric-query-platform.d.ts +77 -0
  366. package/dist/service/metric-query-platform.js +198 -0
  367. package/dist/service/metric-query-scopes.d.ts +43 -0
  368. package/dist/service/metric-query-scopes.js +147 -0
  369. package/dist/service/metric-query.d.ts +48 -0
  370. package/dist/service/metric-query.js +200 -0
  371. package/dist/service/name-suggestions.d.ts +3 -0
  372. package/dist/service/name-suggestions.js +38 -0
  373. package/dist/service/navigation-schemas.d.ts +80 -0
  374. package/dist/service/navigation-schemas.js +49 -0
  375. package/dist/service/navigation.d.ts +20 -0
  376. package/dist/service/navigation.js +165 -0
  377. package/dist/service/oauth/protocol.d.ts +70 -0
  378. package/dist/service/oauth/protocol.js +157 -0
  379. package/dist/service/oauth/refresh-replay.d.ts +2 -0
  380. package/dist/service/oauth/refresh-replay.js +20 -0
  381. package/dist/service/oauth/server.d.ts +28 -0
  382. package/dist/service/oauth/server.js +769 -0
  383. package/dist/service/operations.d.ts +170 -0
  384. package/dist/service/operations.js +392 -0
  385. package/dist/service/plan.d.ts +57 -0
  386. package/dist/service/plan.js +96 -0
  387. package/dist/service/rate-limit.d.ts +22 -0
  388. package/dist/service/rate-limit.js +52 -0
  389. package/dist/service/record-reads.d.ts +21 -0
  390. package/dist/service/record-reads.js +155 -0
  391. package/dist/service/replication.d.ts +5 -0
  392. package/dist/service/replication.js +39 -0
  393. package/dist/service/runtime-contract.d.ts +508 -0
  394. package/dist/service/runtime-contract.js +18 -0
  395. package/dist/service/runtime-identity.d.ts +71 -0
  396. package/dist/service/runtime-identity.js +122 -0
  397. package/dist/service/schemas.d.ts +961 -0
  398. package/dist/service/schemas.js +639 -0
  399. package/dist/service/service.d.ts +21 -0
  400. package/dist/service/service.js +526 -0
  401. package/dist/service/warehouse-platform.d.ts +17 -0
  402. package/dist/service/warehouse-platform.js +122 -0
  403. package/dist/service/warehouse-query.d.ts +24 -0
  404. package/dist/service/warehouse-query.js +280 -0
  405. package/dist/service/webhooks.d.ts +106 -0
  406. package/dist/service/webhooks.js +233 -0
  407. package/dist/service/workflow-admission-provider.d.ts +31 -0
  408. package/dist/service/workflow-admission-provider.js +205 -0
  409. package/dist/service/workflow-argument-serialization.d.ts +2 -0
  410. package/dist/service/workflow-argument-serialization.js +14 -0
  411. package/dist/service/workflow-callback.d.ts +22 -0
  412. package/dist/service/workflow-callback.js +75 -0
  413. package/dist/service/workflow-deployment.d.ts +8 -0
  414. package/dist/service/workflow-deployment.js +131 -0
  415. package/dist/service/workflow-diagnostics.d.ts +23 -0
  416. package/dist/service/workflow-diagnostics.js +263 -0
  417. package/dist/service/workflow-errors.d.ts +26 -0
  418. package/dist/service/workflow-errors.js +181 -0
  419. package/dist/service/workflow-logging.d.ts +2 -0
  420. package/dist/service/workflow-logging.js +50 -0
  421. package/dist/service/workflow-queue-fence.d.ts +6 -0
  422. package/dist/service/workflow-queue-fence.js +66 -0
  423. package/dist/service/workflows.d.ts +200 -0
  424. package/dist/service/workflows.js +1549 -0
  425. package/dist/sign-in.d.ts +58 -0
  426. package/dist/sign-in.js +57 -0
  427. package/dist/source.d.ts +30 -0
  428. package/dist/source.js +107 -0
  429. package/dist/start-recovery-contract.d.ts +49 -0
  430. package/dist/start-recovery-contract.js +26 -0
  431. package/dist/start-recovery.d.ts +27 -0
  432. package/dist/start-recovery.js +81 -0
  433. package/dist/storage/api.d.ts +4 -0
  434. package/dist/storage/api.js +40 -0
  435. package/dist/storage/attachments.d.ts +146 -0
  436. package/dist/storage/attachments.js +733 -0
  437. package/dist/storage/authorization.d.ts +38 -0
  438. package/dist/storage/authorization.js +83 -0
  439. package/dist/storage/file-access.d.ts +17 -0
  440. package/dist/storage/file-access.js +8 -0
  441. package/dist/storage/limits.d.ts +12 -0
  442. package/dist/storage/limits.js +17 -0
  443. package/dist/storage/maintenance-auth.d.ts +20 -0
  444. package/dist/storage/maintenance-auth.js +24 -0
  445. package/dist/storage/maintenance.d.ts +11 -0
  446. package/dist/storage/maintenance.js +67 -0
  447. package/dist/storage/neon.d.ts +4 -0
  448. package/dist/storage/neon.js +318 -0
  449. package/dist/storage/operator.d.ts +11 -0
  450. package/dist/storage/operator.js +30 -0
  451. package/dist/storage/provider.d.ts +93 -0
  452. package/dist/storage/provider.js +36 -0
  453. package/dist/storage/sessions.d.ts +184 -0
  454. package/dist/storage/sessions.js +688 -0
  455. package/dist/storage/tables.d.ts +54 -0
  456. package/dist/storage/tables.js +205 -0
  457. package/dist/storage/transfers.d.ts +16 -0
  458. package/dist/storage/transfers.js +153 -0
  459. package/dist/storage/writes.d.ts +7 -0
  460. package/dist/storage/writes.js +88 -0
  461. package/dist/telegram.d.ts +35 -0
  462. package/dist/telegram.js +173 -0
  463. package/dist/user-identity.d.ts +28 -0
  464. package/dist/user-identity.js +106 -0
  465. package/dist/user.d.ts +75 -0
  466. package/dist/user.js +111 -0
  467. package/dist/warehouse-backed.d.ts +6 -0
  468. package/dist/warehouse-backed.js +495 -0
  469. package/dist/webhook-token.d.ts +11 -0
  470. package/dist/webhook-token.js +18 -0
  471. package/dist/webhooks.d.ts +40 -0
  472. package/dist/webhooks.js +55 -0
  473. package/dist/wire.d.ts +10 -0
  474. package/dist/wire.js +35 -0
  475. package/dist/workflow-runtime.d.ts +116 -0
  476. package/dist/workflow-runtime.js +109 -0
  477. package/dist/workflow-topics.d.ts +28 -0
  478. package/dist/workflow-topics.js +28 -0
  479. package/dist/workflow.d.ts +284 -0
  480. package/dist/workflow.js +259 -0
  481. package/dist/workflows.d.ts +24 -0
  482. package/dist/workflows.js +18 -0
  483. package/package.json +127 -4
@@ -0,0 +1,198 @@
1
+ import { Data, Effect, Redacted } from "effect";
2
+ import { MetricQueryUpstreamUnavailable } from "./errors.js";
3
+ /**
4
+ * How long one metric query may take end to end, the response included. BigQuery answers most within
5
+ * seconds; the margin covers a cold warehouse and the hops to and from SegmentStream.
6
+ */
7
+ export const METRIC_QUERY_TIMEOUT_MS = 60_000;
8
+ /** The header that carries the service's request id to SegmentStream, as connection calls do. */
9
+ const REQUEST_ID_HEADER = "x-segmentstream-request-id";
10
+ /**
11
+ * The hash of the manifest the service resolved and checked the request against. SegmentStream
12
+ * answers `409 ontology_version_mismatch` when its deployed manifest differs, so a request checked
13
+ * against one ontology never runs against another.
14
+ */
15
+ export const MANIFEST_HASH_HEADER = "x-ontology-manifest-hash";
16
+ /**
17
+ * The entities the service checked `<entity>:read` on, sorted and comma-separated. SegmentStream
18
+ * answers `409 aggregate_scope_mismatch` when it would read any other, so the service's resolution
19
+ * and SegmentStream's can never drift apart unnoticed.
20
+ */
21
+ export const TOUCHED_HEADER = "x-ontology-touched";
22
+ /**
23
+ * The caller's read scopes of the stored entities the request reads scoped, base64url JSON of entity
24
+ * name to `where`, `me` resolved. SegmentStream keeps only each scope's rows wherever it reads the
25
+ * entity, confirms the scopes in `execution.rowScopes`, and answers `422
26
+ * scoped_aggregate_unavailable` for a scope the warehouse cannot apply.
27
+ */
28
+ export const ROW_SCOPES_HEADER = "x-ontology-row-scopes";
29
+ /**
30
+ * Statuses that refuse the deployment rather than the caller: its credential, its admission or the
31
+ * route itself. Passing them on would make the caller sign in again or look for a missing route.
32
+ */
33
+ const DEPLOYMENT_FAULTS = {
34
+ 401: "credential_rejected",
35
+ 403: "credential_rejected",
36
+ 404: "upstream_misconfigured",
37
+ };
38
+ /** SegmentStream would read beyond what the service checked: this deployment's SDK is behind. */
39
+ export const SCOPE_MISMATCH = "aggregate_scope_mismatch";
40
+ /** Statuses whose `Retry-After` the caller receives as SegmentStream sent it. */
41
+ const RETRY_AFTER_STATUSES = new Set([429, 503]);
42
+ /** A `Retry-After` value: seconds or an HTTP date. Anything else is not passed on. */
43
+ const RETRY_AFTER_VALUE = /^[0-9A-Za-z ,:+-]{1,64}$/;
44
+ /** The most of SegmentStream's body an operator log keeps. */
45
+ const SNIPPET_LENGTH = 500;
46
+ /** How many causes deep an operator log follows a failed call. */
47
+ const CAUSE_DEPTH = 3;
48
+ /** Hosts a deployment may reach over plain http: the machine itself, in development. */
49
+ const LOOPBACK_HOSTS = new Set(["localhost", "[::1]"]);
50
+ /** The call ended without an answer; `aborted` when the caller went away first. */
51
+ class CallFailed extends Data.TaggedError("CallFailed") {
52
+ }
53
+ function isRecord(value) {
54
+ return typeof value === "object" && value !== null && !Array.isArray(value);
55
+ }
56
+ /** The credential travels only to SegmentStream over TLS, or over plain http to this machine. */
57
+ export function securePlatform(origin) {
58
+ const { protocol, hostname } = new URL(origin);
59
+ if (protocol === "https:") {
60
+ return true;
61
+ }
62
+ return (protocol === "http:" && (LOOPBACK_HOSTS.has(hostname) || /^127(?:\.\d{1,3}){3}$/.test(hostname)));
63
+ }
64
+ /**
65
+ * A failed call for the operator: name, message and stack, then each cause, with every occurrence
66
+ * of the credential replaced.
67
+ */
68
+ export function describeError(error, redact, depth = 0) {
69
+ if (!(error instanceof Error)) {
70
+ return redact(String(error));
71
+ }
72
+ const code = error.code;
73
+ const head = error.stack ?? `${error.name}: ${error.message}`;
74
+ const own = typeof code === "string" ? `${head} [${code}]` : head;
75
+ const cause = error.cause !== undefined && depth < CAUSE_DEPTH
76
+ ? `\ncaused by: ${describeError(error.cause, redact, depth + 1)}`
77
+ : "";
78
+ return redact(`${own}${cause}`);
79
+ }
80
+ function parseObject(text) {
81
+ try {
82
+ const parsed = JSON.parse(text);
83
+ return isRecord(parsed) ? { body: parsed } : { error: new TypeError("Not a JSON object.") };
84
+ }
85
+ catch (error) {
86
+ return { error };
87
+ }
88
+ }
89
+ /**
90
+ * SegmentStream's `POST /api/v1/workspaces/{id}/metrics/query`, and its per-entity
91
+ * `…/entities/{entity}/metrics/query`, called with the workspace app credential. `undefined` when
92
+ * the deployment has none, or when SegmentStream's origin is plain http to another machine, which
93
+ * is logged once. Every request names the manifest it was checked
94
+ * against, and a redirect is refused, so the credential never leaves for another origin.
95
+ *
96
+ * Every answer but a 2xx is logged with both request ids, the status and the start of the body; a
97
+ * failed call with its message, stack and causes. The credential is redacted from all of them. A
98
+ * caller who goes away interrupts the call, which is not SegmentStream's failure.
99
+ */
100
+ export function platformMetricQueries(environment, fetchImpl = fetch) {
101
+ const { appCredential, segmentstreamUrl } = environment;
102
+ if (appCredential === undefined) {
103
+ return undefined;
104
+ }
105
+ if (!securePlatform(segmentstreamUrl)) {
106
+ Effect.runSync(Effect.logError("ontology.metric_query.insecure_platform").pipe(Effect.annotateLogs({
107
+ diagnostic: "SEGMENTSTREAM_URL is not https; metric queries are unavailable.",
108
+ platform: segmentstreamUrl,
109
+ })));
110
+ return undefined;
111
+ }
112
+ const credential = Redacted.value(appCredential);
113
+ const redact = (text) => text.split(credential).join("[redacted]");
114
+ const workspace = `${segmentstreamUrl}/api/v1/workspaces/` + encodeURIComponent(environment.workspaceId);
115
+ const urlOf = (entity) => entity === undefined
116
+ ? `${workspace}/metrics/query`
117
+ : `${workspace}/entities/${encodeURIComponent(entity)}/metrics/query`;
118
+ const exchange = (input) => Effect.tryPromise({
119
+ try: async (signal) => {
120
+ try {
121
+ const response = await fetchImpl(urlOf(input.entity), {
122
+ method: "POST",
123
+ headers: {
124
+ authorization: `Bearer ${credential}`,
125
+ "content-type": "application/json",
126
+ accept: "application/json",
127
+ [REQUEST_ID_HEADER]: input.requestId,
128
+ [MANIFEST_HASH_HEADER]: environment.manifestHash,
129
+ [TOUCHED_HEADER]: input.touched.join(","),
130
+ ...(input.rowScopes === undefined ? {} : { [ROW_SCOPES_HEADER]: input.rowScopes }),
131
+ },
132
+ body: JSON.stringify(input.body),
133
+ redirect: "error",
134
+ signal: AbortSignal.any([signal, AbortSignal.timeout(METRIC_QUERY_TIMEOUT_MS)]),
135
+ });
136
+ const text = await response.text();
137
+ return {
138
+ status: response.status,
139
+ text,
140
+ retryAfter: response.headers.get("retry-after"),
141
+ platformRequestId: response.headers.get("x-request-id"),
142
+ };
143
+ }
144
+ catch (error) {
145
+ throw new CallFailed({ error, aborted: signal.aborted });
146
+ }
147
+ },
148
+ catch: (error) => error instanceof CallFailed ? error : new CallFailed({ error, aborted: false }),
149
+ });
150
+ /** No answer: a timeout or an unreachable SegmentStream. */
151
+ const unanswered = (error, requestId) => {
152
+ const reason = error instanceof DOMException && error.name === "TimeoutError" ? "timeout" : "unreachable";
153
+ return Effect.logWarning("ontology.metric_query.upstream_failed").pipe(Effect.annotateLogs({ requestId, diagnostic: reason, error: describeError(error, redact) }), Effect.andThen(Effect.fail(new MetricQueryUpstreamUnavailable({ reason }))));
154
+ };
155
+ /** An answer: passed on, or a 502 when it faults the deployment or is not a JSON object. */
156
+ const judge = (answer, requestId) => Effect.gen(function* () {
157
+ const parsed = parseObject(answer.text);
158
+ const body = "body" in parsed ? parsed.body : undefined;
159
+ const fault = DEPLOYMENT_FAULTS[answer.status] ?? (body === undefined ? "invalid_response" : undefined);
160
+ const platformRequestId = typeof body?.requestId === "string" ? body.requestId : answer.platformRequestId;
161
+ if (fault !== undefined || answer.status < 200 || answer.status >= 300) {
162
+ const code = typeof body?.error === "string" ? body.error : undefined;
163
+ const level = fault !== undefined || code === SCOPE_MISMATCH
164
+ ? Effect.logError
165
+ : answer.status >= 500
166
+ ? Effect.logWarning
167
+ : Effect.logInfo;
168
+ yield* level(fault === undefined
169
+ ? "ontology.metric_query.platform_refused"
170
+ : "ontology.metric_query.upstream_failed").pipe(Effect.annotateLogs({
171
+ requestId,
172
+ platformRequestId: platformRequestId ?? "none",
173
+ status: answer.status,
174
+ diagnostic: fault ?? code ?? "refused",
175
+ body: redact(answer.text.slice(0, SNIPPET_LENGTH)),
176
+ ...("error" in parsed ? { error: describeError(parsed.error, redact) } : {}),
177
+ }));
178
+ }
179
+ if (fault !== undefined || body === undefined) {
180
+ return yield* new MetricQueryUpstreamUnavailable({
181
+ reason: fault ?? "invalid_response",
182
+ status: answer.status,
183
+ });
184
+ }
185
+ const retryAfter = RETRY_AFTER_STATUSES.has(answer.status) &&
186
+ answer.retryAfter !== null &&
187
+ RETRY_AFTER_VALUE.test(answer.retryAfter)
188
+ ? answer.retryAfter
189
+ : undefined;
190
+ return {
191
+ status: answer.status,
192
+ text: answer.text,
193
+ body,
194
+ ...(retryAfter === undefined ? {} : { retryAfter }),
195
+ };
196
+ });
197
+ return (input) => exchange(input).pipe(Effect.catchTag("CallFailed", (failed) => failed.aborted ? Effect.interrupt : unanswered(failed.error, input.requestId)), Effect.flatMap((answer) => judge(answer, input.requestId)));
198
+ }
@@ -0,0 +1,43 @@
1
+ import { type PermissionHolder, type ScopeWhere } from "../permissions.js";
2
+ import type { OntologyModel } from "../runtime/model.js";
3
+ /**
4
+ * Row scopes of metric queries (docs/ontology-scoped-permissions-spec.md, "Aggregates"). A metric
5
+ * query that reads an entity the caller reads through a scoped permission sends that scope along, so that
6
+ * SegmentStream keeps only the scope's rows wherever it reads the entity. `me` is the caller's user
7
+ * id, resolved here; a path from `me` needs the ontology's records to resolve, so a scope with one
8
+ * cannot travel yet and the metric query is refused, as before. A scope the service's own reads would
9
+ * compile to FALSE travels as one that matches nothing: resolving `me` would otherwise turn a marker
10
+ * on the wrong field into a valid comparison with the caller's id.
11
+ */
12
+ /** The longest `x-ontology-row-scopes` SegmentStream accepts. */
13
+ export declare const MAX_ROW_SCOPES_HEADER = 8192;
14
+ /** The caller's read scopes of the entities a metric query reads, as SegmentStream applies them. */
15
+ export type RowScopes = {
16
+ readonly ok: true;
17
+ readonly scopes: Readonly<Record<string, ScopeWhere>>;
18
+ }
19
+ /** `entity`'s scope cannot travel: it follows a path from `me`, or is too large to send. */
20
+ | {
21
+ readonly ok: false;
22
+ readonly entity: string;
23
+ readonly reason: "me_path" | "too_large";
24
+ };
25
+ /**
26
+ * Each touched entity the caller reads through a scope, with its `where` and `me` replaced by the
27
+ * caller's user id: a bare `me` compares as `{ eq: <id> }`, an operand `me` becomes the id. A scope
28
+ * the service's reads would compile to FALSE (an unknown field or operator, an operand of the wrong
29
+ * type, `me` on a field that is not a key, or a caller whose id is not a record id) matches nothing.
30
+ * A warehouse-backed entity has no stored model to check against; its scope travels as written and
31
+ * SegmentStream refuses it.
32
+ */
33
+ export declare function rowScopesOf(touched: ReadonlyArray<string>, principal: PermissionHolder & {
34
+ readonly id: string;
35
+ }, model: OntologyModel): RowScopes;
36
+ /** `x-ontology-row-scopes`: base64url of the scopes' JSON, or `undefined` without any. */
37
+ export declare function encodeRowScopes(scopes: Readonly<Record<string, ScopeWhere>>): string | undefined;
38
+ /**
39
+ * Whether SegmentStream confirmed every scope it was sent: its answer's `execution.rowScopes` names
40
+ * exactly the scoped entities. A platform that predates row scopes ignores them and confirms none,
41
+ * so its answer, which counts rows the caller may not see, is never passed on.
42
+ */
43
+ export declare function confirmsRowScopes(body: Readonly<Record<string, unknown>>, scopes: Readonly<Record<string, ScopeWhere>>): boolean;
@@ -0,0 +1,147 @@
1
+ import { mePathOf } from "../me.js";
2
+ import { readScope } from "../permissions.js";
3
+ import { FILTER_OPERATORS, MANY_QUANTIFIERS } from "../query.js";
4
+ import { isRecordId } from "../runtime/records.js";
5
+ import { isWellFormedScope } from "../runtime/where.js";
6
+ /**
7
+ * Row scopes of metric queries (docs/ontology-scoped-permissions-spec.md, "Aggregates"). A metric
8
+ * query that reads an entity the caller reads through a scoped permission sends that scope along, so that
9
+ * SegmentStream keeps only the scope's rows wherever it reads the entity. `me` is the caller's user
10
+ * id, resolved here; a path from `me` needs the ontology's records to resolve, so a scope with one
11
+ * cannot travel yet and the metric query is refused, as before. A scope the service's own reads would
12
+ * compile to FALSE travels as one that matches nothing: resolving `me` would otherwise turn a marker
13
+ * on the wrong field into a valid comparison with the caller's id.
14
+ */
15
+ /** The longest `x-ontology-row-scopes` SegmentStream accepts. */
16
+ export const MAX_ROW_SCOPES_HEADER = 8_192;
17
+ /** No row: a scope `check` would have refused, as the service's own reads treat it. */
18
+ const NO_ROWS = { or: [] };
19
+ /** Query and wire names of field operators: their operands are values, never wheres. */
20
+ const OPERATORS = new Set([
21
+ ...FILTER_OPERATORS,
22
+ "is_null",
23
+ "starts_with",
24
+ "has_any",
25
+ ]);
26
+ const QUANTIFIERS = new Set(MANY_QUANTIFIERS);
27
+ /** A path from `me`: only the ontology's records can resolve it. */
28
+ class MePath extends Error {
29
+ }
30
+ function isPlainObject(value) {
31
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32
+ }
33
+ /**
34
+ * Each touched entity the caller reads through a scope, with its `where` and `me` replaced by the
35
+ * caller's user id: a bare `me` compares as `{ eq: <id> }`, an operand `me` becomes the id. A scope
36
+ * the service's reads would compile to FALSE (an unknown field or operator, an operand of the wrong
37
+ * type, `me` on a field that is not a key, or a caller whose id is not a record id) matches nothing.
38
+ * A warehouse-backed entity has no stored model to check against; its scope travels as written and
39
+ * SegmentStream refuses it.
40
+ */
41
+ export function rowScopesOf(touched, principal, model) {
42
+ const scopes = {};
43
+ for (const entity of touched) {
44
+ const where = readScope(entity, principal);
45
+ if (where === undefined) {
46
+ continue;
47
+ }
48
+ const stored = model.entities.get(entity);
49
+ if (stored !== undefined && !isWellFormedScope(model, stored, { reader: principal, where })) {
50
+ scopes[entity] = NO_ROWS;
51
+ continue;
52
+ }
53
+ try {
54
+ scopes[entity] = resolveWhere(where, principal.id);
55
+ }
56
+ catch (error) {
57
+ if (error instanceof MePath) {
58
+ return { ok: false, entity, reason: "me_path" };
59
+ }
60
+ throw error;
61
+ }
62
+ }
63
+ const encoded = encodeRowScopes(scopes);
64
+ if (encoded !== undefined && encoded.length > MAX_ROW_SCOPES_HEADER) {
65
+ return { ok: false, entity: Object.keys(scopes).sort()[0], reason: "too_large" };
66
+ }
67
+ return { ok: true, scopes };
68
+ }
69
+ /** `x-ontology-row-scopes`: base64url of the scopes' JSON, or `undefined` without any. */
70
+ export function encodeRowScopes(scopes) {
71
+ return Object.keys(scopes).length === 0
72
+ ? undefined
73
+ : Buffer.from(JSON.stringify(scopes), "utf8").toString("base64url");
74
+ }
75
+ /** The caller's id; a stored entity's scope with `me` was checked to have a record id. */
76
+ function me(readerId) {
77
+ return isRecordId(readerId) ? readerId.toLowerCase() : readerId;
78
+ }
79
+ /** A `where`: `and`, `or` and `not` hold wheres; every other key a member's condition. */
80
+ function resolveWhere(where, readerId) {
81
+ if (!isPlainObject(where)) {
82
+ return where;
83
+ }
84
+ return Object.fromEntries(Object.entries(where).map(([key, condition]) => {
85
+ if (key === "and" || key === "or") {
86
+ return [
87
+ key,
88
+ Array.isArray(condition)
89
+ ? condition.map((sub) => resolveWhere(sub, readerId))
90
+ : condition,
91
+ ];
92
+ }
93
+ if (key === "not") {
94
+ return [key, resolveWhere(condition, readerId)];
95
+ }
96
+ return [key, resolveMember(condition, readerId)];
97
+ }));
98
+ }
99
+ /**
100
+ * A field's or relationship's condition: bare `me`, an object of operators whose operands may be
101
+ * `me`, a to-many filter of quantifiers, or a related record's where.
102
+ */
103
+ function resolveMember(condition, readerId) {
104
+ const hops = mePathOf(condition);
105
+ if (hops !== undefined) {
106
+ if (hops.length > 0) {
107
+ throw new MePath();
108
+ }
109
+ return { eq: me(readerId) };
110
+ }
111
+ if (!isPlainObject(condition)) {
112
+ return condition;
113
+ }
114
+ const keys = Object.keys(condition);
115
+ if (keys.length > 0 && keys.every((key) => OPERATORS.has(key))) {
116
+ return Object.fromEntries(Object.entries(condition).map(([operator, operand]) => {
117
+ const operandHops = mePathOf(operand);
118
+ if (operandHops === undefined) {
119
+ return [operator, operand];
120
+ }
121
+ if (operandHops.length > 0) {
122
+ throw new MePath();
123
+ }
124
+ return [operator, me(readerId)];
125
+ }));
126
+ }
127
+ if (keys.length > 0 && keys.every((key) => QUANTIFIERS.has(key))) {
128
+ return Object.fromEntries(Object.entries(condition).map(([quantifier, where]) => [
129
+ quantifier,
130
+ resolveWhere(where, readerId),
131
+ ]));
132
+ }
133
+ return resolveWhere(condition, readerId);
134
+ }
135
+ /**
136
+ * Whether SegmentStream confirmed every scope it was sent: its answer's `execution.rowScopes` names
137
+ * exactly the scoped entities. A platform that predates row scopes ignores them and confirms none,
138
+ * so its answer, which counts rows the caller may not see, is never passed on.
139
+ */
140
+ export function confirmsRowScopes(body, scopes) {
141
+ const execution = body.execution;
142
+ const confirmed = isPlainObject(execution) ? execution.rowScopes : undefined;
143
+ const expected = Object.keys(scopes).sort();
144
+ return (Array.isArray(confirmed) &&
145
+ confirmed.length === expected.length &&
146
+ [...confirmed].sort().every((entity, index) => entity === expected[index]));
147
+ }
@@ -0,0 +1,48 @@
1
+ import { Effect } from "effect";
2
+ import type { Ontology } from "../ontology.js";
3
+ import type { MetricQueryTransport, PlatformAnswer } from "./metric-query-platform.js";
4
+ import { CurrentPrincipal } from "./authentication.js";
5
+ import { MetricQueryLimited, MetricQueriesUnavailable, MetricQueryUpstreamUnavailable, InvalidMetricQuery, InvalidRequestBody, ReadDenied, RequestId, ScopedMetricQueryUnavailable } from "./errors.js";
6
+ import { type RateLimit, type RateLimiter } from "./rate-limit.js";
7
+ /**
8
+ * Metric queries one principal may run per minute, through both routes and the MCP tool together.
9
+ * Each runs a warehouse query with the deployment's credential, so one caller must not spend without
10
+ * bound.
11
+ */
12
+ export declare const METRIC_QUERY_LIMIT: RateLimit;
13
+ /** Every way the facade refuses or fails a metric query before SegmentStream answers it. */
14
+ export type MetricQueryFailure = MetricQueryLimited | InvalidRequestBody | InvalidMetricQuery | ReadDenied | ScopedMetricQueryUnavailable | MetricQueriesUnavailable | MetricQueryUpstreamUnavailable;
15
+ /**
16
+ * Runs a metric query as the caller, whatever the transport: the HTTP route passes the parsed body,
17
+ * the MCP tool its arguments. Its answer is SegmentStream's, error statuses included.
18
+ */
19
+ export type QueryMetrics = (body: unknown) => Effect.Effect<PlatformAnswer, MetricQueryFailure, CurrentPrincipal | RequestId>;
20
+ /** The service's metric queries: model-level, and the per-entity shorthand of each entity. */
21
+ export interface MetricQueries {
22
+ /** `POST /api/ontology/query_metrics` and the MCP `query_metrics` tool. */
23
+ readonly model: QueryMetrics;
24
+ /** `POST /api/ontology/<entity>/query_metrics`, the shorthand `segmentstream.ontology.<entity>`. */
25
+ readonly entity: (entity: string) => QueryMetrics;
26
+ }
27
+ /**
28
+ * The ontology service's metric query facade (docs/ontology-aggregates-spec.md, "Surfaces"). Both
29
+ * routes and the MCP tool run as the caller:
30
+ * 0. the call counts against the caller's {@link METRIC_QUERY_LIMIT}, whichever way it came;
31
+ * 1. the request's shape and bounds are checked, and its names resolved against the service's own
32
+ * manifest into every entity it reads;
33
+ * 2. the caller needs `<entity>:read` on all of them; a read scope on any of them travels along,
34
+ * `me` resolved, and SegmentStream keeps only the scope's rows wherever it reads that entity. A
35
+ * scope with a path from `me` is refused with `ScopedMetricQueryUnavailable`;
36
+ * 3. the body goes to SegmentStream as it came, earlier names renamed (`withCurrentMetricQueryNames`),
37
+ * with the workspace app credential, naming the entities checked, or the answer is
38
+ * `aggregate_unavailable` where the deployment has no credential;
39
+ * 4. an answer to a scoped request must confirm every scope it was sent in `execution.rowScopes`,
40
+ * and a scope SegmentStream cannot apply is refused with `ScopedMetricQueryUnavailable`: a platform
41
+ * that ignored the scopes never answers a scoped caller.
42
+ */
43
+ export declare function makeMetricQueries(input: {
44
+ readonly ontology: Ontology;
45
+ readonly transport: MetricQueryTransport | undefined;
46
+ /** One bucket per principal; {@link METRIC_QUERY_LIMIT} by default. */
47
+ readonly limiter?: RateLimiter;
48
+ }): MetricQueries;
@@ -0,0 +1,200 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { resolveMetricRoutes } from "../metric-routes.js";
3
+ import { withCurrentMetricQueryNames } from "../legacy.js";
4
+ import { isAllowed, permissionOf, READ_VERB } from "../permissions.js";
5
+ import { ontologyModel } from "../runtime/model.js";
6
+ import { confirmsRowScopes, encodeRowScopes, rowScopesOf } from "./metric-query-scopes.js";
7
+ import { CurrentPrincipal } from "./authentication.js";
8
+ import { MetricQueryLimited, MetricQueriesUnavailable, InvalidMetricQuery, InvalidRequestBody, ReadDenied, RequestId, schemaIssues, ScopedMetricQueryUnavailable, } from "./errors.js";
9
+ import { fixedWindowLimiter } from "./rate-limit.js";
10
+ import { MetricQuery, EntityMetricQuery } from "./schemas.js";
11
+ /**
12
+ * Metric queries one principal may run per minute, through both routes and the MCP tool together.
13
+ * Each runs a warehouse query with the deployment's credential, so one caller must not spend without
14
+ * bound.
15
+ */
16
+ export const METRIC_QUERY_LIMIT = { limit: 30, windowMs: 60_000, maxKeys: 10_000 };
17
+ function decode(schema, body) {
18
+ return Schema.decodeUnknownEffect(schema)(body, { errors: "all" }).pipe(Effect.mapError((error) => new InvalidRequestBody({ reason: "invalid_request", issues: schemaIssues(error.issue) })));
19
+ }
20
+ /**
21
+ * The first `orderBy` entry that names neither a requested metric nor a requested dimension, by
22
+ * its requested name or its identity. Ordering by anything else would read what the permission
23
+ * check never saw.
24
+ */
25
+ function unrequestedOrder(request, routes) {
26
+ const dimensions = new Set([
27
+ ...(request.dimensions ?? []),
28
+ ...(routes.entities[0]?.dimensions ?? []).map(({ identity }) => identity),
29
+ ]);
30
+ for (const order of request.orderBy ?? []) {
31
+ if (order.metric !== undefined && !request.metrics.includes(order.metric)) {
32
+ return order.metric;
33
+ }
34
+ if (order.dimension !== undefined && !dimensions.has(order.dimension)) {
35
+ return order.dimension;
36
+ }
37
+ }
38
+ return undefined;
39
+ }
40
+ /**
41
+ * A model-level request's entities, as the shared resolver finds them: each metric's entity,
42
+ * every entity on a dimension's or a filter's route, intermediates included, and every entity a
43
+ * filter names even where it does not apply.
44
+ */
45
+ function modelTouched(manifest, body) {
46
+ return Effect.gen(function* () {
47
+ const request = yield* decode(MetricQuery, body);
48
+ const routes = resolveMetricRoutes(manifest, {
49
+ metrics: request.metrics,
50
+ dimensions: request.dimensions ?? [],
51
+ filters: (request.filters ?? []).map((filter) => filter.dimension),
52
+ ...(request.granularityOf === undefined ? {} : { granularityOf: request.granularityOf }),
53
+ });
54
+ if (!routes.ok) {
55
+ return yield* new InvalidMetricQuery({ reason: routes.reason });
56
+ }
57
+ const unordered = unrequestedOrder(request, routes);
58
+ if (unordered !== undefined) {
59
+ return yield* new InvalidMetricQuery({
60
+ reason: `orderBy names ${unordered}, which the request does not ask for.`,
61
+ });
62
+ }
63
+ return routes.touched;
64
+ });
65
+ }
66
+ /**
67
+ * A per-entity request's entities: the entity, and every entity along each relative name it
68
+ * groups, filters, buckets or orders by, following the manifest's `rel.one` relationships. As on
69
+ * SegmentStream's per-entity route, a path may follow a self-relationship (`manager.name`).
70
+ */
71
+ function entityTouched(manifest, entity, body) {
72
+ return Effect.gen(function* () {
73
+ const request = yield* decode(EntityMetricQuery, body);
74
+ const entities = new Map(manifest.entities.map((candidate) => [candidate.name, candidate]));
75
+ const touched = new Set([entity]);
76
+ const names = [
77
+ ...request.dimensions,
78
+ ...(request.filters ?? []).map((filter) => filter.dimension),
79
+ ...(request.granularityOf === undefined ? [] : [request.granularityOf]),
80
+ ...(request.orderBy ?? []).flatMap((order) => order.dimension === undefined ? [] : [order.dimension]),
81
+ ];
82
+ for (const name of names) {
83
+ const segments = name.split(".");
84
+ let current = entities.get(entity);
85
+ if (segments.some((segment) => segment === "")) {
86
+ return yield* new InvalidMetricQuery({ reason: `${name} is not a valid name.` });
87
+ }
88
+ for (const relationshipName of segments.slice(0, -1)) {
89
+ const relationship = current?.relationships.find((candidate) => candidate.name === relationshipName);
90
+ if (current === undefined || relationship === undefined) {
91
+ return yield* new InvalidMetricQuery({
92
+ reason: `${current?.name ?? entity} has no relationship ${relationshipName}.`,
93
+ });
94
+ }
95
+ if (relationship.cardinality !== "one") {
96
+ return yield* new InvalidMetricQuery({
97
+ reason: `${relationshipName} is not a to-one relationship of ${current.name}.`,
98
+ });
99
+ }
100
+ current = entities.get(relationship.to);
101
+ touched.add(relationship.to);
102
+ }
103
+ }
104
+ return [...touched].sort();
105
+ });
106
+ }
107
+ /**
108
+ * SegmentStream's answer to a scoped metric query: passed on when it confirms every scope; a refusal of
109
+ * a scope it cannot apply, or an answer that does not confirm the scopes, fails as the caller's
110
+ * {@link ScopedMetricQueryUnavailable}.
111
+ */
112
+ function scopedAnswer(answer, scopes, requestId) {
113
+ const [first] = Object.keys(scopes).sort();
114
+ const { body } = answer;
115
+ if (body.error === "scoped_aggregate_unavailable") {
116
+ // SegmentStream's explanation is for operators; the caller gets the reason's code.
117
+ return Effect.logWarning("ontology.metric_query.row_scopes_unplannable").pipe(Effect.annotateLogs({
118
+ requestId,
119
+ diagnostic: typeof body.detail === "string" ? body.detail : "No detail.",
120
+ scoped: Object.keys(scopes).sort().join(","),
121
+ }), Effect.andThen(Effect.fail(new ScopedMetricQueryUnavailable({
122
+ entity: typeof body.entity === "string" ? body.entity : first,
123
+ reason: "unplannable",
124
+ }))));
125
+ }
126
+ if (answer.status < 200 || answer.status >= 300 || confirmsRowScopes(body, scopes)) {
127
+ return Effect.succeed(answer);
128
+ }
129
+ return Effect.logError("ontology.metric_query.row_scopes_unconfirmed").pipe(Effect.annotateLogs({
130
+ requestId,
131
+ diagnostic: "SegmentStream answered a scoped metric query without confirming its row scopes.",
132
+ scoped: Object.keys(scopes).sort().join(","),
133
+ }), Effect.andThen(Effect.fail(new ScopedMetricQueryUnavailable({
134
+ entity: first,
135
+ reason: "unconfirmed",
136
+ }))));
137
+ }
138
+ /**
139
+ * The ontology service's metric query facade (docs/ontology-aggregates-spec.md, "Surfaces"). Both
140
+ * routes and the MCP tool run as the caller:
141
+ * 0. the call counts against the caller's {@link METRIC_QUERY_LIMIT}, whichever way it came;
142
+ * 1. the request's shape and bounds are checked, and its names resolved against the service's own
143
+ * manifest into every entity it reads;
144
+ * 2. the caller needs `<entity>:read` on all of them; a read scope on any of them travels along,
145
+ * `me` resolved, and SegmentStream keeps only the scope's rows wherever it reads that entity. A
146
+ * scope with a path from `me` is refused with `ScopedMetricQueryUnavailable`;
147
+ * 3. the body goes to SegmentStream as it came, earlier names renamed (`withCurrentMetricQueryNames`),
148
+ * with the workspace app credential, naming the entities checked, or the answer is
149
+ * `aggregate_unavailable` where the deployment has no credential;
150
+ * 4. an answer to a scoped request must confirm every scope it was sent in `execution.rowScopes`,
151
+ * and a scope SegmentStream cannot apply is refused with `ScopedMetricQueryUnavailable`: a platform
152
+ * that ignored the scopes never answers a scoped caller.
153
+ */
154
+ export function makeMetricQueries(input) {
155
+ const { ontology, transport } = input;
156
+ const { manifest } = ontology;
157
+ const limiter = input.limiter ?? fixedWindowLimiter(METRIC_QUERY_LIMIT);
158
+ const run = (request) => Effect.gen(function* () {
159
+ const principal = yield* CurrentPrincipal;
160
+ const requestId = yield* RequestId;
161
+ const retryAfterSeconds = limiter.take(principal.id);
162
+ if (retryAfterSeconds !== undefined) {
163
+ return yield* new MetricQueryLimited({ retryAfterSeconds });
164
+ }
165
+ const touched = yield* request.touchedBy(request.body);
166
+ const missing = touched
167
+ .map((entity) => permissionOf(entity, READ_VERB))
168
+ .filter((permission) => !isAllowed(permission, principal));
169
+ if (missing.length > 0) {
170
+ return yield* new ReadDenied({ permissions: missing });
171
+ }
172
+ // Counting rows a list hides would leak them: each read scope travels to the warehouse.
173
+ const rowScopes = rowScopesOf(touched, principal, ontologyModel(ontology));
174
+ if (!rowScopes.ok) {
175
+ return yield* new ScopedMetricQueryUnavailable({
176
+ entity: rowScopes.entity,
177
+ reason: rowScopes.reason,
178
+ });
179
+ }
180
+ if (transport === undefined) {
181
+ return yield* new MetricQueriesUnavailable();
182
+ }
183
+ const encoded = encodeRowScopes(rowScopes.scopes);
184
+ const answer = yield* transport({
185
+ ...(request.entity === undefined ? {} : { entity: request.entity }),
186
+ body: withCurrentMetricQueryNames(request.body),
187
+ requestId,
188
+ touched,
189
+ ...(encoded === undefined ? {} : { rowScopes: encoded }),
190
+ });
191
+ if (encoded === undefined) {
192
+ return answer;
193
+ }
194
+ return yield* scopedAnswer(answer, rowScopes.scopes, requestId);
195
+ });
196
+ return {
197
+ model: (body) => run({ body, touchedBy: (value) => modelTouched(manifest, value) }),
198
+ entity: (entity) => (body) => run({ entity, body, touchedBy: (value) => entityTouched(manifest, entity, value) }),
199
+ };
200
+ }
@@ -0,0 +1,3 @@
1
+ /** Candidates must already be filtered for this authenticated caller's visibility. */
2
+ export declare function suggestNames(name: string, candidates: ReadonlyArray<string>): Array<string>;
3
+ export declare function suggestionDetail(detail: string, suggestions: ReadonlyArray<string>): string;