@segmentstream/ontology 0.0.0-stage → 0.92.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 (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,38 @@
1
+ import { Effect } from "effect";
2
+ import type { Ontology } from "../ontology.js";
3
+ import { PermissionDenied } from "../errors.js";
4
+ import { type PrincipalRolesSql } from "../runtime/principals.js";
5
+ /** Re-read user and roles in the same transaction that authorizes a storage operation. */
6
+ export declare function authorizeBlobOperation(ontology: Ontology, sql: PrincipalRolesSql, principalId: string, required: ReadonlyArray<string>, execution?: import("../runtime/workload.js").WorkloadExecution,
7
+ /** The workflow a workflow user's principal acts for, with its subject in this workspace. */
8
+ workflowPrincipal?: {
9
+ readonly name: string;
10
+ readonly subject: string;
11
+ }): Effect.Effect<{
12
+ scopes?: ReadonlyArray<import("../permissions.js").ScopedPermission>;
13
+ id: string;
14
+ permissions: readonly string[];
15
+ } | {
16
+ execution: {
17
+ readonly issuer: string;
18
+ readonly audience: string;
19
+ readonly organizationId: string;
20
+ readonly workspaceId: string;
21
+ readonly subject: string;
22
+ readonly deploymentId: string;
23
+ readonly ontologyDeploymentId: string;
24
+ readonly servingOntologyDeploymentId: string;
25
+ readonly ontologyOrigin: string;
26
+ readonly environment: "production" | "preview";
27
+ readonly jobName: string | null;
28
+ readonly runId: string;
29
+ readonly executionId: string | null;
30
+ readonly attemptId: string;
31
+ readonly generation: number;
32
+ readonly tokenId: string;
33
+ readonly issuedAt: number;
34
+ readonly expiresAt: number;
35
+ };
36
+ id: string;
37
+ permissions: readonly string[];
38
+ }, PermissionDenied | import("effect/unstable/sql/SqlError").SqlError, never>;
@@ -0,0 +1,83 @@
1
+ import { Effect } from "effect";
2
+ import { missingPermission, permissionsOf, principalScopes } from "../permissions.js";
3
+ import { PermissionDenied } from "../errors.js";
4
+ import { MEMBER_ROLE, FEEDBACK_REPORTER_ROLE, toSnakeCase } from "../names.js";
5
+ import { rolesOf } from "../runtime/principals.js";
6
+ import { PIPELINE_WORKER_PROVIDER } from "../runtime/workload.js";
7
+ import { WORKFLOW_USER_PROVIDER, workflowOfSubject } from "../runtime/workflow-users.js";
8
+ /** Re-read user and roles in the same transaction that authorizes a storage operation. */
9
+ export function authorizeBlobOperation(ontology, sql, principalId, required, execution,
10
+ /** The workflow a workflow user's principal acts for, with its subject in this workspace. */
11
+ workflowPrincipal) {
12
+ return Effect.gen(function* () {
13
+ const [catalog] = yield* sql.unsafe(`SELECT hash FROM "_ontology" WHERE id = true FOR SHARE`, []);
14
+ if (catalog?.hash !== ontology.manifest.hash) {
15
+ yield* Effect.logWarning("ontology.storage.catalog_mismatch", {
16
+ servedHash: ontology.manifest.hash,
17
+ appliedHash: catalog?.hash ?? null,
18
+ });
19
+ return yield* new PermissionDenied({
20
+ message: "The deployed ontology no longer matches the database catalog.",
21
+ updating: true,
22
+ });
23
+ }
24
+ const users = yield* sql.unsafe(`SELECT kind::text, active, identity_provider, identity_subject FROM "user" WHERE id = $1::uuid FOR SHARE`, [principalId]);
25
+ const user = users[0];
26
+ const roles = yield* sql.unsafe(`SELECT role FROM "_user_roles" WHERE user_id = $1::uuid FOR SHARE`, [principalId]);
27
+ const held = roles
28
+ .map((row) => String(row.role))
29
+ .filter((name) => toSnakeCase(name) !== FEEDBACK_REPORTER_ROLE);
30
+ // Reuse human principal resolution rather than reconstructing implicit authority here. The
31
+ // result rechecks required permissions and is the reader for scoped file reads; the caller's
32
+ // consent-narrowed principal still governs the rest of the operation.
33
+ const member = user?.kind === "member"
34
+ ? yield* rolesOf(ontology, sql, {
35
+ id: principalId,
36
+ kind: "member",
37
+ active: user.active === true,
38
+ })
39
+ : undefined;
40
+ const worker = execution !== undefined &&
41
+ user?.kind === "service" &&
42
+ user.identity_provider === PIPELINE_WORKER_PROVIDER &&
43
+ user.identity_subject === `pipeline-workers:${execution.workspaceId}`;
44
+ // A workflow's runs hold what member and the declared workflow's role grant. The database
45
+ // must assign exactly that role: an extra or stale assignment widens nothing and is refused.
46
+ const workflowUser = user?.kind === "service" && user.identity_provider === WORKFLOW_USER_PROVIDER;
47
+ // The user's subject must be exactly the principal's, workspace id included.
48
+ const workflow = workflowUser &&
49
+ workflowPrincipal !== undefined &&
50
+ user.identity_subject === workflowPrincipal.subject &&
51
+ workflowOfSubject(user.identity_subject) === workflowPrincipal.name
52
+ ? ontology.workflows.find((candidate) => candidate.name === workflowPrincipal.name)
53
+ : undefined;
54
+ const declaredWorkflow = workflow !== undefined &&
55
+ execution === undefined &&
56
+ held.length === 1 &&
57
+ held[0] === workflow.role;
58
+ const liveHeld = workflowUser && workflow ? [MEMBER_ROLE, workflow.role] : (member?.roles ?? held);
59
+ const permissions = worker
60
+ ? ["*:*"]
61
+ : workflowUser && !declaredWorkflow
62
+ ? []
63
+ : permissionsOf(ontology.roles, liveHeld);
64
+ const missing = missingPermission(required, {
65
+ ...(worker ? { execution } : {}),
66
+ permissions,
67
+ });
68
+ if (!user?.active ||
69
+ missing ||
70
+ (execution !== undefined && !worker) ||
71
+ (workflowUser && !declaredWorkflow)) {
72
+ return yield* new PermissionDenied({
73
+ message: "The member cannot use this file operation.",
74
+ ...(missing ? { permission: missing } : {}),
75
+ });
76
+ }
77
+ return {
78
+ id: principalId,
79
+ permissions,
80
+ ...(worker ? { execution } : principalScopes(ontology.roles, liveHeld)),
81
+ };
82
+ });
83
+ }
@@ -0,0 +1,17 @@
1
+ import { Context } from "effect";
2
+ import type { Files } from "../files.js";
3
+ import type { Principal } from "../runtime.js";
4
+ /** Private factory; authoring code receives only the bound Files capability. */
5
+ export interface FileInvocation {
6
+ readonly principal: Principal;
7
+ readonly action?: string;
8
+ readonly idempotencyKey?: string;
9
+ readonly createIntent?: string;
10
+ }
11
+ declare const FileAccess_base: Context.ServiceClass<FileAccess, "@segmentstream/ontology/FileAccess", {
12
+ readonly forInvocation: (input: FileInvocation) => Files["Service"];
13
+ }>;
14
+ export declare class FileAccess extends FileAccess_base {
15
+ }
16
+ export declare const unavailableFiles: Files["Service"];
17
+ export {};
@@ -0,0 +1,8 @@
1
+ import { Context, Effect } from "effect";
2
+ import { ActionRejected } from "../errors.js";
3
+ export class FileAccess extends Context.Service()("@segmentstream/ontology/FileAccess") {
4
+ }
5
+ export const unavailableFiles = {
6
+ stage: () => Effect.fail(new ActionRejected({ message: "file_storage_unavailable" })),
7
+ open: () => Effect.fail(new ActionRejected({ message: "file_storage_unavailable" })),
8
+ };
@@ -0,0 +1,12 @@
1
+ import { ActionRejected } from "../errors.js";
2
+ /** Upload sessions one principal may hold open at once. */
3
+ export declare const MAX_PENDING_UPLOADS = 8;
4
+ /**
5
+ * Refuses a file that would take the workspace past its storage quota. `usedBytes` counts every
6
+ * file revision not yet deleted, including retained history, reserved uploads and attachments.
7
+ */
8
+ export declare function storageQuotaRejection(input: {
9
+ readonly usedBytes: number;
10
+ readonly requestedBytes: number;
11
+ readonly quotaBytes: number;
12
+ }): ActionRejected | undefined;
@@ -0,0 +1,17 @@
1
+ import { ActionRejected } from "../errors.js";
2
+ /** Upload sessions one principal may hold open at once. */
3
+ export const MAX_PENDING_UPLOADS = 8;
4
+ /**
5
+ * Refuses a file that would take the workspace past its storage quota. `usedBytes` counts every
6
+ * file revision not yet deleted, including retained history, reserved uploads and attachments.
7
+ */
8
+ export function storageQuotaRejection(input) {
9
+ if (input.usedBytes + input.requestedBytes <= input.quotaBytes) {
10
+ return undefined;
11
+ }
12
+ return new ActionRejected({
13
+ message: `File storage quota reached: ${input.usedBytes} of ${input.quotaBytes} bytes are used ` +
14
+ `and this file needs ${input.requestedBytes}.`,
15
+ limit: { kind: "storage_quota", ...input },
16
+ });
17
+ }
@@ -0,0 +1,20 @@
1
+ import { Layer, Redacted } from "effect";
2
+ import { HttpApiMiddleware, HttpApiSecurity } from "effect/unstable/httpapi";
3
+ import { RequestId } from "../service/errors.js";
4
+ declare const StorageMaintenanceAuthentication_base: HttpApiMiddleware.ServiceClass<StorageMaintenanceAuthentication, "@segmentstream/ontology/StorageMaintenanceAuthentication", {
5
+ requires: RequestId;
6
+ provides: never;
7
+ error: readonly [import("effect/Schema").Top];
8
+ clientError: never;
9
+ requiredForClient: false;
10
+ security: {
11
+ readonly maintenanceBearer: HttpApiSecurity.Http;
12
+ };
13
+ }, HttpApiMiddleware.HttpApiMiddlewareSecurity<{
14
+ readonly maintenanceBearer: HttpApiSecurity.Http;
15
+ }, never, readonly [import("effect/Schema").Top], RequestId>>;
16
+ /** Deployment scheduler identity: this credential grants only orphan maintenance. */
17
+ export declare class StorageMaintenanceAuthentication extends StorageMaintenanceAuthentication_base {
18
+ }
19
+ export declare function storageMaintenanceAuthenticationLayer(key?: Redacted.Redacted<string>): Layer.Layer<StorageMaintenanceAuthentication, never, never>;
20
+ export {};
@@ -0,0 +1,24 @@
1
+ import { createHash, timingSafeEqual } from "node:crypto";
2
+ import { Effect, Layer, Redacted } from "effect";
3
+ import { HttpApiMiddleware, HttpApiSecurity } from "effect/unstable/httpapi";
4
+ import { RequestId, toServerResponse, unauthorized } from "../service/errors.js";
5
+ import { ErrorSchemas } from "../service/schemas.js";
6
+ /** Deployment scheduler identity: this credential grants only orphan maintenance. */
7
+ export class StorageMaintenanceAuthentication extends HttpApiMiddleware.Service()("@segmentstream/ontology/StorageMaintenanceAuthentication", {
8
+ security: { maintenanceBearer: HttpApiSecurity.bearer },
9
+ error: [ErrorSchemas.unauthorized],
10
+ }) {
11
+ }
12
+ export function storageMaintenanceAuthenticationLayer(key) {
13
+ return Layer.succeed(StorageMaintenanceAuthentication)({
14
+ maintenanceBearer: (httpEffect, { credential }) => Effect.gen(function* () {
15
+ const requestId = yield* RequestId;
16
+ const digest = (value) => createHash("sha256").update(value).digest();
17
+ if (!key ||
18
+ !timingSafeEqual(digest(Redacted.value(credential)), digest(Redacted.value(key)))) {
19
+ return toServerResponse(unauthorized(requestId, "A deployment maintenance credential is required."));
20
+ }
21
+ return yield* httpEffect;
22
+ }),
23
+ });
24
+ }
@@ -0,0 +1,11 @@
1
+ import { Effect } from "effect";
2
+ import type { SqlClient } from "effect/unstable/sql";
3
+ import type { BlobProvider } from "./provider.js";
4
+ /**
5
+ * A scheduler-owned capability: lifecycle operations only, with persisted deletion fencing. The
6
+ * agent's attachments expire first, so that their files are removed in the same run.
7
+ */
8
+ export declare function maintainBlobStorage(sql: SqlClient.SqlClient, provider: BlobProvider["Service"], limit?: number): Effect.Effect<{
9
+ removed: number;
10
+ hasMore: boolean;
11
+ }, import("effect/unstable/sql/SqlError").SqlError | import("./provider.js").BlobStorageError, never>;
@@ -0,0 +1,67 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { Effect } from "effect";
3
+ import { maintainAttachments } from "./attachments.js";
4
+ /**
5
+ * A scheduler-owned capability: lifecycle operations only, with persisted deletion fencing. The
6
+ * agent's attachments expire first, so that their files are removed in the same run.
7
+ */
8
+ export function maintainBlobStorage(sql, provider, limit = 100) {
9
+ return Effect.gen(function* () {
10
+ const attachments = yield* maintainAttachments(sql, provider, limit);
11
+ let removed = attachments.removed;
12
+ let attempted = 0;
13
+ for (let count = 0; count < limit; count += 1) {
14
+ const claim = randomUUID();
15
+ const candidate = yield* sql.withTransaction(Effect.gen(function* () {
16
+ const [row] = yield* sql.unsafe(`SELECT u.id::text, u.blob_id::text, b.key, u.provider_upload_id
17
+ FROM "_blob_uploads" u JOIN "_blobs" b ON b.id = u.blob_id
18
+ WHERE u.state NOT IN ('consumed', 'deleted') AND b.state IN ('ready', 'deleting')
19
+ AND (u.branch_id <> $1 OR u.expires_at <= now() OR u.state IN ('canceled', 'deleting'))
20
+ AND (u.claim IS NULL OR u.claimed_at < now() - interval '5 minutes')
21
+ AND NOT EXISTS (SELECT 1 FROM "_blob_references" r WHERE r.blob_id = b.id)
22
+ ORDER BY u.created_at LIMIT 1 FOR UPDATE OF u, b SKIP LOCKED`, [provider.binding.branchId]);
23
+ if (!row) {
24
+ return undefined;
25
+ }
26
+ yield* sql.unsafe(`UPDATE "_blob_uploads" SET state = 'deleting', claim = $1::uuid,
27
+ claimed_at = now() WHERE id = $2::uuid`, [claim, row.id]);
28
+ yield* sql.unsafe(`UPDATE "_blobs" SET state = 'deleting' WHERE id = $1::uuid`, [
29
+ row.blob_id,
30
+ ]);
31
+ return row;
32
+ }));
33
+ if (!candidate) {
34
+ break;
35
+ }
36
+ attempted += 1;
37
+ const handles = new Set([
38
+ ...(candidate.provider_upload_id ? [candidate.provider_upload_id] : []),
39
+ ...(yield* provider.pending(candidate.key)),
40
+ ]);
41
+ for (const uploadId of handles) {
42
+ yield* provider.abort({ key: candidate.key, uploadId });
43
+ }
44
+ yield* provider.remove(candidate.key);
45
+ yield* sql.withTransaction(Effect.gen(function* () {
46
+ const done = yield* sql.unsafe(`UPDATE "_blob_uploads" SET state = 'deleted', claim = NULL,
47
+ claimed_at = NULL WHERE id = $1::uuid AND state = 'deleting' AND claim = $2::uuid
48
+ RETURNING blob_id`, [candidate.id, claim]);
49
+ if (done.length) {
50
+ yield* sql.unsafe(`UPDATE "_blobs" SET state = 'deleted' WHERE id = $1::uuid AND state = 'deleting'`, [candidate.blob_id]);
51
+ removed += 1;
52
+ }
53
+ }));
54
+ }
55
+ // Claims and row locks defer work; they do not make the backlog empty.
56
+ const [backlog] = yield* sql.unsafe(`SELECT EXISTS (
57
+ SELECT 1 FROM "_blob_uploads" u JOIN "_blobs" b ON b.id = u.blob_id
58
+ WHERE u.state NOT IN ('consumed', 'deleted') AND b.state IN ('ready', 'deleting')
59
+ AND (u.branch_id <> $1 OR u.expires_at <= now() OR u.state IN ('canceled', 'deleting'))
60
+ AND NOT EXISTS (SELECT 1 FROM "_blob_references" r WHERE r.blob_id = b.id)
61
+ ) AS remaining`, [provider.binding.branchId]);
62
+ return {
63
+ removed,
64
+ hasMore: attachments.hasMore || attempted >= limit || backlog.remaining,
65
+ };
66
+ });
67
+ }
@@ -0,0 +1,4 @@
1
+ import { type DeploymentObservation } from "../deployment.js";
2
+ import { BlobProvider, type BlobStorageBinding } from "./provider.js";
3
+ /** A branch-bound S3 adapter; never uses the ambient AWS credential chain. */
4
+ export declare function neonBlobProvider(binding: BlobStorageBinding, deployment?: DeploymentObservation): BlobProvider["Service"];
@@ -0,0 +1,318 @@
1
+ import { createHash } from "node:crypto";
2
+ import { AbortMultipartUploadCommand, CompleteMultipartUploadCommand, CreateMultipartUploadCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, ListMultipartUploadsCommand, ListPartsCommand, S3Client, UploadPartCommand, } from "@aws-sdk/client-s3";
3
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
4
+ import { Effect } from "effect";
5
+ import { DeploymentAdmissionError, requireDeploymentCapability, } from "../deployment.js";
6
+ import { BlobStorageError, validateDeploymentStorage, } from "./provider.js";
7
+ function missing(error) {
8
+ return error instanceof Error && ["NotFound", "NoSuchKey", "NoSuchUpload"].includes(error.name);
9
+ }
10
+ function redactStorageFailure(cause, binding) {
11
+ const seen = new WeakSet();
12
+ const redact = (value) => {
13
+ if (typeof value === "string") {
14
+ return [binding.accessKeyId, binding.secretAccessKey]
15
+ .reduce((text, secret) => secret
16
+ ? text
17
+ .replaceAll(secret, "[redacted]")
18
+ .replaceAll(encodeURIComponent(secret), "[redacted]")
19
+ : text, value)
20
+ .replace(/https?:\/\/[^\s"'<>]*[?&]X-Amz-(?:Signature|Credential)=[^\s"'<>]*/gi, "[redacted storage grant]")
21
+ .replace(/(X-Amz-Signature=)[^&\s]+/gi, "$1[redacted]");
22
+ }
23
+ if (value === null || typeof value !== "object") {
24
+ return value;
25
+ }
26
+ if (seen.has(value)) {
27
+ return "[Circular]";
28
+ }
29
+ seen.add(value);
30
+ if (Array.isArray(value)) {
31
+ return value.map(redact);
32
+ }
33
+ const entries = value instanceof Error
34
+ ? Object.fromEntries([
35
+ ["name", value.name],
36
+ ["message", value.message],
37
+ ["stack", value.stack],
38
+ ["cause", value.cause],
39
+ ...(value instanceof AggregateError ? [["errors", value.errors]] : []),
40
+ ...Object.entries(value),
41
+ ])
42
+ : value;
43
+ return Object.fromEntries(Object.entries(entries).map(([key, child]) => [key, redact(child)]));
44
+ };
45
+ return redact(cause);
46
+ }
47
+ /** A branch-bound S3 adapter; never uses the ambient AWS credential chain. */
48
+ export function neonBlobProvider(binding, deployment) {
49
+ validateDeploymentStorage(binding, deployment);
50
+ const endpoint = new URL(binding.endpoint);
51
+ if (endpoint.protocol !== "https:" ||
52
+ endpoint.username ||
53
+ endpoint.password ||
54
+ !endpoint.hostname.startsWith(`${binding.branchId}.storage.`) ||
55
+ !endpoint.hostname.endsWith(".aws.neon.tech") ||
56
+ endpoint.pathname !== "/" ||
57
+ endpoint.search ||
58
+ endpoint.hash ||
59
+ endpoint.port) {
60
+ throw new Error("The ontology storage endpoint does not match its verified branch.");
61
+ }
62
+ const client = new S3Client({
63
+ endpoint: binding.endpoint,
64
+ region: binding.region,
65
+ credentials: { accessKeyId: binding.accessKeyId, secretAccessKey: binding.secretAccessKey },
66
+ forcePathStyle: true,
67
+ requestChecksumCalculation: "WHEN_REQUIRED",
68
+ maxAttempts: 1,
69
+ requestHandler: { requestTimeout: 30000 },
70
+ });
71
+ let storageClockOffset;
72
+ // The SDK's normal skew correction tolerates four minutes, longer than a download grant.
73
+ // Calibrate every grant from an authenticated response instead of extending its lifetime.
74
+ client.middlewareStack.add((next) => async (args) => {
75
+ const result = await next(args);
76
+ const response = result.response;
77
+ const serverTime = Date.parse(response.headers?.date ?? "");
78
+ if (Number.isFinite(serverTime)) {
79
+ storageClockOffset = serverTime - Date.now();
80
+ }
81
+ return result;
82
+ }, { step: "deserialize", name: "ontologyStorageClock" });
83
+ const signingDate = () => {
84
+ if (storageClockOffset === undefined) {
85
+ throw new Error("Neon did not return a valid server time for the transfer grant.");
86
+ }
87
+ return new Date(Date.now() + storageClockOffset);
88
+ };
89
+ const object = (key) => ({ Bucket: binding.bucket, Key: key });
90
+ // SigV4 collapses sequential header spaces. Send that same value on the wire: Neon's
91
+ // multipart verifier rejects a quoted filename containing unnormalized double spaces.
92
+ // Only normalize the fallback; filename* preserves the original name and whitespace.
93
+ const disposition = (filename, inline = false) => {
94
+ const fallback = filename.replace(/[^a-zA-Z0-9_. -]/g, "_").replace(/ +/g, " ");
95
+ // encodeURIComponent leaves these characters unescaped, but RFC 5987 disallows them.
96
+ const encoded = encodeURIComponent(filename).replace(/['()*]/g, (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`);
97
+ return `${inline ? "inline" : "attachment"}; filename="${fallback}"; filename*=UTF-8''${encoded}`;
98
+ };
99
+ const attempt = (operation, run) => Effect.suspend(() => {
100
+ if (deployment) {
101
+ requireDeploymentCapability(deployment);
102
+ }
103
+ return Effect.tryPromise({
104
+ try: run,
105
+ catch: (cause) => {
106
+ if (cause instanceof DeploymentAdmissionError) {
107
+ throw cause;
108
+ }
109
+ const status = cause?.$metadata
110
+ ?.httpStatusCode;
111
+ return new BlobStorageError({
112
+ operation,
113
+ cause: redactStorageFailure(cause, binding),
114
+ ...(operation === "blob.initiate" &&
115
+ status !== undefined &&
116
+ status >= 400 &&
117
+ status < 500 &&
118
+ status !== 408
119
+ ? { initiationRejected: true }
120
+ : {}),
121
+ });
122
+ },
123
+ });
124
+ });
125
+ const grantSeconds = (maximum, signedAt) => {
126
+ if (deployment?.target !== "preview") {
127
+ return maximum;
128
+ }
129
+ const remaining = Math.floor((Date.parse(deployment.expiresAt) - signedAt.getTime()) / 1000);
130
+ if (remaining <= 0) {
131
+ throw new DeploymentAdmissionError("preview_expired");
132
+ }
133
+ return Math.min(maximum, remaining);
134
+ };
135
+ const grant = (url, method, seconds, signedAt) => ({
136
+ url,
137
+ method,
138
+ headers: {},
139
+ expiresAt: new Date(signedAt.getTime() + seconds * 1000).toISOString(),
140
+ });
141
+ return {
142
+ binding,
143
+ close: () => client.destroy(),
144
+ initiate: ({ key, filename, contentType, sessionId }) => attempt("blob.initiate", async () => {
145
+ const response = await client.send(new CreateMultipartUploadCommand({
146
+ ...object(key),
147
+ ContentType: contentType,
148
+ ContentDisposition: disposition(filename),
149
+ CacheControl: "private, no-store",
150
+ Metadata: { session: sessionId },
151
+ }));
152
+ if (!response.UploadId) {
153
+ throw new Error("Neon did not return a multipart upload ID.");
154
+ }
155
+ return response.UploadId;
156
+ }),
157
+ signPart: ({ key, uploadId, partNumber, size }) => attempt("blob.sign_part", async () => {
158
+ await client.send(new ListPartsCommand({ ...object(key), UploadId: uploadId }));
159
+ const signedAt = signingDate();
160
+ const seconds = grantSeconds(300, signedAt);
161
+ const url = await getSignedUrl(client, new UploadPartCommand({
162
+ ...object(key),
163
+ UploadId: uploadId,
164
+ PartNumber: partNumber,
165
+ ContentLength: size,
166
+ }), {
167
+ expiresIn: seconds,
168
+ signingDate: signedAt,
169
+ signableHeaders: new Set(["content-length"]),
170
+ });
171
+ return grant(url, "PUT", seconds, signedAt);
172
+ }),
173
+ parts: ({ key, uploadId }) => attempt("blob.parts", async () => {
174
+ const response = await client.send(new ListPartsCommand({ ...object(key), UploadId: uploadId }));
175
+ if (response.IsTruncated) {
176
+ throw new Error("Unexpected truncated multipart session.");
177
+ }
178
+ return (response.Parts ?? []).map((part) => {
179
+ if (!part.PartNumber || part.Size === undefined || !part.ETag) {
180
+ throw new Error("Neon returned incomplete part metadata.");
181
+ }
182
+ return { number: part.PartNumber, size: part.Size, etag: part.ETag };
183
+ });
184
+ }),
185
+ complete: ({ key, uploadId, parts }) => attempt("blob.complete", async () => {
186
+ await client.send(new CompleteMultipartUploadCommand({
187
+ ...object(key),
188
+ UploadId: uploadId,
189
+ MultipartUpload: {
190
+ Parts: parts.map((part) => ({ PartNumber: part.number, ETag: part.etag })),
191
+ },
192
+ }));
193
+ }),
194
+ inspect: (key) => attempt("blob.inspect", async () => {
195
+ try {
196
+ const response = await client.send(new HeadObjectCommand(object(key)));
197
+ if (response.ContentLength === undefined ||
198
+ !response.ContentType ||
199
+ !response.Metadata?.session) {
200
+ throw new Error("Neon returned incomplete object metadata.");
201
+ }
202
+ return {
203
+ size: response.ContentLength,
204
+ contentType: response.ContentType,
205
+ sessionId: response.Metadata.session,
206
+ };
207
+ }
208
+ catch (error) {
209
+ if (missing(error)) {
210
+ return undefined;
211
+ }
212
+ throw error;
213
+ }
214
+ }),
215
+ sha256: (key, size) => attempt("blob.sha256", async () => {
216
+ const response = await client.send(new GetObjectCommand(object(key)));
217
+ if (!response.Body) {
218
+ throw new Error("Neon returned no object body.");
219
+ }
220
+ const hash = createHash("sha256");
221
+ const reader = response.Body.transformToWebStream().getReader();
222
+ let received = 0;
223
+ let failure;
224
+ try {
225
+ for (;;) {
226
+ const { done, value } = await reader.read();
227
+ if (done) {
228
+ break;
229
+ }
230
+ received += value.byteLength;
231
+ if (received > size) {
232
+ throw new Error("The stored object exceeds its declared size.");
233
+ }
234
+ hash.update(value);
235
+ }
236
+ if (received !== size) {
237
+ throw new Error("The stored object does not match its declared size.");
238
+ }
239
+ return hash.digest("hex");
240
+ }
241
+ catch (cause) {
242
+ failure = cause;
243
+ throw cause;
244
+ }
245
+ finally {
246
+ try {
247
+ await reader.cancel();
248
+ }
249
+ catch (cleanup) {
250
+ if (failure !== undefined) {
251
+ throw new AggregateError([failure, cleanup], "Hashing and stream cleanup failed.", {
252
+ cause: cleanup,
253
+ });
254
+ }
255
+ throw cleanup;
256
+ }
257
+ finally {
258
+ reader.releaseLock();
259
+ }
260
+ }
261
+ }),
262
+ readPrefix: (key) => attempt("blob.read_prefix", async () => {
263
+ const response = await client.send(new GetObjectCommand({ ...object(key), Range: "bytes=0-511" }));
264
+ if (!response.Body) {
265
+ throw new Error("Neon returned no object body.");
266
+ }
267
+ return response.Body.transformToByteArray();
268
+ }),
269
+ read: (key, maxBytes) => attempt("blob.read", async () => {
270
+ const response = await client.send(new GetObjectCommand(object(key)));
271
+ if (!response.Body) {
272
+ throw new Error("Neon returned no object body.");
273
+ }
274
+ if (response.ContentLength !== undefined && response.ContentLength > maxBytes) {
275
+ throw new Error("The stored object exceeds the size it may have.");
276
+ }
277
+ const bytes = await response.Body.transformToByteArray();
278
+ if (bytes.byteLength > maxBytes) {
279
+ throw new Error("The stored object exceeds the size it may have.");
280
+ }
281
+ return bytes;
282
+ }),
283
+ download: ({ key, filename, contentType, inline }) => attempt("blob.download", async () => {
284
+ await client.send(new HeadObjectCommand(object(key)));
285
+ const signedAt = signingDate();
286
+ const seconds = grantSeconds(60, signedAt);
287
+ const url = await getSignedUrl(client, new GetObjectCommand({
288
+ ...object(key),
289
+ ResponseContentType: contentType,
290
+ ResponseContentDisposition: disposition(filename, inline),
291
+ ResponseCacheControl: "private, no-store",
292
+ }), { expiresIn: seconds, signingDate: signedAt });
293
+ return grant(url, "GET", seconds, signedAt);
294
+ }),
295
+ abort: ({ key, uploadId }) => attempt("blob.abort", async () => {
296
+ try {
297
+ await client.send(new AbortMultipartUploadCommand({ ...object(key), UploadId: uploadId }));
298
+ }
299
+ catch (error) {
300
+ if (!missing(error)) {
301
+ throw error;
302
+ }
303
+ }
304
+ }),
305
+ remove: (key) => attempt("blob.remove", async () => {
306
+ await client.send(new DeleteObjectCommand(object(key)));
307
+ }),
308
+ pending: (key) => attempt("blob.pending", async () => {
309
+ const response = await client.send(new ListMultipartUploadsCommand({ Bucket: binding.bucket, Prefix: key }));
310
+ if (response.IsTruncated) {
311
+ throw new Error("Unexpected truncated initialization recovery.");
312
+ }
313
+ return (response.Uploads ?? [])
314
+ .filter((upload) => upload.Key === key && upload.UploadId)
315
+ .map((upload) => upload.UploadId);
316
+ }),
317
+ };
318
+ }
@@ -0,0 +1,11 @@
1
+ import { Effect, Redacted } from "effect";
2
+ import { BlobStorageError, type BlobStorageBinding } from "./provider.js";
3
+ /** Scheduler capability that survives removal of blob declarations. Never reads file contents. */
4
+ export declare function runBlobStorageMaintenance(input: {
5
+ readonly databaseUrl: Redacted.Redacted<string>;
6
+ readonly binding: Redacted.Redacted<BlobStorageBinding>;
7
+ readonly limit?: number;
8
+ }): Effect.Effect<{
9
+ removed: number;
10
+ hasMore: boolean;
11
+ }, import("effect/unstable/sql/SqlError").SqlError | BlobStorageError, never>;