@vertesia/common 1.6.0-dev.20260923.085325Z → 1.6.0-dev.20261008.064737Z

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 (421) hide show
  1. package/lib/access-control-values.d.ts +2 -2
  2. package/lib/access-control-values.d.ts.map +1 -1
  3. package/lib/access-control-values.js +2 -2
  4. package/lib/access-control-values.js.map +1 -1
  5. package/lib/access-control.d.ts +7 -8
  6. package/lib/access-control.d.ts.map +1 -1
  7. package/lib/access-control.js +5 -0
  8. package/lib/access-control.js.map +1 -1
  9. package/lib/analytics.d.ts +6 -7
  10. package/lib/analytics.d.ts.map +1 -1
  11. package/lib/api-contract/components.generated.json +2553 -1046
  12. package/lib/api-contract/engine.d.ts +65 -0
  13. package/lib/api-contract/engine.d.ts.map +1 -0
  14. package/lib/api-contract/engine.js +569 -0
  15. package/lib/api-contract/engine.js.map +1 -0
  16. package/lib/api-contract/index.d.ts +21 -182
  17. package/lib/api-contract/index.d.ts.map +1 -1
  18. package/lib/api-contract/index.js +13 -551
  19. package/lib/api-contract/index.js.map +1 -1
  20. package/lib/api-schemas/access-control.d.ts +33 -10
  21. package/lib/api-schemas/access-control.d.ts.map +1 -1
  22. package/lib/api-schemas/access-control.js +7 -6
  23. package/lib/api-schemas/access-control.js.map +1 -1
  24. package/lib/api-schemas/account.d.ts +5 -9
  25. package/lib/api-schemas/account.d.ts.map +1 -1
  26. package/lib/api-schemas/account.js +0 -7
  27. package/lib/api-schemas/account.js.map +1 -1
  28. package/lib/api-schemas/agent-budget.d.ts +15 -0
  29. package/lib/api-schemas/agent-budget.d.ts.map +1 -0
  30. package/lib/api-schemas/agent-budget.js +55 -0
  31. package/lib/api-schemas/agent-budget.js.map +1 -0
  32. package/lib/api-schemas/agent-runs.d.ts +1525 -100
  33. package/lib/api-schemas/agent-runs.d.ts.map +1 -1
  34. package/lib/api-schemas/agent-runs.js +60 -28
  35. package/lib/api-schemas/agent-runs.js.map +1 -1
  36. package/lib/api-schemas/apikey.d.ts +11 -10
  37. package/lib/api-schemas/apikey.d.ts.map +1 -1
  38. package/lib/api-schemas/apikey.js.map +1 -1
  39. package/lib/api-schemas/app-lifecycle.d.ts +13 -0
  40. package/lib/api-schemas/app-lifecycle.d.ts.map +1 -1
  41. package/lib/api-schemas/app-lifecycle.js +4 -0
  42. package/lib/api-schemas/app-lifecycle.js.map +1 -1
  43. package/lib/api-schemas/app-runtime.d.ts +1821 -108
  44. package/lib/api-schemas/app-runtime.d.ts.map +1 -1
  45. package/lib/api-schemas/audit-trail.d.ts +275 -0
  46. package/lib/api-schemas/audit-trail.d.ts.map +1 -1
  47. package/lib/api-schemas/audit-trail.js +156 -1
  48. package/lib/api-schemas/audit-trail.js.map +1 -1
  49. package/lib/api-schemas/content.d.ts +665 -30
  50. package/lib/api-schemas/content.d.ts.map +1 -1
  51. package/lib/api-schemas/content.js +47 -0
  52. package/lib/api-schemas/content.js.map +1 -1
  53. package/lib/api-schemas/cost-analytics.d.ts +19 -0
  54. package/lib/api-schemas/cost-analytics.d.ts.map +1 -1
  55. package/lib/api-schemas/cost-analytics.js +38 -2
  56. package/lib/api-schemas/cost-analytics.js.map +1 -1
  57. package/lib/api-schemas/document-processing.d.ts +381 -18
  58. package/lib/api-schemas/document-processing.d.ts.map +1 -1
  59. package/lib/api-schemas/environment.d.ts +0 -5
  60. package/lib/api-schemas/environment.d.ts.map +1 -1
  61. package/lib/api-schemas/environment.js +0 -1
  62. package/lib/api-schemas/environment.js.map +1 -1
  63. package/lib/api-schemas/events.d.ts +1143 -54
  64. package/lib/api-schemas/events.d.ts.map +1 -1
  65. package/lib/api-schemas/group.d.ts +2 -1
  66. package/lib/api-schemas/group.d.ts.map +1 -1
  67. package/lib/api-schemas/group.js.map +1 -1
  68. package/lib/api-schemas/index.d.ts +2 -0
  69. package/lib/api-schemas/index.d.ts.map +1 -1
  70. package/lib/api-schemas/index.js +2 -0
  71. package/lib/api-schemas/index.js.map +1 -1
  72. package/lib/api-schemas/inference-profile.d.ts +5017 -0
  73. package/lib/api-schemas/inference-profile.d.ts.map +1 -0
  74. package/lib/api-schemas/inference-profile.js +135 -0
  75. package/lib/api-schemas/inference-profile.js.map +1 -0
  76. package/lib/api-schemas/integrations.d.ts +6 -6
  77. package/lib/api-schemas/interaction.d.ts +34391 -703
  78. package/lib/api-schemas/interaction.d.ts.map +1 -1
  79. package/lib/api-schemas/interaction.js +34 -1
  80. package/lib/api-schemas/interaction.js.map +1 -1
  81. package/lib/api-schemas/invites.d.ts +10 -9
  82. package/lib/api-schemas/invites.d.ts.map +1 -1
  83. package/lib/api-schemas/invites.js.map +1 -1
  84. package/lib/api-schemas/process.d.ts +653 -34
  85. package/lib/api-schemas/process.d.ts.map +1 -1
  86. package/lib/api-schemas/process.js +66 -0
  87. package/lib/api-schemas/process.js.map +1 -1
  88. package/lib/api-schemas/project-configuration.d.ts +1323 -62
  89. package/lib/api-schemas/project-configuration.d.ts.map +1 -1
  90. package/lib/api-schemas/project-configuration.js +15 -1
  91. package/lib/api-schemas/project-configuration.js.map +1 -1
  92. package/lib/api-schemas/project.d.ts +2031 -116
  93. package/lib/api-schemas/project.d.ts.map +1 -1
  94. package/lib/api-schemas/project.js +9 -1
  95. package/lib/api-schemas/project.js.map +1 -1
  96. package/lib/api-schemas/quota.d.ts +7 -6
  97. package/lib/api-schemas/quota.d.ts.map +1 -1
  98. package/lib/api-schemas/quota.js.map +1 -1
  99. package/lib/api-schemas/registry.d.ts +28171 -36096
  100. package/lib/api-schemas/registry.d.ts.map +1 -1
  101. package/lib/api-schemas/registry.js +77 -30
  102. package/lib/api-schemas/registry.js.map +1 -1
  103. package/lib/api-schemas/run-budget.d.ts +16 -0
  104. package/lib/api-schemas/run-budget.d.ts.map +1 -0
  105. package/lib/api-schemas/run-budget.js +22 -0
  106. package/lib/api-schemas/run-budget.js.map +1 -0
  107. package/lib/api-schemas/secrets.d.ts +0 -71
  108. package/lib/api-schemas/secrets.d.ts.map +1 -1
  109. package/lib/api-schemas/secrets.js +0 -73
  110. package/lib/api-schemas/secrets.js.map +1 -1
  111. package/lib/api-schemas/store.d.ts +6388 -338
  112. package/lib/api-schemas/store.d.ts.map +1 -1
  113. package/lib/api-schemas/store.js +11 -0
  114. package/lib/api-schemas/store.js.map +1 -1
  115. package/lib/api-schemas/user.d.ts +9 -8
  116. package/lib/api-schemas/user.d.ts.map +1 -1
  117. package/lib/api-schemas/user.js.map +1 -1
  118. package/lib/api-schemas/view-execution.d.ts +8 -0
  119. package/lib/api-schemas/view-execution.d.ts.map +1 -1
  120. package/lib/api-schemas/views.d.ts +14 -0
  121. package/lib/api-schemas/views.d.ts.map +1 -1
  122. package/lib/api-schemas/workflow-runs.d.ts +335 -12
  123. package/lib/api-schemas/workflow-runs.d.ts.map +1 -1
  124. package/lib/api-schemas/workflow-runs.js +2 -0
  125. package/lib/api-schemas/workflow-runs.js.map +1 -1
  126. package/lib/apikey.d.ts +30 -25
  127. package/lib/apikey.d.ts.map +1 -1
  128. package/lib/apikey.js.map +1 -1
  129. package/lib/apps.d.ts +116 -121
  130. package/lib/apps.d.ts.map +1 -1
  131. package/lib/apps.js.map +1 -1
  132. package/lib/audit-trail.d.ts +30 -19
  133. package/lib/audit-trail.d.ts.map +1 -1
  134. package/lib/audit-trail.js +6 -0
  135. package/lib/audit-trail.js.map +1 -1
  136. package/lib/browser-credentials.d.ts +11 -12
  137. package/lib/browser-credentials.d.ts.map +1 -1
  138. package/lib/common.d.ts +17 -24
  139. package/lib/common.d.ts.map +1 -1
  140. package/lib/content-query.d.ts +3 -4
  141. package/lib/content-query.d.ts.map +1 -1
  142. package/lib/cost-analytics.d.ts +13 -21
  143. package/lib/cost-analytics.d.ts.map +1 -1
  144. package/lib/cost-analytics.js +0 -7
  145. package/lib/cost-analytics.js.map +1 -1
  146. package/lib/data-platform.d.ts +79 -88
  147. package/lib/data-platform.d.ts.map +1 -1
  148. package/lib/data-platform.js.map +1 -1
  149. package/lib/delegation.d.ts +4 -5
  150. package/lib/delegation.d.ts.map +1 -1
  151. package/lib/email.d.ts +15 -17
  152. package/lib/email.d.ts.map +1 -1
  153. package/lib/email.js.map +1 -1
  154. package/lib/embeddings.d.ts +25 -26
  155. package/lib/embeddings.d.ts.map +1 -1
  156. package/lib/environment.d.ts +16 -17
  157. package/lib/environment.d.ts.map +1 -1
  158. package/lib/environment.js.map +1 -1
  159. package/lib/facets.d.ts +3 -4
  160. package/lib/facets.d.ts.map +1 -1
  161. package/lib/group.d.ts +6 -7
  162. package/lib/group.d.ts.map +1 -1
  163. package/lib/group.js.map +1 -1
  164. package/lib/index.d.ts +3 -1
  165. package/lib/index.d.ts.map +1 -1
  166. package/lib/index.js.map +1 -1
  167. package/lib/inference-profile.d.ts +17 -0
  168. package/lib/inference-profile.d.ts.map +1 -0
  169. package/lib/inference-profile.js +2 -0
  170. package/lib/inference-profile.js.map +1 -0
  171. package/lib/integrations.d.ts +19 -20
  172. package/lib/integrations.d.ts.map +1 -1
  173. package/lib/integrations.js.map +1 -1
  174. package/lib/interaction.d.ts +68 -73
  175. package/lib/interaction.d.ts.map +1 -1
  176. package/lib/interaction.js.map +1 -1
  177. package/lib/meters.d.ts +4 -5
  178. package/lib/meters.d.ts.map +1 -1
  179. package/lib/oauth-server.d.ts +40 -41
  180. package/lib/oauth-server.d.ts.map +1 -1
  181. package/lib/oauth.d.ts +9 -10
  182. package/lib/oauth.d.ts.map +1 -1
  183. package/lib/payload.d.ts +11 -14
  184. package/lib/payload.d.ts.map +1 -1
  185. package/lib/pending-asks.d.ts +8 -13
  186. package/lib/pending-asks.d.ts.map +1 -1
  187. package/lib/pending-asks.js +0 -4
  188. package/lib/pending-asks.js.map +1 -1
  189. package/lib/platform-event.d.ts +48 -71
  190. package/lib/platform-event.d.ts.map +1 -1
  191. package/lib/platform-event.js.map +1 -1
  192. package/lib/principal-context.d.ts +3 -3
  193. package/lib/principal-context.d.ts.map +1 -1
  194. package/lib/project.d.ts +42 -43
  195. package/lib/project.d.ts.map +1 -1
  196. package/lib/project.js.map +1 -1
  197. package/lib/prompt.d.ts +14 -16
  198. package/lib/prompt.d.ts.map +1 -1
  199. package/lib/prompt.js.map +1 -1
  200. package/lib/query.d.ts +10 -13
  201. package/lib/query.d.ts.map +1 -1
  202. package/lib/rate-limiter.d.ts +7 -11
  203. package/lib/rate-limiter.d.ts.map +1 -1
  204. package/lib/refs.d.ts +2 -3
  205. package/lib/refs.d.ts.map +1 -1
  206. package/lib/refs.js.map +1 -1
  207. package/lib/roles/types.d.ts +5 -6
  208. package/lib/roles/types.d.ts.map +1 -1
  209. package/lib/roles/types.js.map +1 -1
  210. package/lib/run-budget.d.ts +4 -0
  211. package/lib/run-budget.d.ts.map +1 -0
  212. package/lib/run-budget.js +2 -0
  213. package/lib/run-budget.js.map +1 -0
  214. package/lib/runs.d.ts +9 -10
  215. package/lib/runs.d.ts.map +1 -1
  216. package/lib/secrets.d.ts +10 -21
  217. package/lib/secrets.d.ts.map +1 -1
  218. package/lib/store/agent-approval.d.ts +4 -5
  219. package/lib/store/agent-approval.d.ts.map +1 -1
  220. package/lib/store/agent-approval.js.map +1 -1
  221. package/lib/store/agent-run.d.ts +50 -52
  222. package/lib/store/agent-run.d.ts.map +1 -1
  223. package/lib/store/agent-run.js.map +1 -1
  224. package/lib/store/collections.d.ts +11 -12
  225. package/lib/store/collections.d.ts.map +1 -1
  226. package/lib/store/collections.js.map +1 -1
  227. package/lib/store/conversation-state.d.ts +14 -8
  228. package/lib/store/conversation-state.d.ts.map +1 -1
  229. package/lib/store/doc-analyzer.d.ts +7 -8
  230. package/lib/store/doc-analyzer.d.ts.map +1 -1
  231. package/lib/store/dsl-workflow.d.ts +10 -12
  232. package/lib/store/dsl-workflow.d.ts.map +1 -1
  233. package/lib/store/dsl-workflow.js.map +1 -1
  234. package/lib/store/duration.d.ts +12 -0
  235. package/lib/store/duration.d.ts.map +1 -0
  236. package/lib/store/duration.js +2 -0
  237. package/lib/store/duration.js.map +1 -0
  238. package/lib/store/grounded-extraction.d.ts +6 -7
  239. package/lib/store/grounded-extraction.d.ts.map +1 -1
  240. package/lib/store/intake-policy-schema.generated.d.ts.map +1 -1
  241. package/lib/store/intake-policy-schema.generated.js +143 -2
  242. package/lib/store/intake-policy-schema.generated.js.map +1 -1
  243. package/lib/store/process.d.ts +70 -69
  244. package/lib/store/process.d.ts.map +1 -1
  245. package/lib/store/process.js.map +1 -1
  246. package/lib/store/rendering.d.ts +6 -12
  247. package/lib/store/rendering.d.ts.map +1 -1
  248. package/lib/store/rendering.js +0 -5
  249. package/lib/store/rendering.js.map +1 -1
  250. package/lib/store/signals.d.ts +43 -0
  251. package/lib/store/signals.d.ts.map +1 -1
  252. package/lib/store/signals.js +6 -1
  253. package/lib/store/signals.js.map +1 -1
  254. package/lib/store/store.d.ts +92 -91
  255. package/lib/store/store.d.ts.map +1 -1
  256. package/lib/store/store.js.map +1 -1
  257. package/lib/store/task.d.ts +10 -14
  258. package/lib/store/task.d.ts.map +1 -1
  259. package/lib/store/workflow.d.ts +35 -41
  260. package/lib/store/workflow.d.ts.map +1 -1
  261. package/lib/store/workflow.js.map +1 -1
  262. package/lib/sts-token-types.d.ts +14 -19
  263. package/lib/sts-token-types.d.ts.map +1 -1
  264. package/lib/tools.d.ts +12 -13
  265. package/lib/tools.d.ts.map +1 -1
  266. package/lib/transient-tokens.d.ts +3 -3
  267. package/lib/transient-tokens.d.ts.map +1 -1
  268. package/lib/user.d.ts +16 -20
  269. package/lib/user.d.ts.map +1 -1
  270. package/lib/user.js.map +1 -1
  271. package/lib/vertesia-common.js +2 -2
  272. package/lib/vertesia-common.js.map +1 -1
  273. package/lib/views.d.ts +61 -64
  274. package/lib/views.d.ts.map +1 -1
  275. package/lib/views.js.map +1 -1
  276. package/lib/wire-types.generated.d.ts +11227 -0
  277. package/lib/wire-types.generated.d.ts.map +1 -0
  278. package/lib/wire-types.generated.js +4 -0
  279. package/lib/wire-types.generated.js.map +1 -0
  280. package/lib/workflow-analytics.d.ts +21 -19
  281. package/lib/workflow-analytics.d.ts.map +1 -1
  282. package/lib/workflow-analytics.js +2 -2
  283. package/lib/workflow-analytics.js.map +1 -1
  284. package/package.json +16 -11
  285. package/src/access-control-values.ts +2 -2
  286. package/src/access-control.ts +7 -15
  287. package/src/analytics.ts +6 -13
  288. package/src/api-contract/components.generated.json +2553 -1046
  289. package/src/api-contract/engine.ts +641 -0
  290. package/src/api-contract/index.ts +30 -661
  291. package/src/api-schemas/access-control.ts +18 -16
  292. package/src/api-schemas/account.ts +5 -12
  293. package/src/api-schemas/agent-budget.ts +60 -0
  294. package/src/api-schemas/agent-runs.ts +63 -27
  295. package/src/api-schemas/apikey.ts +11 -10
  296. package/src/api-schemas/app-lifecycle.ts +5 -0
  297. package/src/api-schemas/audit-trail.ts +175 -1
  298. package/src/api-schemas/content.ts +55 -0
  299. package/src/api-schemas/cost-analytics.ts +42 -2
  300. package/src/api-schemas/environment.ts +0 -1
  301. package/src/api-schemas/group.ts +2 -1
  302. package/src/api-schemas/index.ts +2 -0
  303. package/src/api-schemas/inference-profile.ts +151 -0
  304. package/src/api-schemas/interaction.ts +40 -1
  305. package/src/api-schemas/invites.ts +10 -9
  306. package/src/api-schemas/process.ts +78 -2
  307. package/src/api-schemas/project-configuration.ts +19 -1
  308. package/src/api-schemas/project.ts +19 -10
  309. package/src/api-schemas/quota.ts +7 -6
  310. package/src/api-schemas/registry.ts +164 -62
  311. package/src/api-schemas/run-budget.ts +23 -0
  312. package/src/api-schemas/secrets.ts +0 -84
  313. package/src/api-schemas/store.ts +12 -0
  314. package/src/api-schemas/user.ts +9 -8
  315. package/src/api-schemas/workflow-runs.ts +2 -0
  316. package/src/apikey.ts +30 -39
  317. package/src/apps.ts +116 -239
  318. package/src/audit-trail.ts +37 -35
  319. package/src/browser-credentials.ts +11 -23
  320. package/src/common.ts +17 -37
  321. package/src/content-query.ts +3 -4
  322. package/src/cost-analytics.ts +13 -35
  323. package/src/data-platform.ts +79 -168
  324. package/src/delegation.ts +4 -9
  325. package/src/email.ts +15 -29
  326. package/src/embeddings.ts +25 -51
  327. package/src/environment.ts +16 -33
  328. package/src/facets.ts +3 -4
  329. package/src/group.ts +6 -13
  330. package/src/index.ts +23 -0
  331. package/src/inference-profile.ts +20 -0
  332. package/src/integrations.ts +21 -41
  333. package/src/interaction.ts +68 -137
  334. package/src/meters.ts +4 -9
  335. package/src/oauth-server.ts +40 -81
  336. package/src/oauth.ts +9 -19
  337. package/src/payload.ts +11 -25
  338. package/src/pending-asks.ts +8 -22
  339. package/src/platform-event.ts +48 -122
  340. package/src/principal-context.ts +3 -3
  341. package/src/project.ts +43 -86
  342. package/src/prompt.ts +14 -31
  343. package/src/query.ts +10 -20
  344. package/src/rate-limiter.ts +7 -19
  345. package/src/refs.ts +2 -3
  346. package/src/roles/types.ts +5 -11
  347. package/src/run-budget.ts +4 -0
  348. package/src/runs.ts +9 -19
  349. package/src/secrets.ts +10 -42
  350. package/src/store/agent-approval.ts +4 -9
  351. package/src/store/agent-run.ts +53 -99
  352. package/src/store/collections.ts +11 -23
  353. package/src/store/conversation-state.ts +15 -15
  354. package/src/store/doc-analyzer.ts +7 -15
  355. package/src/store/dsl-workflow.ts +10 -23
  356. package/src/store/duration.ts +45 -0
  357. package/src/store/grounded-extraction.ts +6 -13
  358. package/src/store/intake-policy-schema.generated.ts +148 -2
  359. package/src/store/process.ts +70 -140
  360. package/src/store/rendering.ts +6 -19
  361. package/src/store/signals.ts +48 -0
  362. package/src/store/store.ts +92 -181
  363. package/src/store/task.ts +10 -24
  364. package/src/store/workflow.ts +35 -71
  365. package/src/sts-token-types.ts +14 -33
  366. package/src/tools.ts +12 -25
  367. package/src/transient-tokens.ts +3 -3
  368. package/src/user.ts +16 -40
  369. package/src/views.ts +61 -125
  370. package/src/wire-types.generated.ts +11888 -0
  371. package/src/workflow-analytics.ts +21 -19
  372. package/src/agent-resources.test.ts +0 -89
  373. package/src/api-contract/components.contract.test.ts +0 -99
  374. package/src/api-schemas/access-control.contract.test.ts +0 -209
  375. package/src/api-schemas/account-apikey.test.ts +0 -60
  376. package/src/api-schemas/account.contract.test.ts +0 -319
  377. package/src/api-schemas/adapter-edge-cases.test.ts +0 -499
  378. package/src/api-schemas/agent-communication.contract.test.ts +0 -90
  379. package/src/api-schemas/agent-history.contract.test.ts +0 -42
  380. package/src/api-schemas/agent-runs.contract.test.ts +0 -240
  381. package/src/api-schemas/api-discriminators.test.ts +0 -185
  382. package/src/api-schemas/apikey.contract.test.ts +0 -270
  383. package/src/api-schemas/app-delete-summary.contract.test.ts +0 -67
  384. package/src/api-schemas/bulk-operation.contract.test.ts +0 -39
  385. package/src/api-schemas/bundle-isolation.test.ts +0 -44
  386. package/src/api-schemas/commands.contract.test.ts +0 -51
  387. package/src/api-schemas/cost-analytics.contract.test.ts +0 -64
  388. package/src/api-schemas/dashboard.contract.test.ts +0 -138
  389. package/src/api-schemas/data-store.contract.test.ts +0 -97
  390. package/src/api-schemas/document-processing.contract.test.ts +0 -76
  391. package/src/api-schemas/emit-json-schema.test.ts +0 -36
  392. package/src/api-schemas/environment.contract.test.ts +0 -202
  393. package/src/api-schemas/group.contract.test.ts +0 -205
  394. package/src/api-schemas/indexing.contract.test.ts +0 -122
  395. package/src/api-schemas/interaction.contract.test.ts +0 -307
  396. package/src/api-schemas/invites.contract.test.ts +0 -268
  397. package/src/api-schemas/llumiverse.contract.test.ts +0 -179
  398. package/src/api-schemas/mcp-api-key.contract.test.ts +0 -125
  399. package/src/api-schemas/oauth.contract.test.ts +0 -181
  400. package/src/api-schemas/parameters.test.ts +0 -402
  401. package/src/api-schemas/process.contract.test.ts +0 -115
  402. package/src/api-schemas/project.contract.test.ts +0 -472
  403. package/src/api-schemas/pruning-limits.test.ts +0 -189
  404. package/src/api-schemas/quota.contract.test.ts +0 -147
  405. package/src/api-schemas/registry-groups.test.ts +0 -99
  406. package/src/api-schemas/response-pruning.test.ts +0 -260
  407. package/src/api-schemas/store.contract.test.ts +0 -378
  408. package/src/api-schemas/sts.contract.test.ts +0 -112
  409. package/src/api-schemas/user.contract.test.ts +0 -197
  410. package/src/api-schemas/views.contract.test.ts +0 -112
  411. package/src/api-schemas/zeno-response-contracts.test.ts +0 -380
  412. package/src/apps.test.ts +0 -89
  413. package/src/oauth-scopes.test.ts +0 -15
  414. package/src/roles.test.ts +0 -33
  415. package/src/schema-for-extraction.test.ts +0 -191
  416. package/src/store/agent-approval.test.ts +0 -18
  417. package/src/store/content-type-editing.test.ts +0 -17
  418. package/src/store/ms.d.ts +0 -42
  419. package/src/store/schedule.test.ts +0 -59
  420. package/src/store/workflow.test.ts +0 -640
  421. package/src/versions.test.ts +0 -13
@@ -1,260 +0,0 @@
1
- import { Ajv2020 } from 'ajv/dist/2020.js';
2
- import { describe, expect, it } from 'vitest';
3
- import { AccountType, BillingMethod } from '../user.js';
4
- import { findUnprunablePaths, type JsonObject, pruneToSchema, toOpenApiComponents } from './adapter.js';
5
- import {
6
- type ApiComponentType,
7
- ApiSchemaComponents,
8
- apiComponentRef,
9
- pruneAndValidateApiResponse,
10
- pruneApiResponse,
11
- } from './registry.js';
12
-
13
- function compile(name: string) {
14
- const ajv = new Ajv2020({ strictSchema: false, allErrors: true });
15
- ajv.addSchema({ $id: 'vertesia://openapi', components: { schemas: ApiSchemaComponents } });
16
- return ajv.compile({ $ref: `vertesia://openapi${apiComponentRef(name as never)}` });
17
- }
18
-
19
- const ACCOUNT: ApiComponentType<'Account'> = {
20
- id: 'acc_1',
21
- name: 'Acme',
22
- email_domains: ['acme.com'],
23
- onboarding: { completed: true, completed_at: '2026-07-29T10:00:00.000Z' },
24
- datacenter: 'gcp',
25
- account_type: AccountType.customer,
26
- billing: { method: BillingMethod.stripe, stripe_customer_id: 'cus_1' },
27
- feature_flags: { new_editor: true, beta_agents: 'on' },
28
- created_by: 'u1',
29
- updated_by: 'u1',
30
- created_at: '2026-07-29T10:00:00.000Z',
31
- updated_at: '2026-07-29T10:00:00.000Z',
32
- };
33
-
34
- /**
35
- * An Account carrying extra runtime fields — what a Mongo document actually is. The cast models
36
- * the gap the pruner exists to close: the value is typed as the component, but at runtime it has
37
- * more than the component declares.
38
- */
39
- const withExtras = (extra: Record<string, unknown>): ApiComponentType<'Account'> =>
40
- ({ ...ACCOUNT, ...extra }) as ApiComponentType<'Account'>;
41
-
42
- describe('response pruning narrows payloads to the published contract', () => {
43
- it('drops undeclared top-level fields', () => {
44
- const pruned = pruneApiResponse(
45
- 'Account',
46
- withExtras({ __v: 3, internal_notes: 'do not ship', stripe_secret: 'sk_live_leak' }),
47
- );
48
- expect(pruned).toEqual(ACCOUNT);
49
- expect('stripe_secret' in pruned).toBe(false);
50
- });
51
-
52
- it('drops undeclared fields nested inside a declared object', () => {
53
- const pruned = pruneApiResponse(
54
- 'Account',
55
- withExtras({
56
- onboarding: { ...ACCOUNT.onboarding, internal_step: 7 },
57
- billing: { ...ACCOUNT.billing, stripe_secret_key: 'sk_live_leak' },
58
- }),
59
- );
60
- expect(pruned.onboarding).toEqual(ACCOUNT.onboarding);
61
- expect(pruned.billing).toEqual(ACCOUNT.billing);
62
- });
63
-
64
- it('PRESERVES the contents of freeform maps', () => {
65
- // The regression this design exists to avoid: AJV's removeAdditional:'all' strips keys
66
- // from objects that declare additionalProperties too, which is how launch_workstream's
67
- // `data` was emptied. `feature_flags` is `{additionalProperties:{}}` with no `properties`,
68
- // so every operator flag would vanish under a blanket removal mode.
69
- const pruned = pruneApiResponse('Account', ACCOUNT);
70
- expect(pruned.feature_flags).toEqual({ new_editor: true, beta_agents: 'on' });
71
- });
72
-
73
- it('leaves a conforming payload byte-identical', () => {
74
- expect(pruneApiResponse('Account', ACCOUNT)).toEqual(ACCOUNT);
75
- });
76
-
77
- it('never mutates the payload it is given', () => {
78
- const input = withExtras({ rogue: 1 });
79
- const pristine = structuredClone(input);
80
- pruneApiResponse('Account', input);
81
- expect(input).toEqual(pristine);
82
- });
83
-
84
- it('produces output that validates against the published schema', () => {
85
- const validate = compile('Account');
86
- const pruned = pruneApiResponse('Account', withExtras({ leaked: 'x' }));
87
- expect(validate(pruned)).toBe(true);
88
- });
89
-
90
- it('does not throw on a payload that is missing required fields', () => {
91
- // Pruning is not validation. A malformed document still reaches the client rather than
92
- // becoming a 500 — surfacing drift is the validator's job, not the pruner's.
93
- const malformed = { id: 'acc_1', junk: true } as unknown as ApiComponentType<'Account'>;
94
- expect(() => pruneApiResponse('Account', malformed)).not.toThrow();
95
- expect(pruneApiResponse('Account', malformed)).toEqual({ id: 'acc_1' });
96
- });
97
- });
98
-
99
- describe('pruneAndValidateApiResponse is the sound entry point for untyped payloads', () => {
100
- it('returns the component type only on the valid branch', () => {
101
- const result = pruneAndValidateApiResponse('Account', withExtras({ leaked: 'x' }));
102
- expect(result.valid).toBe(true);
103
- if (result.valid) {
104
- // Reachable as the component type only after validation succeeded.
105
- const id: string = result.data.id;
106
- expect(id).toBe('acc_1');
107
- expect('leaked' in result.data).toBe(false);
108
- }
109
- });
110
-
111
- it('reports errors instead of typing an incomplete payload as complete', () => {
112
- // The unsoundness this replaces: narrowing `{id}` and handing it back as a full Account.
113
- const result = pruneAndValidateApiResponse('Account', { id: 'acc_1', junk: true });
114
- expect(result.valid).toBe(false);
115
- if (!result.valid) {
116
- expect(result.errors.join(' ')).toContain("must have required property 'name'");
117
- // The pruned value is still available, so the caller chooses ship-and-log or fail.
118
- expect(result.data).toEqual({ id: 'acc_1' });
119
- }
120
- });
121
-
122
- it('flags a legacy account missing created_by/updated_by', () => {
123
- // Real migration hazard: the Mongo schema declares these without `required`, and the
124
- // BackfillAccountCreatedBy migration skips ownerless accounts by design.
125
- const { created_by: _c, updated_by: _u, ...legacy } = ACCOUNT;
126
- const result = pruneAndValidateApiResponse('Account', legacy);
127
- expect(result.valid).toBe(false);
128
- if (!result.valid) {
129
- expect(result.errors.join(' ')).toContain('created_by');
130
- expect(result.errors.join(' ')).toContain('updated_by');
131
- }
132
- });
133
- });
134
-
135
- describe('response pruning through structural schema features', () => {
136
- it('follows the discriminator to the matching union branch', () => {
137
- const enabled = pruneApiResponse('StripeBillingStatusResponse', {
138
- status: 'enabled',
139
- billing_method: 'stripe',
140
- portal_url: 'https://billing',
141
- internal_session_id: 'leak',
142
- } as never);
143
- expect(enabled).toEqual({ status: 'enabled', billing_method: 'stripe', portal_url: 'https://billing' });
144
-
145
- const disabled = pruneApiResponse('StripeBillingStatusResponse', {
146
- status: 'disabled',
147
- billing_method: null,
148
- reason: 'No billing method',
149
- internal_trace: 'leak',
150
- } as never);
151
- expect(disabled).toEqual({ status: 'disabled', billing_method: null, reason: 'No billing method' });
152
- });
153
-
154
- it('prunes inside arrays', () => {
155
- const components = toOpenApiComponents({
156
- Page: {
157
- type: 'object',
158
- properties: {
159
- items: {
160
- type: 'array',
161
- items: { $id: 'Row', type: 'object', properties: { id: { type: 'string' } } },
162
- },
163
- },
164
- },
165
- });
166
- const pruned = pruneToSchema(
167
- {
168
- items: [
169
- { id: 'a', secret: 1 },
170
- { id: 'b', secret: 2 },
171
- ],
172
- extra: true,
173
- },
174
- { $ref: '#/components/schemas/Page' },
175
- components,
176
- ) as JsonObject;
177
- expect(pruned).toEqual({ items: [{ id: 'a' }, { id: 'b' }] });
178
- });
179
-
180
- it('leaves ambiguous schemas untouched rather than guessing', () => {
181
- // An undiscriminated union and an allOf could each drop fields that belong to a branch we
182
- // cannot identify, so the payload passes through intact.
183
- const components = toOpenApiComponents({
184
- Loose: { anyOf: [{ type: 'object', properties: { a: { type: 'string' } } }, { type: 'object' }] },
185
- Merged: { allOf: [{ type: 'object', properties: { a: { type: 'string' } } }] },
186
- });
187
- const payload = { a: 'x', b: 'keep' };
188
- expect(pruneToSchema(payload, { $ref: '#/components/schemas/Loose' }, components)).toEqual(payload);
189
- expect(pruneToSchema(payload, { $ref: '#/components/schemas/Merged' }, components)).toEqual(payload);
190
- });
191
-
192
- it('keeps extras where a component explicitly declares itself extensible', () => {
193
- const components = toOpenApiComponents({
194
- Open: { type: 'object', properties: { a: { type: 'string' } }, additionalProperties: true },
195
- });
196
- expect(pruneToSchema({ a: 'x', b: 'keep' }, { $ref: '#/components/schemas/Open' }, components)).toEqual({
197
- a: 'x',
198
- b: 'keep',
199
- });
200
- });
201
-
202
- it('keeps properties documented on a $ref sibling', () => {
203
- // 2020-12 applies $ref siblings as additional constraints, so `extra` is declared here
204
- // and must survive pruning rather than being dropped as unknown.
205
- const components = toOpenApiComponents({
206
- Wrapper: {
207
- type: 'object',
208
- properties: {
209
- inner: {
210
- $ref: '#/$defs/Base',
211
- properties: { extra: { type: 'string' } },
212
- required: ['extra'],
213
- },
214
- },
215
- $defs: { Base: { type: 'object', properties: { a: { type: 'string' } }, required: ['a'] } },
216
- },
217
- });
218
- const pruned = pruneToSchema(
219
- { inner: { a: 'x', extra: 'documented', undeclared: 'drop' } },
220
- { $ref: '#/components/schemas/Wrapper' },
221
- components,
222
- );
223
- expect(pruned).toEqual({ inner: { a: 'x', extra: 'documented' } });
224
- });
225
-
226
- it('follows a chain of aliased references to the terminal schema', () => {
227
- // A component that is itself a reference is an alias. Resolving only one hop would leave a
228
- // node whose `properties` lists just `extra`, so pruning would read that as the entire
229
- // shape and drop `a` — which Base requires, making the pruned response fail validation.
230
- const components = toOpenApiComponents({
231
- Alias: {
232
- $ref: '#/components/schemas/Base',
233
- properties: { extra: { type: 'string' } },
234
- required: ['extra'],
235
- },
236
- Base: { type: 'object', properties: { a: { type: 'string' } }, required: ['a'] },
237
- });
238
- const ref = { $ref: '#/components/schemas/Alias' };
239
-
240
- const pruned = pruneToSchema({ a: 'x', extra: 'documented', undeclared: 'drop' }, ref, components);
241
- expect(pruned).toEqual({ a: 'x', extra: 'documented' });
242
- // The detector recurses through references, so it must reach the same terminal schema —
243
- // a divergence here means it certifies a component the pruner then mangles.
244
- expect(findUnprunablePaths(ref, components)).toEqual([]);
245
-
246
- const ajv = new Ajv2020({ strictSchema: false, allErrors: true });
247
- ajv.addSchema({ $id: 'vertesia://chain', components: { schemas: components } });
248
- expect(ajv.validate({ $ref: 'vertesia://chain#/components/schemas/Alias' }, pruned)).toBe(true);
249
- });
250
-
251
- it('strips undeclared fields on a component closed with additionalProperties:false', () => {
252
- const components = toOpenApiComponents(
253
- { Closed: { type: 'object', properties: { a: { type: 'string' } } } },
254
- { strictComponents: new Set(['Closed']) },
255
- );
256
- expect(pruneToSchema({ a: 'x', b: 'drop' }, { $ref: '#/components/schemas/Closed' }, components)).toEqual({
257
- a: 'x',
258
- });
259
- });
260
- });
@@ -1,378 +0,0 @@
1
- import { Ajv } from 'ajv';
2
- import { describe, expect, it } from 'vitest';
3
- import { ContentTypeIntakePolicySchema as GeneratedIntakePolicySchema } from '../store/intake-policy-schema.generated.js';
4
- import type { ContentObjectTypeRef, ContentTypeIntakePolicy, IntakePageRanges } from '../store/store.js';
5
- import type { JsonObject } from './adapter.js';
6
- import { ApiSchemaComponents, bundleCanonicalComponent, validateApiResponse } from './registry.js';
7
- import { ContentTypeIntakePolicySchema } from './store.js';
8
-
9
- /** Exact type identity — `extends` in both directions is too weak (any/unknown slip through). */
10
- type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
11
- function assertType<T extends true>(_ok: T): void {}
12
-
13
- /**
14
- * The intake policy is now stated once, in Zod, and reaches its consumers three ways: as the
15
- * canonical component, as the checked-in JSON artifact consumers compile, and as the TypeScript
16
- * type. This file keeps those package-owned contracts aligned. Downstream consumers test their
17
- * published API documents and generated-client fixtures separately.
18
- *
19
- * It also pins the behaviour changes the conversion makes, because the schema it replaced was
20
- * hand-written and disagreed with the contract in both directions. Each is asserted rather than
21
- * described: the whole point of the migration is that a disagreement fails a build instead of
22
- * shipping.
23
- */
24
- const ajv = new Ajv({ strict: false, allErrors: true });
25
- const validate = ajv.compile<ContentTypeIntakePolicy>(GeneratedIntakePolicySchema);
26
-
27
- function errors(): string {
28
- return ajv.errorsText(validate.errors, { separator: '\n' });
29
- }
30
-
31
- describe('generated artifact and canonical component', () => {
32
- it('is the exact bundle the registry emits, so the artifact is compiled output', () => {
33
- // Deep equality, not a spot check: the file is generated by `pnpm run gen:schemas` from this
34
- // same function, so any difference means someone hand-edited it or forgot to regenerate.
35
- expect(GeneratedIntakePolicySchema).toEqual(bundleCanonicalComponent('ContentTypeIntakePolicy'));
36
- });
37
-
38
- it('registers the component the alias claims, under the id the alias name requires', () => {
39
- expect(Object.keys(ApiSchemaComponents)).toContain('ContentTypeIntakePolicy');
40
- assertType<Equals<ContentTypeIntakePolicy, (typeof ContentTypeIntakePolicySchema)['_zod']['output']>>(true);
41
- });
42
- });
43
-
44
- describe('content object response classification', () => {
45
- it('accepts the current sensitivity and compartments fields', () => {
46
- const result = validateApiResponse('ContentObjectApiResponse', {
47
- id: 'content-object-id',
48
- name: 'Classified document',
49
- updated_by: 'user-id',
50
- created_by: 'user-id',
51
- created_at: '2026-08-06T09:00:00.000Z',
52
- updated_at: '2026-08-06T09:00:00.000Z',
53
- location: '/',
54
- status: 'completed',
55
- properties: {},
56
- revision: { root: 'content-object-id', head: true },
57
- sensitivity: 3,
58
- compartments: ['legal'],
59
- });
60
-
61
- expect(result).toMatchObject({ valid: true });
62
- });
63
- });
64
-
65
- /**
66
- * Bodies that probe where the two validators could disagree.
67
- *
68
- * The gate above compares the artifact to the component, and both are produced by the SAME adapter
69
- * from the SAME Zod schema — so any transform applied on the way out is invisible to it. That blind
70
- * spot shipped once: an adapter pass stripped the bounds `z.int()` attaches for the JavaScript
71
- * safe-integer range, on the reasoning that no JSON value could fall outside them. `1e20` does, and
72
- * the Zod schema rejected it while the generated schema accepted it. Nothing in a
73
- * schema-versus-schema comparison can see that; only running both validators over the same value can.
74
- */
75
- const PROBES: unknown[] = [
76
- // Numeric range, including the values that made the sentinel-stripping bug observable.
77
- {},
78
- { extraction: { max_pages: 1 } },
79
- { extraction: { max_pages: 0 } },
80
- { extraction: { max_pages: 2.5 } },
81
- { extraction: { max_pages: 1e20 } },
82
- { extraction: { max_pages: 2147483647 } },
83
- { extraction: { max_pages: 2147483648 } },
84
- { extraction: { max_pages: Number.MAX_SAFE_INTEGER + 1 } },
85
- { extraction: { max_pages: -1 } },
86
- { locate: { instructions: 'x', min_pages: 0 } },
87
- { locate: { instructions: 'x', min_pages: -1 } },
88
- { locate: { instructions: 'x', min_pages: 1e20 } },
89
- { locate: { detail: 8 } },
90
- { text_conversion: { render_dpi: 72 } },
91
- { text_conversion: { render_dpi: 71 } },
92
- { text_conversion: { render_dpi: 1e20 } },
93
- { extraction: { verification: { threshold: 0 } } },
94
- { extraction: { verification: { threshold: 1 } } },
95
- { extraction: { verification: { threshold: 1.000001 } } },
96
- { extraction: { verification: { max_retries: 1e20 } } },
97
- { extraction: { vision: { max_image_tokens: 1e20, max_payload_mb: 1e20 } } },
98
- { extraction: { grounding: { window_pages: 1e20, grid_cell_pt: 1e20 } } },
99
- { extraction: { grounding: { hardness_threshold: 1e20 } } },
100
- // Page ranges: length, element type, and element magnitude.
101
- { extraction: { page_ranges: [[1, 2]] } },
102
- { extraction: { page_ranges: [[-1, -1]] } },
103
- { extraction: { page_ranges: [[1]] } },
104
- { extraction: { page_ranges: [[1, 2, 3]] } },
105
- { extraction: { page_ranges: [[1.5, 2]] } },
106
- { extraction: { page_ranges: [[1e20, 2]] } },
107
- // Nullability, unknown keys, and the enums.
108
- { generate_toc: null },
109
- { extraction: null },
110
- { extraction: { max_pages: null } },
111
- { grounded_extraction: { enabled: true } },
112
- { locate: { instructions: 'x', dpi: 300 } },
113
- { extraction: { scope: 'first-two' } },
114
- { extraction: { vision: { default_detail: 'ultra' } } },
115
- { default_view: 'pdf' },
116
- { mode: 'agentic' },
117
- // The execution config: closedness, the option union, the two enums.
118
- { extraction: { config: { model: 'm' } } },
119
- { extraction: { config: { temperature: 0.5 } } },
120
- { extraction: { config: { http_timeout: { bodyTimeout: 1000 } } } },
121
- { extraction: { config: { http_timeout: { socketTimeout: 1000 } } } },
122
- { extraction: { config: { model_options: { _option_id: 'openai-text', temperature: 0.5 } } } },
123
- { extraction: { config: { model_options: { temperature: 0.5 } } } },
124
- { extraction: { config: { model_options: { _option_id: 'not-a-driver' } } } },
125
- { extraction: { config: { run_data: 'STANDARD' } } },
126
- { extraction: { config: { run_data: 'WHATEVER' } } },
127
- { extraction: { config: { configMode: 'RUN_CONFIG_ONLY' } } },
128
- // Wrong types where a shape is expected.
129
- { extraction: 'nope' },
130
- { embeddings: { text: 'yes' } },
131
- { identification: { examples: 'not-a-list' } },
132
- ];
133
-
134
- describe('gate — the artifact accepts exactly what the Zod schema accepts', () => {
135
- it.each(PROBES.map((probe) => [JSON.stringify(probe), probe] as const))('agrees on %s', (_label, probe) => {
136
- // The point of the migration is that ONE schema is enforced. Two validators built from it
137
- // that disagree on a value means one of the consumers is enforcing something the source
138
- // never said, which is the drift this whole exercise removes.
139
- expect(validate(probe)).toBe(ContentTypeIntakePolicySchema.safeParse(probe).success);
140
- });
141
- });
142
-
143
- describe('the TypeScript type says what the schema says', () => {
144
- it('widens page ranges to number[][], which is what the component has always described', () => {
145
- // `[number, number][]` is what the interface used to claim. The published component is
146
- // `items: {type: integer}` with `minItems`/`maxItems` — a two-element ARRAY, not a tuple —
147
- // because a Zod tuple emits `prefixItems`, which generated Java and Go clients read
148
- // differently. The wire shape is unchanged; the SDK type is corrected to match it.
149
- assertType<Equals<IntakePageRanges, number[][]>>(true);
150
- expect(validate({ extraction: { page_ranges: [[1, 2]] } }), errors()).toBe(true);
151
- });
152
-
153
- it('keeps the two type refs’ default_view in step with the policy', () => {
154
- // Those refs spell the union out rather than writing `ContentTypeIntakePolicy['default_view']`,
155
- // because indexing into a canonical alias makes the generator DROP the property instead of
156
- // failing. This is what stops the restatement from drifting.
157
- assertType<
158
- Equals<
159
- NonNullable<ContentObjectTypeRef['default_view']>,
160
- NonNullable<ContentTypeIntakePolicy['default_view']>
161
- >
162
- >(true);
163
- });
164
- });
165
-
166
- describe('parity with the hand-written AJV schema it replaces', () => {
167
- it('still accepts a full policy across every block', () => {
168
- const policy: ContentTypeIntakePolicy = {
169
- mode: 'programmatic',
170
- identification: { guidance: 'Investor reports' },
171
- locate: { instructions: 'allocation tables', detail: 8, min_pages: 10 },
172
- text_conversion: { method: 'llm', scope: 'located', render_dpi: 150 },
173
- extraction: {
174
- source: 'vision',
175
- page_ranges: [
176
- [1, 2],
177
- [-1, -1],
178
- ],
179
- max_pages: 6,
180
- vision: { default_detail: 'high', max_image_tokens: 9000, max_payload_mb: 12 },
181
- verification: { threshold: 0.7, max_retries: 2 },
182
- grounding: {
183
- enabled: true,
184
- max_pages: 12,
185
- hardness_threshold: 0.5,
186
- config: { model: 'claude-sonnet-4-5' },
187
- review: { threshold: 0.7, coverage_threshold: 0.2 },
188
- },
189
- },
190
- embeddings: { text: true, properties: true },
191
- default_view: 'pdf',
192
- };
193
- expect(validate(policy), errors()).toBe(true);
194
- });
195
-
196
- it('keeps every numeric bound the hand-written schema enforced', () => {
197
- // These were NOT in the published component — the interface carried no `@minimum` tags — so
198
- // converting to Zod dropped all eighteen of them until this test caught it. They are restored
199
- // in the schema, which means the document now publishes constraints the server has enforced
200
- // all along.
201
- expect(validate({ locate: { instructions: 'x', min_pages: -1 } })).toBe(false);
202
- expect(validate({ text_conversion: { render_dpi: 71 } })).toBe(false);
203
- expect(validate({ extraction: { max_pages: 0 } })).toBe(false);
204
- expect(validate({ extraction: { verification: { threshold: 1.2 } } })).toBe(false);
205
- expect(validate({ extraction: { verification: { max_retries: -1 } } })).toBe(false);
206
- expect(validate({ extraction: { vision: { max_image_tokens: 0 } } })).toBe(false);
207
- expect(validate({ extraction: { vision: { max_payload_mb: 0 } } })).toBe(false);
208
- expect(validate({ extraction: { vision: { max_pages_per_call: 0 } } })).toBe(false);
209
- expect(validate({ extraction: { grounding: { max_pages: 0 } } })).toBe(false);
210
- expect(validate({ extraction: { grounding: { window_pages: 0 } } })).toBe(false);
211
- expect(validate({ extraction: { grounding: { grid_cell_pt: 0 } } })).toBe(false);
212
- expect(validate({ extraction: { grounding: { hardness_threshold: -0.1 } } })).toBe(false);
213
- expect(validate({ extraction: { grounding: { min_citation_density: 1.1 } } })).toBe(false);
214
- expect(validate({ extraction: { grounding: { review: { threshold: 1.1 } } } })).toBe(false);
215
- expect(validate({ extraction: { grounding: { review: { coverage_threshold: -0.1 } } } })).toBe(false);
216
- });
217
-
218
- it('keeps the page and DPI counters integral', () => {
219
- // `type: 'integer'`, which the published component also never stated. A fractional page cap
220
- // was rejected before this conversion and is rejected after it.
221
- expect(validate({ extraction: { max_pages: 2.5 } })).toBe(false);
222
- expect(validate({ text_conversion: { render_dpi: 150.5 } })).toBe(false);
223
- expect(validate({ extraction: { page_ranges: [[1.5, 2]] } })).toBe(false);
224
- expect(validate({ extraction: { page_ranges: [[1]] } })).toBe(false);
225
- expect(validate({ locate: { instructions: 'x', min_pages: 8.5 } })).toBe(false);
226
- });
227
-
228
- it('keeps rejecting unknown keys and the obsolete root block', () => {
229
- expect(validate({ grounded_extraction: { enabled: true } })).toBe(false);
230
- expect(validate({ locate: { instructions: 'x', dpi: 300 } })).toBe(false);
231
- expect(validate({ extraction: { vision: { default_detail: 'ultra' } } })).toBe(false);
232
- });
233
- });
234
-
235
- describe('runtime tightenings — recorded as operation 25 of the 1.5 runbook', () => {
236
- it('rejects an explicit null where the hand-written schema accepted one', () => {
237
- // The replaced schema carried `nullable: true` on 112 subschemas and AJV honours that keyword
238
- // for OpenAPI compatibility, so 101 of them accepted `null` — which neither the TypeScript
239
- // type nor the published component has ever allowed. The fields are optional, not nullable.
240
- expect(validate({ generate_toc: null })).toBe(false);
241
- expect(validate({ rendering_template: null })).toBe(false);
242
- expect(validate({ extraction: { max_pages: null } })).toBe(false);
243
- expect(validate({ extraction: null })).toBe(false);
244
- // Omission is still how you say "inherit", which is what every one of those fields meant.
245
- expect(validate({}), errors()).toBe(true);
246
- expect(validate({ extraction: {} }), errors()).toBe(true);
247
- });
248
-
249
- it('closes the execution config, which the published component already described closed', () => {
250
- // `config` was `additionalProperties: true` in the hand-written schema while
251
- // `InteractionExecutionConfiguration` has always been published closed. A stored policy
252
- // carrying an undeclared key there is now rejected at write time.
253
- expect(ApiSchemaComponents.InteractionExecutionConfiguration.additionalProperties).toBe(false);
254
- expect(validate({ extraction: { config: { model: 'claude-sonnet-4-5' } } }), errors()).toBe(true);
255
- expect(
256
- validate({ extraction: { config: { prompt_cache_mode: 'required', prompt_cache_ttl_seconds: 3600 } } }),
257
- errors(),
258
- ).toBe(true);
259
- expect(validate({ extraction: { config: { prompt_cache_ttl_seconds: 59 } } })).toBe(false);
260
- expect(validate({ extraction: { config: { temperature: 0.5 } } })).toBe(false);
261
- expect(validate({ extraction: { config: { http_timeout: { socketTimeout: 1000 } } } })).toBe(false);
262
- });
263
-
264
- it('validates model_options against the union instead of accepting any object', () => {
265
- // Same class: `model_options` was `{type: object, additionalProperties: true}` in the
266
- // hand-written schema and `$ref: ModelOptions` in the published component. The family hint
267
- // is optional, but known field types and supplied IDs remain validated.
268
- expect(ApiSchemaComponents.ContentTypeIntakePolicy).toBeDefined();
269
- expect(
270
- validate({
271
- extraction: { config: { model_options: { _option_id: 'openai-text', temperature: 0.5 } } },
272
- }),
273
- errors(),
274
- ).toBe(true);
275
- expect(validate({ extraction: { config: { model_options: { temperature: 0.5 } } } })).toBe(true);
276
- expect(validate({ extraction: { config: { model_options: { _option_id: 'not-a-driver' } } } })).toBe(false);
277
- expect(validate({ extraction: { config: { model_options: {} } } })).toBe(true);
278
- expect(validate({ extraction: { config: { model_options: { temperature: 'hot' } } } })).toBe(false);
279
- expect(validate({ extraction: { config: { model_options: { unknown_option: true } } } })).toBe(false);
280
- });
281
-
282
- it('constrains the two config enums that were unconstrained strings', () => {
283
- expect(validate({ extraction: { config: { run_data: 'STANDARD' } } }), errors()).toBe(true);
284
- expect(validate({ extraction: { config: { run_data: 'WHATEVER' } } })).toBe(false);
285
- expect(validate({ extraction: { config: { configMode: 'RUN_CONFIG_ONLY' } } }), errors()).toBe(true);
286
- expect(validate({ extraction: { config: { configMode: 'WHATEVER' } } })).toBe(false);
287
- });
288
- });
289
-
290
- describe('the five content-type shapes are composed, not repeated', () => {
291
- const properties = (name: string) =>
292
- Object.keys((ApiSchemaComponents[name] as { properties: Record<string, unknown> }).properties);
293
- const property = (name: string, key: string) =>
294
- (ApiSchemaComponents[name] as { properties: Record<string, JsonObject> }).properties[key];
295
-
296
- it('gives every shape the same definition for a shared field', () => {
297
- // The drift this guards: five hand-transcribed copies of `table_layout` could disagree about
298
- // its item type or its description and nothing would notice. They come from one dictionary now.
299
- const shapes = [
300
- 'ContentObjectTypeItem',
301
- 'ContentObjectType',
302
- 'ContentObjectTypeCatalogEntry',
303
- 'InCodeTypeDefinition',
304
- 'CreateContentObjectTypePayload',
305
- ];
306
- for (const field of ['table_layout', 'object_schema', 'strict_mode', 'intake', 'editing', 'status']) {
307
- const rendered = shapes.map((shape) => JSON.stringify(property(shape, field)));
308
- expect(new Set(rendered).size, `${field} differs across the content-type shapes`).toBe(1);
309
- }
310
- });
311
-
312
- it('keeps the published property order, which composition must not reshuffle', () => {
313
- // Order is contract: it decides the order of the generated clients' constructor arguments and
314
- // model fields. The five orders differ because they were derived from five different types.
315
- expect(properties('ContentObjectTypeItem')).toEqual(properties('ContentObjectType'));
316
- expect(properties('ContentObjectTypeCatalogEntry').slice(0, 12)).toEqual(properties('InCodeTypeDefinition'));
317
- expect(properties('CreateContentObjectTypePayload')).toEqual([
318
- 'status',
319
- 'is_chunkable',
320
- 'intake',
321
- 'editing',
322
- 'table_layout',
323
- 'object_schema',
324
- 'strict_mode',
325
- 'name',
326
- 'description',
327
- 'tags',
328
- ]);
329
- });
330
-
331
- it('keeps the audit fields required on a stored type and optional in the catalog', () => {
332
- // Not a detail: a catalog entry may be an in-code type contributed by a plugin, which nobody
333
- // created and nobody has modified. Requiring the four there would reject a legitimate entry.
334
- const audit = ['updated_by', 'created_by', 'created_at', 'updated_at'];
335
- const required = (name: string) => (ApiSchemaComponents[name] as { required?: string[] }).required ?? [];
336
-
337
- expect(required('ContentObjectTypeItem')).toEqual(expect.arrayContaining(audit));
338
- expect(required('ContentObjectType')).toEqual(expect.arrayContaining(audit));
339
- for (const field of audit) {
340
- expect(required('ContentObjectTypeCatalogEntry')).not.toContain(field);
341
- expect(property('ContentObjectTypeCatalogEntry', field)).toEqual({ type: 'string' });
342
- }
343
- });
344
-
345
- it('accepts a catalog entry for an in-code type that has no audit trail', () => {
346
- expect(
347
- validateApiResponse('ContentObjectTypeCatalogEntry', {
348
- id: 'sys:Invoice',
349
- name: 'Invoice',
350
- is_chunkable: false,
351
- }).valid,
352
- ).toBe(true);
353
- });
354
-
355
- it('publishes `title` on the app-contribution shapes and withholds it from the stored ones', () => {
356
- // An app package contributes a display title alongside the app-local `name`, exactly as
357
- // `InCodeViewDefinition` and `InCodeProcessDefinition` do. Only the two shapes that carry a
358
- // contribution get it; a type someone stored through the API has no `title` to publish.
359
- for (const shape of ['InCodeTypeDefinition', 'ContentObjectTypeCatalogEntry']) {
360
- expect(property(shape, 'title'), `${shape} should publish title`).toBeDefined();
361
- }
362
- for (const shape of ['ContentObjectTypeItem', 'ContentObjectType', 'CreateContentObjectTypePayload']) {
363
- expect(property(shape, 'title'), `${shape} should not publish title`).toBeUndefined();
364
- }
365
- });
366
-
367
- it('accepts an app-contributed type that carries a title', () => {
368
- // The regression: deployed app packages send `title`, the shape was strict and did not
369
- // declare it, so every `GET /projects/:projectId/app-types` failed its own response contract.
370
- expect(
371
- validateApiResponse('InCodeTypeDefinition', {
372
- id: 'invoice',
373
- name: 'invoice',
374
- title: 'Invoice',
375
- }).valid,
376
- ).toBe(true);
377
- });
378
- });