@tailor-platform/sdk 2.0.0-next.0 → 2.0.0-next.10

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 (497) hide show
  1. package/CHANGELOG.md +972 -0
  2. package/README.md +9 -9
  3. package/agent-skills/{tailor-sdk → tailor}/SKILL.md +3 -1
  4. package/dist/aigateway-DR4Kwuik.mjs +9 -0
  5. package/dist/aigateway-DR4Kwuik.mjs.map +1 -0
  6. package/dist/application-DArFTTJ9.mjs +3 -0
  7. package/dist/{application-76hhIhnJ.mjs → application-miwiXtB4.mjs} +1963 -1953
  8. package/dist/application-miwiXtB4.mjs.map +1 -0
  9. package/dist/{assert-CKfwrmCV.mjs → assert-DBxo8jPo.mjs} +1 -2
  10. package/dist/{assert-CKfwrmCV.mjs.map → assert-DBxo8jPo.mjs.map} +1 -1
  11. package/dist/authconnection-CZvi9ANm.mjs +9 -0
  12. package/dist/authconnection-CZvi9ANm.mjs.map +1 -0
  13. package/dist/{brand-DlnJ375c.mjs → brand-Eo4pLXPJ.mjs} +1 -2
  14. package/dist/brand-Eo4pLXPJ.mjs.map +1 -0
  15. package/dist/cli/cache/bundle-cache.d.mts +2 -0
  16. package/dist/cli/cache/store.d.mts +1 -0
  17. package/dist/cli/cache/types.d.mts +1 -0
  18. package/dist/cli/commands/api/api-call.d.mts +19 -0
  19. package/dist/cli/commands/api/index.d.mts +4 -0
  20. package/dist/cli/commands/deploy/aigateway.d.mts +5 -0
  21. package/dist/cli/commands/deploy/application.d.mts +7 -0
  22. package/dist/cli/commands/deploy/apply-phases.d.mts +14 -0
  23. package/dist/cli/commands/deploy/auth.d.mts +5 -0
  24. package/dist/cli/commands/deploy/deploy.d.mts +34 -0
  25. package/dist/cli/commands/deploy/executor.d.mts +7 -0
  26. package/dist/cli/commands/deploy/function-registry-types.d.mts +12 -0
  27. package/dist/cli/commands/deploy/function-registry.d.mts +7 -0
  28. package/dist/cli/commands/deploy/idp.d.mts +5 -0
  29. package/dist/cli/commands/deploy/resolver.d.mts +5 -0
  30. package/dist/cli/commands/deploy/secret-manager.d.mts +5 -0
  31. package/dist/cli/commands/deploy/staticwebsite.d.mts +5 -0
  32. package/dist/cli/commands/deploy/tailordb/index.d.mts +9 -0
  33. package/dist/cli/commands/deploy/types.d.mts +3 -0
  34. package/dist/cli/commands/deploy/workflow-execution-policy.d.mts +3 -0
  35. package/dist/cli/commands/deploy/workflow.d.mts +4 -0
  36. package/dist/cli/commands/executor/get.d.mts +28 -0
  37. package/dist/cli/commands/executor/jobs.d.mts +122 -0
  38. package/dist/cli/commands/executor/list.d.mts +18 -0
  39. package/dist/cli/commands/executor/transform.d.mts +42 -0
  40. package/dist/cli/commands/executor/trigger.d.mts +40 -0
  41. package/dist/cli/commands/executor/webhook.d.mts +21 -0
  42. package/dist/cli/commands/function/get.d.mts +17 -0
  43. package/dist/cli/commands/function/list.d.mts +21 -0
  44. package/dist/cli/commands/function/transform.d.mts +12 -0
  45. package/dist/cli/commands/generate/options.d.mts +6 -0
  46. package/dist/cli/commands/generate/seed/bundler.d.mts +26 -0
  47. package/dist/cli/commands/generate/service.d.mts +15 -0
  48. package/dist/cli/commands/machineuser/list.d.mts +26 -0
  49. package/dist/cli/commands/machineuser/token.d.mts +21 -0
  50. package/dist/cli/commands/oauth2client/get.d.mts +17 -0
  51. package/dist/cli/commands/oauth2client/list.d.mts +19 -0
  52. package/dist/cli/commands/oauth2client/transform.d.mts +21 -0
  53. package/dist/cli/commands/organization/folder/create.d.mts +17 -0
  54. package/dist/cli/commands/organization/folder/delete.d.mts +15 -0
  55. package/dist/cli/commands/organization/folder/get.d.mts +16 -0
  56. package/dist/cli/commands/organization/folder/list.d.mts +21 -0
  57. package/dist/cli/commands/organization/folder/update.d.mts +17 -0
  58. package/dist/cli/commands/organization/get.d.mts +15 -0
  59. package/dist/cli/commands/organization/list.d.mts +14 -0
  60. package/dist/cli/commands/organization/transform.d.mts +29 -0
  61. package/dist/cli/commands/organization/tree.d.mts +24 -0
  62. package/dist/cli/commands/organization/update.d.mts +16 -0
  63. package/dist/cli/commands/remove.d.mts +15 -0
  64. package/dist/cli/commands/show.d.mts +39 -0
  65. package/dist/cli/commands/staticwebsite/deploy.d.mts +19 -0
  66. package/dist/cli/commands/tailordb/migrate/bundler.d.mts +29 -0
  67. package/dist/cli/commands/tailordb/migrate/config.d.mts +18 -0
  68. package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +246 -0
  69. package/dist/cli/commands/tailordb/migrate/generate.d.mts +16 -0
  70. package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +208 -0
  71. package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +98 -0
  72. package/dist/cli/commands/tailordb/migrate/types.d.mts +7 -0
  73. package/dist/cli/commands/tailordb/truncate.d.mts +18 -0
  74. package/dist/cli/commands/workflow/executions.d.mts +74 -0
  75. package/dist/cli/commands/workflow/get.d.mts +30 -0
  76. package/dist/cli/commands/workflow/list.d.mts +18 -0
  77. package/dist/cli/commands/workflow/resume.d.mts +22 -0
  78. package/dist/cli/commands/workflow/start.d.mts +60 -0
  79. package/dist/cli/commands/workflow/status.d.mts +6 -0
  80. package/dist/cli/commands/workflow/transform.d.mts +34 -0
  81. package/dist/cli/commands/workflow/wait.d.mts +15 -0
  82. package/dist/cli/commands/workflow/waiter.d.mts +23 -0
  83. package/dist/cli/commands/workspace/app/health.d.mts +17 -0
  84. package/dist/cli/commands/workspace/app/list.d.mts +21 -0
  85. package/dist/cli/commands/workspace/app/transform.d.mts +20 -0
  86. package/dist/cli/commands/workspace/create.d.mts +27 -0
  87. package/dist/cli/commands/workspace/delete.d.mts +14 -0
  88. package/dist/cli/commands/workspace/get.d.mts +16 -0
  89. package/dist/cli/commands/workspace/list.d.mts +17 -0
  90. package/dist/cli/commands/workspace/restore.d.mts +14 -0
  91. package/dist/cli/commands/workspace/transform.d.mts +20 -0
  92. package/dist/cli/commands/workspace/user/invite.d.mts +21 -0
  93. package/dist/cli/commands/workspace/user/list.d.mts +21 -0
  94. package/dist/cli/commands/workspace/user/remove.d.mts +16 -0
  95. package/dist/cli/commands/workspace/user/transform.d.mts +9 -0
  96. package/dist/cli/commands/workspace/user/update.d.mts +21 -0
  97. package/dist/cli/index.mjs +12 -5534
  98. package/dist/cli/lib.d.mts +90 -21180
  99. package/dist/cli/lib.mjs +157 -16
  100. package/dist/cli/lib.mjs.map +1 -1
  101. package/dist/cli/main.d.mts +23 -0
  102. package/dist/cli/main.mjs +6583 -0
  103. package/dist/cli/main.mjs.map +1 -0
  104. package/dist/cli/query/index.d.mts +38 -0
  105. package/dist/cli/services/application.d.mts +12 -0
  106. package/dist/cli/services/auth/service.d.mts +3 -0
  107. package/dist/cli/services/executor/service.d.mts +1 -0
  108. package/dist/cli/services/http-adapter/bundler.d.mts +3 -0
  109. package/dist/cli/services/http-adapter/service.d.mts +2 -0
  110. package/dist/cli/services/resolver/service.d.mts +1 -0
  111. package/dist/cli/services/tailordb/service.d.mts +3 -0
  112. package/dist/cli/services/workflow/bundler.d.mts +2 -0
  113. package/dist/cli/services/workflow/service.d.mts +1 -0
  114. package/dist/cli/shared/args.d.mts +13 -0
  115. package/dist/cli/shared/client.d.mts +1273 -0
  116. package/dist/cli/shared/config-loader.d.mts +25 -0
  117. package/dist/cli/shared/context.d.mts +29 -0
  118. package/dist/cli/shared/error-json.d.mts +23 -0
  119. package/dist/cli/shared/readonly-guard.d.mts +25 -0
  120. package/dist/cli/shared/script-executor.d.mts +77 -0
  121. package/dist/cli/shared/seed-chunker.d.mts +45 -0
  122. package/dist/cli/shared/seed-context.d.mts +49 -0
  123. package/dist/cli/shared/tailordb-namespaces.d.mts +40 -0
  124. package/dist/cli/shared/type-generator.d.mts +19 -0
  125. package/dist/cli/shared/workspace-name.d.mts +1 -0
  126. package/dist/cli/ts-hook.d.mts +4 -0
  127. package/dist/cli/ts-hook.mjs +333 -0
  128. package/dist/completion/zsh-worker.zsh +4223 -0
  129. package/dist/configure/config/index.d.mts +20 -0
  130. package/dist/configure/config/types.d.mts +111 -0
  131. package/dist/configure/index.d.mts +135 -7
  132. package/dist/configure/index.mjs +409 -56
  133. package/dist/configure/index.mjs.map +1 -1
  134. package/dist/configure/services/aigateway/index.d.mts +16 -0
  135. package/dist/configure/services/aigateway/types.d.mts +10 -0
  136. package/dist/configure/services/auth/index.d.mts +33 -0
  137. package/dist/configure/services/auth/types.d.mts +168 -0
  138. package/dist/configure/services/executor/executor.d.mts +70 -0
  139. package/dist/configure/services/executor/index.d.mts +9 -0
  140. package/dist/configure/services/executor/operation.d.mts +50 -0
  141. package/dist/configure/services/executor/trigger/event.d.mts +271 -0
  142. package/dist/configure/services/executor/trigger/index.d.mts +7 -0
  143. package/dist/configure/services/executor/trigger/schedule.d.mts +24 -0
  144. package/dist/configure/services/executor/trigger/webhook.d.mts +43 -0
  145. package/dist/configure/services/executor/types.d.mts +2 -0
  146. package/dist/configure/services/http-adapter/http-adapter.d.mts +124 -0
  147. package/dist/configure/services/http-adapter/index.d.mts +2 -0
  148. package/dist/configure/services/idp/index.d.mts +60 -0
  149. package/dist/configure/services/idp/permission.d.mts +64 -0
  150. package/dist/configure/services/idp/types.d.mts +23 -0
  151. package/dist/configure/services/index.d.mts +40 -0
  152. package/dist/configure/services/resolver/index.d.mts +6 -0
  153. package/dist/configure/services/resolver/permission.d.mts +64 -0
  154. package/dist/configure/services/resolver/resolver.d.mts +88 -0
  155. package/dist/configure/services/resolver/types.d.mts +5 -0
  156. package/dist/configure/services/secrets/index.d.mts +37 -0
  157. package/dist/configure/services/secrets/types.d.mts +10 -0
  158. package/dist/configure/services/staticwebsite/index.d.mts +18 -0
  159. package/dist/configure/services/staticwebsite/types.d.mts +10 -0
  160. package/dist/configure/services/tailordb/index.d.mts +4 -0
  161. package/dist/configure/services/tailordb/permission.d.mts +103 -0
  162. package/dist/configure/services/tailordb/schema.d.mts +486 -0
  163. package/dist/configure/services/tailordb/types.d.mts +198 -0
  164. package/dist/configure/services/workflow/execution-policy.d.mts +70 -0
  165. package/dist/configure/services/workflow/execution-policy.types.d.mts +103 -0
  166. package/dist/configure/services/workflow/index.d.mts +9 -0
  167. package/dist/configure/services/workflow/job.d.mts +83 -0
  168. package/dist/configure/services/workflow/types.d.mts +2 -0
  169. package/dist/configure/services/workflow/wait-point.d.mts +72 -0
  170. package/dist/configure/services/workflow/workflow.d.mts +56 -0
  171. package/dist/configure/types/aigateway-name.d.mts +12 -0
  172. package/dist/configure/types/connection-name.d.mts +12 -0
  173. package/dist/configure/types/field.d.mts +8 -0
  174. package/dist/configure/types/field.types.d.mts +70 -0
  175. package/dist/configure/types/idp-name.d.mts +12 -0
  176. package/dist/configure/types/index.d.mts +5 -0
  177. package/dist/configure/types/machine-user.d.mts +2 -0
  178. package/dist/configure/types/permission-operand.types.d.mts +20 -0
  179. package/dist/configure/types/type.d.mts +73 -0
  180. package/dist/{context-s0lxhu8_.mjs → context-DYQVYWqZ.mjs} +4 -6
  181. package/dist/context-DYQVYWqZ.mjs.map +1 -0
  182. package/dist/{crashreport-BhD0y14F.mjs → crashreport-B5LqCTfF.mjs} +25 -17
  183. package/dist/{crashreport-BhD0y14F.mjs.map → crashreport-B5LqCTfF.mjs.map} +1 -1
  184. package/dist/{crashreport-D1wKBJ8N.mjs → crashreport-eI7ty7ok.mjs} +1 -2
  185. package/dist/{enum-constants-C7DaWeQo.mjs → enum-constants-j9QBF0cB.mjs} +1 -2
  186. package/dist/enum-constants-j9QBF0cB.mjs.map +1 -0
  187. package/dist/{errors-EsY4XO6O.mjs → errors-D7583Zz7.mjs} +18 -3
  188. package/dist/errors-D7583Zz7.mjs.map +1 -0
  189. package/dist/{file-B58Dm-2P.mjs → file-BUcmVIH2.mjs} +12 -23
  190. package/dist/file-BUcmVIH2.mjs.map +1 -0
  191. package/dist/{file-utils-BHPxPXmn.mjs → file-utils-yEiIS4nJ.mjs} +7 -8
  192. package/dist/file-utils-yEiIS4nJ.mjs.map +1 -0
  193. package/dist/{globals-ByrCoDip.mjs → globals-DQotNuwK.mjs} +32 -6
  194. package/dist/globals-DQotNuwK.mjs.map +1 -0
  195. package/dist/iconv-QWaZh0TT.mjs +38 -0
  196. package/dist/iconv-QWaZh0TT.mjs.map +1 -0
  197. package/dist/{idp-Ch95ag8h.mjs → idp-RA_swu-h.mjs} +12 -6
  198. package/dist/idp-RA_swu-h.mjs.map +1 -0
  199. package/dist/{interceptor-DOqRkCya.mjs → interceptor-e33JtsC-.mjs} +2 -3
  200. package/dist/interceptor-e33JtsC-.mjs.map +1 -0
  201. package/dist/kysely/index.d.mts +5 -7
  202. package/dist/kysely/index.mjs +0 -1
  203. package/dist/kysely/index.mjs.map +1 -1
  204. package/dist/{kysely-type-D1e0Vwkd.mjs → kysely-type-DqIRgDYR.mjs} +6 -6
  205. package/dist/kysely-type-DqIRgDYR.mjs.map +1 -0
  206. package/dist/logger-BtX0suGY.mjs +48 -0
  207. package/dist/logger-BtX0suGY.mjs.map +1 -0
  208. package/dist/logger-CXQq9YIp.mjs +317 -0
  209. package/dist/logger-CXQq9YIp.mjs.map +1 -0
  210. package/dist/{multiline-Cf9ODpr1.mjs → multiline-sfHpTZZK.mjs} +1 -2
  211. package/dist/{multiline-Cf9ODpr1.mjs.map → multiline-sfHpTZZK.mjs.map} +1 -1
  212. package/dist/{package-json-DcQApfPQ.mjs → package-json-8b0O9TlX.mjs} +1 -2
  213. package/dist/{package-json-DcQApfPQ.mjs.map → package-json-8b0O9TlX.mjs.map} +1 -1
  214. package/dist/package-json-Cv2Z-TqQ.mjs +3 -0
  215. package/dist/parser/service/auth/index.d.mts +1 -0
  216. package/dist/parser/service/auth/schema.d.mts +3 -0
  217. package/dist/parser/service/http-adapter/index.d.mts +1 -0
  218. package/dist/parser/service/http-adapter/schema.d.mts +1 -0
  219. package/dist/parser/service/idp/types.d.mts +5 -0
  220. package/dist/parser/service/tailordb/type-source.d.mts +10 -0
  221. package/dist/parser/service/tailordb/types.d.mts +131 -0
  222. package/dist/platform-serialize-RoRtBS0v.mjs +46 -0
  223. package/dist/platform-serialize-RoRtBS0v.mjs.map +1 -0
  224. package/dist/plugin/builtin/enum-constants/index.d.mts +15 -1
  225. package/dist/plugin/builtin/enum-constants/index.mjs +1 -2
  226. package/dist/plugin/builtin/file-utils/index.d.mts +15 -1
  227. package/dist/plugin/builtin/file-utils/index.mjs +1 -2
  228. package/dist/plugin/builtin/kysely-type/index.d.mts +15 -1
  229. package/dist/plugin/builtin/kysely-type/index.mjs +1 -2
  230. package/dist/plugin/builtin/seed/index.d.mts +46 -2
  231. package/dist/plugin/builtin/seed/index.mjs +1 -2
  232. package/dist/plugin/builtin/seed/seed-type-processor.d.mts +19 -0
  233. package/dist/plugin/builtin/seed/types.d.mts +2 -0
  234. package/dist/plugin/get-generated-type.d.mts +16 -0
  235. package/dist/plugin/index.d.mts +3 -119
  236. package/dist/plugin/index.mjs +1 -2
  237. package/dist/plugin/index.mjs.map +1 -1
  238. package/dist/plugin/manager.d.mts +2 -0
  239. package/dist/plugin/types.d.mts +242 -0
  240. package/dist/plugin/with-context.d.mts +101 -0
  241. package/dist/{runtime-C7qTBDD2.mjs → register-ts-hook-BAHMwxfG.mjs} +12374 -8672
  242. package/dist/register-ts-hook-BAHMwxfG.mjs.map +1 -0
  243. package/dist/registry-BIGVUrMB.mjs +54 -0
  244. package/dist/registry-BIGVUrMB.mjs.map +1 -0
  245. package/dist/{repl-editor-CJG3sz7A.mjs → repl-editor-BCozyiNq.mjs} +7 -7
  246. package/dist/{repl-editor-CJG3sz7A.mjs.map → repl-editor-BCozyiNq.mjs.map} +1 -1
  247. package/dist/runtime/aigateway.d.mts +25 -0
  248. package/dist/runtime/aigateway.mjs +3 -0
  249. package/dist/runtime/authconnection.d.mts +21 -2
  250. package/dist/runtime/authconnection.mjs +2 -3
  251. package/dist/runtime/context.d.mts +54 -2
  252. package/dist/runtime/context.mjs +2 -3
  253. package/dist/runtime/field-parse.d.mts +10 -0
  254. package/dist/runtime/file.d.mts +170 -2
  255. package/dist/runtime/file.mjs +2 -3
  256. package/dist/runtime/globals.d.mts +38 -53
  257. package/dist/runtime/globals.mjs +0 -1
  258. package/dist/runtime/iconv.d.mts +73 -2
  259. package/dist/runtime/iconv.mjs +2 -3
  260. package/dist/runtime/idp.d.mts +129 -2
  261. package/dist/runtime/idp.mjs +2 -3
  262. package/dist/runtime/index.d.mts +48 -9
  263. package/dist/runtime/index.mjs +10 -9
  264. package/dist/runtime/logger.d.mts +98 -0
  265. package/dist/runtime/logger.mjs +3 -0
  266. package/dist/runtime/secretmanager.d.mts +41 -2
  267. package/dist/runtime/secretmanager.mjs +2 -3
  268. package/dist/runtime/types.d.mts +25 -0
  269. package/dist/runtime/workflow.d.mts +124 -2
  270. package/dist/runtime/workflow.mjs +2 -3
  271. package/dist/{schema-1msIhXwA.mjs → schema--xYWRGfe.mjs} +289 -231
  272. package/dist/schema--xYWRGfe.mjs.map +1 -0
  273. package/dist/{secret-file-CWzF8rry.mjs → secret-file-C3J4Gy8r.mjs} +2 -3
  274. package/dist/{secret-file-CWzF8rry.mjs.map → secret-file-C3J4Gy8r.mjs.map} +1 -1
  275. package/dist/secretmanager-CYlpffsz.mjs +13 -0
  276. package/dist/secretmanager-CYlpffsz.mjs.map +1 -0
  277. package/dist/secretmanager-IY4UvinW.mjs +131 -0
  278. package/dist/secretmanager-IY4UvinW.mjs.map +1 -0
  279. package/dist/seed/index.d.mts +4 -4
  280. package/dist/seed/index.mjs +0 -1
  281. package/dist/seed/index.mjs.map +1 -1
  282. package/dist/seed-LUVr7jHL.mjs +444 -0
  283. package/dist/seed-LUVr7jHL.mjs.map +1 -0
  284. package/dist/{service-DMohAx8a2.mjs → service-B5WynBHQ.mjs} +3 -4
  285. package/dist/service-B5WynBHQ.mjs.map +1 -0
  286. package/dist/service-BNtPsK9Q.mjs +837 -0
  287. package/dist/service-BNtPsK9Q.mjs.map +1 -0
  288. package/dist/service-D5jn05ZI.mjs +3 -0
  289. package/dist/service_pb-BwZRiNug.mjs +167 -0
  290. package/dist/service_pb-BwZRiNug.mjs.map +1 -0
  291. package/dist/service_pb-wRkxUta6.mjs +3 -0
  292. package/dist/tailor-proto/src/tailor/v1/aigateway_pb.d.mts +203 -0
  293. package/dist/tailor-proto/src/tailor/v1/aigateway_resource_pb.d.mts +57 -0
  294. package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +315 -0
  295. package/dist/tailor-proto/src/tailor/v1/application_resource_pb.d.mts +160 -0
  296. package/dist/tailor-proto/src/tailor/v1/auth_pb.d.mts +2069 -0
  297. package/dist/tailor-proto/src/tailor/v1/auth_resource_pb.d.mts +865 -0
  298. package/dist/tailor-proto/src/tailor/v1/events_pb.d.mts +111 -0
  299. package/dist/tailor-proto/src/tailor/v1/events_resource_pb.d.mts +68 -0
  300. package/dist/tailor-proto/src/tailor/v1/executor_pb.d.mts +438 -0
  301. package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +563 -0
  302. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +144 -0
  303. package/dist/tailor-proto/src/tailor/v1/function_registry_pb.d.mts +450 -0
  304. package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +191 -0
  305. package/dist/tailor-proto/src/tailor/v1/http_adapter_resource_pb.d.mts +49 -0
  306. package/dist/tailor-proto/src/tailor/v1/idp_pb.d.mts +406 -0
  307. package/dist/tailor-proto/src/tailor/v1/idp_resource_pb.d.mts +429 -0
  308. package/dist/tailor-proto/src/tailor/v1/metadata_pb.d.mts +72 -0
  309. package/dist/tailor-proto/src/tailor/v1/metadata_resource_pb.d.mts +16 -0
  310. package/dist/tailor-proto/src/tailor/v1/meter_pb.d.mts +308 -0
  311. package/dist/tailor-proto/src/tailor/v1/pipeline_pb.d.mts +590 -0
  312. package/dist/tailor-proto/src/tailor/v1/pipeline_resource_pb.d.mts +329 -0
  313. package/dist/tailor-proto/src/tailor/v1/resource_pb.d.mts +112 -0
  314. package/dist/tailor-proto/src/tailor/v1/secret_manager_pb.d.mts +345 -0
  315. package/dist/tailor-proto/src/tailor/v1/secret_manager_resource_pb.d.mts +53 -0
  316. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +3575 -0
  317. package/dist/tailor-proto/src/tailor/v1/stateflow_pb.d.mts +186 -0
  318. package/dist/tailor-proto/src/tailor/v1/stateflow_resource_pb.d.mts +28 -0
  319. package/dist/tailor-proto/src/tailor/v1/staticwebsite_pb.d.mts +428 -0
  320. package/dist/tailor-proto/src/tailor/v1/staticwebsite_resource_pb.d.mts +89 -0
  321. package/dist/tailor-proto/src/tailor/v1/tailordb_pb.d.mts +683 -0
  322. package/dist/tailor-proto/src/tailor/v1/tailordb_resource_pb.d.mts +796 -0
  323. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_pb.d.mts +329 -0
  324. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +182 -0
  325. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +861 -0
  326. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +309 -0
  327. package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +2014 -0
  328. package/dist/tailor-proto/src/tailor/v1/workspace_resource_pb.d.mts +482 -0
  329. package/dist/{telemetry-BQbbVo2t.mjs → telemetry-BRVdwh14.mjs} +4 -5
  330. package/dist/telemetry-BRVdwh14.mjs.map +1 -0
  331. package/dist/telemetry-CkbkeJxl.mjs +3 -0
  332. package/dist/test-env-key-D7UkZp99.mjs +75 -0
  333. package/dist/test-env-key-D7UkZp99.mjs.map +1 -0
  334. package/dist/type-source-DH_LH20p.mjs +13 -0
  335. package/dist/type-source-DH_LH20p.mjs.map +1 -0
  336. package/dist/types/aigateway.generated.d.mts +12 -0
  337. package/dist/types/app-config.generated.d.mts +4 -0
  338. package/dist/types/auth-connection.generated.d.mts +33 -0
  339. package/dist/types/auth.generated.d.mts +188 -0
  340. package/dist/types/executor.generated.d.mts +209 -0
  341. package/dist/types/helpers.d.mts +40 -0
  342. package/dist/types/http-adapter.generated.d.mts +28 -0
  343. package/dist/types/idp.generated.d.mts +626 -0
  344. package/dist/types/resolver.generated.d.mts +82 -0
  345. package/dist/types/secrets.generated.d.mts +14 -0
  346. package/dist/types/staticwebsite.generated.d.mts +14 -0
  347. package/dist/types/tailordb.generated.d.mts +468 -0
  348. package/dist/types/workflow.generated.d.mts +17 -0
  349. package/dist/user-agent-Bgsszb5I.mjs +28 -0
  350. package/dist/user-agent-Bgsszb5I.mjs.map +1 -0
  351. package/dist/utils/test/index.d.mts +6 -99
  352. package/dist/utils/test/index.mjs +60 -40
  353. package/dist/utils/test/index.mjs.map +1 -1
  354. package/dist/utils/test/mock.d.mts +86 -0
  355. package/dist/vitest/environment.d.mts +1 -2
  356. package/dist/vitest/environment.mjs +2 -3
  357. package/dist/vitest/environment.mjs.map +1 -1
  358. package/dist/vitest/index.d.mts +15 -392
  359. package/dist/vitest/index.mjs +1347 -9
  360. package/dist/vitest/index.mjs.map +1 -1
  361. package/dist/vitest/mock-kysely.d.mts +61 -0
  362. package/dist/vitest/mock.d.mts +10 -0
  363. package/dist/vitest/mocks/aigateway.d.mts +40 -0
  364. package/dist/vitest/mocks/authconnection.d.mts +38 -0
  365. package/dist/vitest/mocks/file.d.mts +58 -0
  366. package/dist/vitest/mocks/iconv.d.mts +51 -0
  367. package/dist/vitest/mocks/idp.d.mts +60 -0
  368. package/dist/vitest/mocks/logger.d.mts +45 -0
  369. package/dist/vitest/mocks/secretmanager.d.mts +44 -0
  370. package/dist/vitest/mocks/tailordb.d.mts +115 -0
  371. package/dist/vitest/mocks/workflow.d.mts +157 -0
  372. package/dist/vitest/setup.d.mts +1 -2
  373. package/dist/vitest/setup.mjs +2 -3
  374. package/dist/vitest/setup.mjs.map +1 -1
  375. package/dist/vitest/workflow-local.d.mts +41 -0
  376. package/dist/workflow-CsaQ9qK-.mjs +42 -0
  377. package/dist/workflow-CsaQ9qK-.mjs.map +1 -0
  378. package/dist/{client-CobIRHl-.mjs → workspace_resource_pb-UGK1SSn_.mjs} +55 -616
  379. package/dist/workspace_resource_pb-UGK1SSn_.mjs.map +1 -0
  380. package/docs/cli/application.md +150 -252
  381. package/docs/cli/auth.md +51 -295
  382. package/docs/cli/completion.md +4 -25
  383. package/docs/cli/crashreport.md +3 -63
  384. package/docs/cli/executor.md +72 -183
  385. package/docs/cli/function.md +17 -133
  386. package/docs/cli/organization.md +11 -221
  387. package/docs/cli/plugin.md +29 -0
  388. package/docs/cli/query.md +2 -22
  389. package/docs/cli/secret.md +71 -251
  390. package/docs/cli/setup.md +138 -40
  391. package/docs/cli/skills.md +50 -39
  392. package/docs/cli/staticwebsite.md +32 -180
  393. package/docs/cli/tailordb.md +71 -427
  394. package/docs/cli/upgrade.md +2 -22
  395. package/docs/cli/user.md +78 -247
  396. package/docs/cli/workflow.md +150 -172
  397. package/docs/cli/workspace.md +167 -538
  398. package/docs/cli-reference.md +213 -96
  399. package/docs/configuration.md +40 -8
  400. package/docs/github-actions.md +72 -24
  401. package/docs/migration/v2.md +1316 -0
  402. package/docs/multi-environment.md +29 -7
  403. package/docs/plugin/custom.md +6 -6
  404. package/docs/plugin/index.md +9 -9
  405. package/docs/quickstart.md +8 -7
  406. package/docs/runtime.md +21 -12
  407. package/docs/services/aigateway.md +115 -0
  408. package/docs/services/auth.md +70 -61
  409. package/docs/services/executor.md +8 -5
  410. package/docs/services/http-adapter.md +16 -1
  411. package/docs/services/idp.md +55 -2
  412. package/docs/services/resolver.md +63 -11
  413. package/docs/services/secret.md +11 -11
  414. package/docs/services/staticwebsite.md +8 -2
  415. package/docs/services/tailordb-migration.md +43 -28
  416. package/docs/services/tailordb.md +200 -99
  417. package/docs/services/workflow.md +135 -59
  418. package/docs/testing.md +253 -145
  419. package/package.json +61 -47
  420. package/postinstall.mjs +4 -6
  421. package/dist/actor-J2gJ0eK5.d.mts +0 -24
  422. package/dist/application-76hhIhnJ.mjs.map +0 -1
  423. package/dist/application-av2raLs6.mjs +0 -4
  424. package/dist/authconnection-BIYzEh2p.d.mts +0 -39
  425. package/dist/authconnection-D8SJGMpj.mjs +0 -16
  426. package/dist/authconnection-D8SJGMpj.mjs.map +0 -1
  427. package/dist/brand-DlnJ375c.mjs.map +0 -1
  428. package/dist/chunk-BkoGK1jX.mjs +0 -21
  429. package/dist/cli/erd-viewer-assets/app.js +0 -1181
  430. package/dist/cli/erd-viewer-assets/index.html +0 -73
  431. package/dist/cli/erd-viewer-assets/serve.json +0 -13
  432. package/dist/cli/erd-viewer-assets/styles.css +0 -789
  433. package/dist/cli/index.d.mts +0 -5
  434. package/dist/cli/index.mjs.map +0 -1
  435. package/dist/cli/skills.d.mts +0 -1
  436. package/dist/cli/skills.mjs +0 -22
  437. package/dist/cli/skills.mjs.map +0 -1
  438. package/dist/client-C68VWo4g.mjs +0 -4
  439. package/dist/client-CobIRHl-.mjs.map +0 -1
  440. package/dist/context-CUBwSBq4.d.mts +0 -68
  441. package/dist/context-s0lxhu8_.mjs.map +0 -1
  442. package/dist/enum-constants-C7DaWeQo.mjs.map +0 -1
  443. package/dist/env-B-g-qgE4.d.mts +0 -7
  444. package/dist/errors-EsY4XO6O.mjs.map +0 -1
  445. package/dist/field-C4zdJLW5.mjs +0 -23
  446. package/dist/field-C4zdJLW5.mjs.map +0 -1
  447. package/dist/file-B58Dm-2P.mjs.map +0 -1
  448. package/dist/file-BzK8z3X-.d.mts +0 -250
  449. package/dist/file-utils-BHPxPXmn.mjs.map +0 -1
  450. package/dist/globals-ByrCoDip.mjs.map +0 -1
  451. package/dist/iconv-DreIffeM.mjs +0 -64
  452. package/dist/iconv-DreIffeM.mjs.map +0 -1
  453. package/dist/iconv-kwrmd1U_.d.mts +0 -122
  454. package/dist/idp-BlBPtXJ-.d.mts +0 -160
  455. package/dist/idp-Ch95ag8h.mjs.map +0 -1
  456. package/dist/index-CLxubakC.d.mts +0 -1225
  457. package/dist/index-CPRnOjjt.d.mts +0 -18
  458. package/dist/index-CQZVJ5SX.d.mts +0 -18
  459. package/dist/index-CfRFkXIO.d.mts +0 -47
  460. package/dist/index-DRhMpdnA.d.mts +0 -46
  461. package/dist/index-DUupuPhZ.d.mts +0 -18
  462. package/dist/interceptor-DOqRkCya.mjs.map +0 -1
  463. package/dist/job-BpsFXPbi.mjs +0 -54
  464. package/dist/job-BpsFXPbi.mjs.map +0 -1
  465. package/dist/kysely-type-D1e0Vwkd.mjs.map +0 -1
  466. package/dist/logger-DpJyJvNz.mjs +0 -221
  467. package/dist/logger-DpJyJvNz.mjs.map +0 -1
  468. package/dist/mock-DMgIygjE.mjs +0 -806
  469. package/dist/mock-DMgIygjE.mjs.map +0 -1
  470. package/dist/package-json-wzO6nV9O.mjs +0 -4
  471. package/dist/plugin-C_FyVSdl.d.mts +0 -634
  472. package/dist/registry-D0uB0OrK.mjs +0 -178
  473. package/dist/registry-D0uB0OrK.mjs.map +0 -1
  474. package/dist/runtime-C7qTBDD2.mjs.map +0 -1
  475. package/dist/schema-1msIhXwA.mjs.map +0 -1
  476. package/dist/secretmanager-B9h-U_8U.mjs +0 -25
  477. package/dist/secretmanager-B9h-U_8U.mjs.map +0 -1
  478. package/dist/secretmanager-CKLB3wAQ.d.mts +0 -55
  479. package/dist/seed-BH2FbrPV.mjs +0 -1171
  480. package/dist/seed-BH2FbrPV.mjs.map +0 -1
  481. package/dist/service-BHQIerYh.mjs +0 -4
  482. package/dist/service-DMohAx8a2.mjs.map +0 -1
  483. package/dist/service-wI3Hvrgx.mjs +0 -460
  484. package/dist/service-wI3Hvrgx.mjs.map +0 -1
  485. package/dist/tailordb-BlBGmQK-.d.mts +0 -863
  486. package/dist/telemetry-BQbbVo2t.mjs.map +0 -1
  487. package/dist/telemetry-w92bvGdC.mjs +0 -4
  488. package/dist/types-2Be3wSMc.mjs +0 -5
  489. package/dist/types-CmzfQP_m.mjs +0 -372
  490. package/dist/types-CmzfQP_m.mjs.map +0 -1
  491. package/dist/workflow--aPbA8Uq.mjs +0 -39
  492. package/dist/workflow--aPbA8Uq.mjs.map +0 -1
  493. package/dist/workflow-CMamswkK.d.mts +0 -96
  494. package/dist/workflow.generated-Bf1tWylx.d.mts +0 -1416
  495. package/docs/generator/builtin.md +0 -257
  496. package/docs/generator/custom.md +0 -147
  497. package/docs/generator/index.md +0 -66
package/docs/testing.md CHANGED
@@ -11,19 +11,22 @@ Lean on unit tests for the day-to-day feedback loop — they run fast and exerci
11
11
 
12
12
  Unit-test entrypoints exposed by the SDK:
13
13
 
14
- - `resolver.body({ input, user, env })` — invoke a resolver
15
- - `workflowJob.body(input, { env })` / `workflowJob.trigger(input)` — invoke or chain a workflow job
16
- - `executor.operation.body(args)` — invoke a function-kind executor
14
+ - `resolver.body({ input, caller, invoker, env })` — invoke a resolver
15
+ - `workflowJob.body(input, { env, invoker })` — invoke a workflow job body directly
16
+ - `workflowJob.start(input)` — chain a workflow job through the workflow runtime
17
+ - `runWorkflowLocally(workflow, args)` — run a workflow chain locally with real job bodies
18
+ - `executor.operation.body({ ...args, invoker })` — invoke a function-kind executor
17
19
 
18
- Helpers under `@tailor-platform/sdk/test`:
20
+ For anonymous direct calls:
19
21
 
20
- - `unauthenticatedTailorUser` default `user` value for resolver contexts
22
+ - Pass `null` for anonymous `caller` / `invoker` context in direct unit tests.
21
23
 
22
24
  Platform API mocks under `@tailor-platform/sdk/vitest` (for use with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta) below):
23
25
 
24
26
  - `mockTailordb` — TailorDB query stubs and call recording
25
27
  - `mockWorkflow` — `tailor.workflow` job / wait / resolve mocks
26
- - `mockSecretmanager`, `mockAuthconnection`, `mockIdp`, `mockFile`, `mockIconv` corresponding platform API mocks
28
+ - `runWorkflowLocally` — local full-chain workflow runner
29
+ - `mockSecretmanager`, `mockAuthconnection`, `mockIdp`, `mockFile`, `mockIconv`, `mockAigateway`, `mockLogger` — corresponding platform API mocks
27
30
 
28
31
  For tighter alignment with the production runtime — Node.js module blocking, Web-only globals, and platform API mocks — pair the resolver helpers with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta) below.
29
32
 
@@ -60,25 +63,30 @@ export default defineConfig({
60
63
 
61
64
  ### Acquiring mocks with `using`
62
65
 
63
- Each mock controller (`mockTailordb`, `mockWorkflow`, `mockSecretmanager`, `mockAuthconnection`, `mockIdp`, `mockFile`, `mockIconv`) is a **factory function**. Acquire it inside a test with a [`using` declaration](https://github.com/tc39/proposal-explicit-resource-management) — its state is reset automatically when the test scope exits, so you no longer need `beforeEach(() => mock.reset())`:
66
+ Each mock controller (`mockTailordb`, `mockWorkflow`, `mockSecretmanager`, `mockAuthconnection`, `mockIdp`, `mockFile`, `mockIconv`, `mockAigateway`, `mockLogger`) is a **factory function**. Acquire it inside a test with a [`using` declaration](https://github.com/tc39/proposal-explicit-resource-management) — its state is reset automatically when the test scope exits, so you no longer need `beforeEach(() => mock.reset())`:
64
67
 
65
68
  ```typescript
66
69
  import { mockTailordb } from "@tailor-platform/sdk/vitest";
67
70
 
68
71
  test("...", () => {
69
72
  using db = mockTailordb();
70
- db.enqueueResult({ age: 30 });
73
+ db.onQuery(/SELECT age/).returnsRows([{ age: 30 }]);
71
74
  // …
72
75
  }); // reset automatically here
73
76
  ```
74
77
 
75
- The mock functions are also exposed directly (e.g. `db.queryObject`, `wf.triggerJobFunction`) so you can assert on them with `expect(...).toHaveBeenCalledWith(...)`.
78
+ Runtime operations are exposed as typed Vitest mocks wherever the platform API has a stable operation shape. For example, use `file.download.mockResolvedValue(...)`, `iconv.decode.mockReturnValue(...)`, or `wf.job(myJob).mockResolvedValue(...)`, then assert with native Vitest matchers. Service-specific helpers cover stateful fixtures and query matching.
79
+
80
+ Every controller provides two lifecycle methods when manual reuse is useful:
81
+
82
+ - `clear()` removes call history but preserves configured behavior.
83
+ - `reset()` removes call history and configured behavior, restoring the controller's default behavior.
76
84
 
77
85
  > **Requirements:** `using` requires TypeScript ≥ 5.2 and a runtime that provides `Symbol.dispose` (Node ≥ 20.4 — the SDK already targets Node ≥ 22, and Vitest's transformer downlevels the syntax for you).
78
86
  >
79
87
  > **Acquire what you use:** a namespace is only mocked while you hold it with `using`, so code under test that calls a platform API (e.g. `tailor.workflow`, `tailordb.Client`) must run inside a test that has acquired the matching `mockX()`. The error classes and `tailor.context` are always present.
80
88
  >
81
- > **Seeded secrets survive:** secrets seeded from `tailor.config.ts` stay available across tests; a per-test `mockSecretmanager().setSecrets(...)` override applies only within that test.
89
+ > **Seeded secrets survive:** secrets seeded from `tailor.config.ts` stay available across tests; per-test fixtures passed to `mockSecretmanager({ secrets: ... })` apply only within that test.
82
90
 
83
91
  ### TailorDB Mock
84
92
 
@@ -89,14 +97,19 @@ import { mockTailordb } from "@tailor-platform/sdk/vitest";
89
97
 
90
98
  test("resolver queries the database", async () => {
91
99
  using db = mockTailordb();
92
- // Order-based: stage rows for each upcoming query in one call
93
- db.enqueueResults(
100
+ // Use an explicit queue when transaction order is part of the test.
101
+ db.enqueueRows(
94
102
  [], // BEGIN (empty result)
95
103
  [{ age: 30 }], // SELECT (one row)
96
104
  [], // COMMIT
97
105
  );
98
106
 
99
- const result = await resolver.body({ input: { email: "test@example.com" } });
107
+ const result = await resolver.body({
108
+ input: { email: "test@example.com" },
109
+ caller: null,
110
+ invoker: null,
111
+ env: {},
112
+ });
100
113
 
101
114
  expect(result).toEqual({ oldAge: 30, newAge: 31 });
102
115
  expect(db.executedQueries).toHaveLength(3);
@@ -104,75 +117,85 @@ test("resolver queries the database", async () => {
104
117
  });
105
118
  ```
106
119
 
107
- Three response modes:
108
-
109
- - **`enqueueResult(...rows)`** — Order-based, single query. Arguments are the row objects returned by the next `queryObject` call (`enqueueResult()` for empty, `enqueueResult({ id: "1" })` for one row, `enqueueResult({ a: 1 }, { a: 2 })` for multiple rows). Consumed in FIFO order.
110
- - **`enqueueResults(...rowsArrays)`** — Order-based, multiple queries. Each argument is a rows array for one upcoming query. Equivalent to calling `enqueueResult` for each entry but easier to read for transactional sequences.
111
- - **`setQueryResolver((query, params) => rows)`** — Content-based fallback. Called when the queue is empty.
120
+ Match queries by SQL text, a regular expression, SQL plus parameters, or a predicate. The most recently registered matcher wins:
112
121
 
113
122
  ```typescript
114
123
  test("content-based mock", async () => {
115
124
  using db = mockTailordb();
116
- db.setQueryResolver((query) => {
117
- if (query.includes("SELECT")) return [{ id: "1", name: "test" }];
118
- return [];
125
+ db.onQuery({ sql: /FROM users/i, params: ["1"] }).returnsRows([{ id: "1", name: "test" }]);
126
+ db.onQuery(/FROM audit_logs/i)
127
+ .returnsRowsOnce([{ id: "first" }])
128
+ .returnsRows([{ id: "later" }]);
129
+
130
+ const result = await resolver.body({
131
+ input: { userId: "1" },
132
+ caller: null,
133
+ invoker: null,
134
+ env: {},
119
135
  });
120
136
 
121
- const result = await resolver.body({ input: { userId: "1" } });
122
-
123
137
  expect(db.executedQueries[0].query).toContain("SELECT");
124
138
  });
125
139
  ```
126
140
 
141
+ Within one `mockTailordb()` instance, use either `onQuery()` matchers or a direct `queryObject.mockImplementation()` override. A direct override replaces matcher-based behavior, so do not combine the two styles.
142
+
143
+ `returnsRowsOnce` and `rejectsOnce` configure one-time responses before the persistent `returnsRows` or `rejects` response. `enqueueRows(...rowArrays)` remains available for transaction sequences whose exact call order is under test. The existing `enqueueResult`, `enqueueResults`, and `setQueryResolver` helpers remain supported for compatibility.
144
+
145
+ Pass `{ onUnhandled: "error" }` to make an unmatched query fail instead of returning an empty result.
146
+
127
147
  ### Workflow Mock
128
148
 
129
- `.trigger()` runs the real job bodies locally out of the box (see [Running a full workflow locally](#running-a-full-workflow-locally)). Acquire `mockWorkflow()` when you want to override responses with `setJobHandler` / `enqueueResult` or assert on `triggeredJobs`:
149
+ Workflow job `.start()` calls use the platform workflow runtime. Acquire `mockWorkflow()` when you want to provide start responses with `setJobHandler` / `enqueueResult` or assert on `startedJobs`. If no response is configured, the mock throws so missing job mocks fail loudly. Use `job(definition)` or `workflow(definition)` to get a stable, fully typed Vitest mock for one definition:
130
150
 
131
151
  ```typescript
132
152
  import { mockWorkflow } from "@tailor-platform/sdk/vitest";
153
+ import { processPayment, validateOrder } from "./jobs";
133
154
 
134
- test("workflow triggers jobs", async () => {
155
+ test("workflow starts jobs", async () => {
135
156
  using wf = mockWorkflow();
136
- wf.setJobHandler((jobName, args) => {
137
- if (jobName === "validate-order") return { valid: true };
138
- if (jobName === "process-payment") return { txnId: "txn-1" };
139
- return null;
140
- });
157
+ const validate = wf.job(validateOrder);
158
+ const payment = wf.job(processPayment);
159
+ validate.mockResolvedValue({ valid: true });
160
+ payment.mockResolvedValue({ txnId: "txn-1" });
141
161
 
142
162
  const result = await main({ input: { orderId: "o-1" } });
143
163
 
144
- expect(wf.triggeredJobs).toEqual([
145
- { jobName: "validate-order", args: { orderId: "o-1" } },
146
- { jobName: "process-payment", args: { orderId: "o-1" } },
147
- ]);
164
+ expect(validate).toHaveBeenCalledWith({ orderId: "o-1" });
165
+ expect(payment).toHaveBeenCalledWith({ orderId: "o-1" });
148
166
  });
149
167
  ```
150
168
 
151
- `mockWorkflow()` also supports order-based responses:
169
+ Unconfigured definition mocks continue to run their real implementations. The lower-level `execJobFunction`, `startWorkflow`, `resumeWorkflowExecution`, `wait`, and `resolve` mocks and the existing `setJobHandler`, `enqueueResult`, `enqueueResults`, and call-record helpers remain available.
170
+
171
+ Use `waitPoint(definition)` for typed wait-point control:
152
172
 
153
173
  ```typescript
154
174
  using wf = mockWorkflow();
175
+ const approvalMock = wf.waitPoint(approvalWaitPoint);
155
176
 
156
- // Single response for the next triggerJobFunction call
157
- wf.enqueueResult({ valid: true });
177
+ approvalMock.wait.mockResolvedValue({ approved: true });
178
+ await approvalWaitPoint.wait({ message: "Please approve" });
158
179
 
159
- // Multiple responses for subsequent calls (FIFO)
160
- wf.enqueueResults({ valid: true }, { txnId: "txn-1" });
180
+ expect(approvalMock.wait).toHaveBeenCalledWith({ message: "Please approve" });
161
181
  ```
162
182
 
183
+ Use `wf.setEnv(...)` when locally-run workflow job bodies need configuration values. Per-run `runWorkflowLocally(..., { env })` options take precedence over the mock's env.
184
+
163
185
  ### SecretManager Mock
164
186
 
165
187
  ```typescript
166
188
  import { mockSecretmanager } from "@tailor-platform/sdk/vitest";
167
189
 
168
190
  test("reads secrets from vault", async () => {
169
- using sm = mockSecretmanager();
170
- sm.setSecrets({
171
- "my-vault": { API_KEY: "sk-123", DB_PASS: "secret" },
191
+ using sm = mockSecretmanager({
192
+ secrets: { "my-vault": { API_KEY: "sk-123" } },
172
193
  });
194
+ sm.setSecret("my-vault", "API_KEY", "override");
195
+ sm.mergeSecrets("my-vault", { DB_PASS: "secret" });
173
196
 
174
197
  const key = await tailor.secretmanager.getSecret("my-vault", "API_KEY");
175
- expect(key).toBe("sk-123");
198
+ expect(key).toBe("override");
176
199
  expect(sm.calls).toEqual([{ method: "getSecret", vault: "my-vault", name: "API_KEY" }]);
177
200
  });
178
201
  ```
@@ -183,65 +206,65 @@ test("reads secrets from vault", async () => {
183
206
  import { mockAuthconnection } from "@tailor-platform/sdk/vitest";
184
207
 
185
208
  test("returns configured token", async () => {
186
- using ac = mockAuthconnection();
187
- ac.setTokens({
188
- google: { access_token: "ya29.xxx", expires_in: 3600 },
209
+ using ac = mockAuthconnection({
210
+ tokens: { google: { access_token: "ya29.xxx" } },
211
+ onUnhandled: "error",
189
212
  });
213
+ ac.setToken("google", { access_token: "replacement" });
190
214
 
191
215
  const token = await tailor.authconnection.getConnectionToken("google");
192
- expect(token.access_token).toBe("ya29.xxx");
216
+ expect(token.access_token).toBe("replacement");
193
217
  });
194
218
  ```
195
219
 
196
- When no token is configured for a connection, it returns `{ access_token: "mock-token" }`.
220
+ By default, an unconfigured connection returns `{ access_token: "mock-token" }`. Pass `onUnhandled: "error"` to fail instead.
197
221
 
198
222
  ### IDP Mock
199
223
 
200
224
  ```typescript
201
225
  import { mockIdp } from "@tailor-platform/sdk/vitest";
202
226
 
203
- test("resolver-based", async () => {
204
- using idp = mockIdp();
205
- idp.setResolver((method, args) => {
206
- if (method === "user") return { id: "u-1", name: "alice", disabled: false };
207
- return null; // falls back to defaults
227
+ test("namespace-specific mock", async () => {
228
+ using idp = mockIdp({ onUnhandled: "error" });
229
+ const customerIdp = idp.namespace("my-ns");
230
+ customerIdp.user.mockResolvedValue({
231
+ id: "u-1",
232
+ name: "alice",
233
+ disabled: false,
234
+ mfaEnrolled: false,
235
+ mfaFactorIds: [],
208
236
  });
209
237
 
210
238
  const client = new tailor.idp.Client({ namespace: "my-ns" });
211
239
  const user = await client.user("u-1");
212
240
  expect(user.name).toBe("alice");
213
- });
214
-
215
- test("queue-based", async () => {
216
- using idp = mockIdp();
217
- idp.enqueueResult({ id: "u-1", name: "alice", disabled: false });
218
-
219
- const client = new tailor.idp.Client({ namespace: "my-ns" });
220
- const user = await client.user("u-1");
221
- expect(user.name).toBe("alice");
222
- expect(idp.calls).toMatchObject([{ method: "user", namespace: "my-ns" }]);
241
+ expect(customerIdp.user).toHaveBeenCalledWith("u-1");
223
242
  });
224
243
  ```
225
244
 
245
+ Each namespace exposes typed mocks for `users`, `user`, `userByName`, `createUser`, `updateUser`, `deleteUser`, `sendPasswordResetEmail`, and `unenrollMfa`. The existing resolver, queue, and aggregate `calls` APIs remain supported.
246
+
226
247
  ### File Mock
227
248
 
228
249
  ```typescript
229
250
  import { mockFile } from "@tailor-platform/sdk/vitest";
230
251
 
231
252
  test("mock file download", async () => {
232
- using file = mockFile();
233
- file.enqueueResult({
253
+ using file = mockFile({ onUnhandled: "error" });
254
+ file.download.mockResolvedValue({
234
255
  data: new Uint8Array([1, 2, 3]),
235
256
  metadata: { contentType: "image/png", fileSize: 3, sha256sum: "abc", lastUploadedAt: "" },
236
257
  });
237
258
 
238
259
  const result = await tailordb.file.download("ns", "Doc", "attachment", "r-1");
239
260
  expect(result.data).toEqual(new Uint8Array([1, 2, 3]));
240
- expect(file.calls).toMatchObject([{ method: "download", recordId: "r-1" }]);
261
+ expect(file.download).toHaveBeenCalledWith("ns", "Doc", "attachment", "r-1");
241
262
  });
242
263
  ```
243
264
 
244
- For `downloadStream`, enqueue a `FileDownloadStreamResponse` object with a `ReadableStream` body and metadata:
265
+ All File operations are typed Vitest mocks: `upload`, `download`, `downloadAsBase64`, `delete`, `getMetadata`, `downloadStream`, and `uploadStream`. Use native methods such as `mockResolvedValueOnce` and `mockRejectedValueOnce` to model success and failure. The existing resolver, queue, and aggregate `calls` APIs remain supported.
266
+
267
+ For `downloadStream`, configure a `FileDownloadStreamResponse` object with a `ReadableStream` body and metadata:
245
268
 
246
269
  ```typescript
247
270
  test("mock file download stream", async () => {
@@ -252,7 +275,7 @@ test("mock file download stream", async () => {
252
275
  controller.close();
253
276
  },
254
277
  });
255
- file.enqueueResult({
278
+ file.downloadStream.mockResolvedValue({
256
279
  body,
257
280
  metadata: { contentType: "image/png", fileSize: 3, sha256sum: "abc", lastUploadedAt: "" },
258
281
  });
@@ -262,28 +285,6 @@ test("mock file download stream", async () => {
262
285
  });
263
286
  ```
264
287
 
265
- For the deprecated `openDownloadStream`, enqueue an iterable of `StreamValue` items — `metadata`, one or more `chunk` items, and a terminal `complete`. Raw `Uint8Array` / `ArrayBuffer` chunks are rejected so tests stay aligned with the platform's structured stream contract.
266
-
267
- ```typescript
268
- test("mock file download stream (deprecated openDownloadStream)", async () => {
269
- using file = mockFile();
270
- file.enqueueResult([
271
- {
272
- type: "metadata",
273
- metadata: { contentType: "image/png", fileSize: 3, sha256sum: "abc" },
274
- },
275
- { type: "chunk", data: new Uint8Array([1, 2]), position: 0 },
276
- { type: "chunk", data: new Uint8Array([3]), position: 2 },
277
- { type: "complete" },
278
- ]);
279
-
280
- const stream = await tailordb.file.openDownloadStream("ns", "Doc", "attachment", "r-1");
281
- const items = [];
282
- for await (const item of stream) items.push(item);
283
- expect(items).toHaveLength(4);
284
- });
285
- ```
286
-
287
288
  ### Iconv Mock
288
289
 
289
290
  ```typescript
@@ -291,10 +292,7 @@ import { mockIconv } from "@tailor-platform/sdk/vitest";
291
292
 
292
293
  test("mock encoding conversion", () => {
293
294
  using iconv = mockIconv();
294
- iconv.setResolver((method, args) => {
295
- if (method === "decode") return "decoded-text";
296
- return null; // falls back to default empty string
297
- });
295
+ iconv.decode.mockReturnValue("decoded-text");
298
296
 
299
297
  const result = tailor.iconv.decode(new Uint8Array([0x48, 0x69]), "UTF-8");
300
298
  expect(result).toBe("decoded-text");
@@ -302,6 +300,48 @@ test("mock encoding conversion", () => {
302
300
  });
303
301
  ```
304
302
 
303
+ `convert`, `convertBuffer`, `decode`, `encode`, and `encodings` are all typed Vitest mocks. Pass `{ onUnhandled: "error" }` to fail calls without a configured implementation. The existing resolver and aggregate `calls` APIs remain supported.
304
+
305
+ ### AI Gateway Mock
306
+
307
+ ```typescript
308
+ import { mockAigateway } from "@tailor-platform/sdk/vitest";
309
+
310
+ test("resolves an AI Gateway URL", async () => {
311
+ using aigateway = mockAigateway({
312
+ urls: { "my-aigateway": "https://my-aigateway.example.com" },
313
+ });
314
+ aigateway.setUrl("my-aigateway", "https://replacement.example.com");
315
+
316
+ const { url } = await tailor.aigateway.get("my-aigateway");
317
+ expect(url).toBe("https://replacement.example.com");
318
+ expect(aigateway.calls).toEqual([{ name: "my-aigateway" }]);
319
+ });
320
+ ```
321
+
322
+ Calling `get` for a name that has not been registered throws. `setUrls` remains available when replacing the complete URL fixture.
323
+
324
+ ### Logger Mock
325
+
326
+ Each method is a `vi.fn`, so assert on it directly. `calls` returns the emitted `debug`/`info`/`warn`/`error` entries in order.
327
+
328
+ ```typescript
329
+ import { mockLogger } from "@tailor-platform/sdk/vitest";
330
+
331
+ test("logs the processed order", () => {
332
+ using logger = mockLogger();
333
+
334
+ tailor.logger.info("order processed", { orderId: "o-1" });
335
+
336
+ expect(logger.info).toHaveBeenCalledWith("order processed", { orderId: "o-1" });
337
+ expect(logger.calls).toEqual([
338
+ { severity: "info", message: "order processed", attributes: { orderId: "o-1" } },
339
+ ]);
340
+ });
341
+ ```
342
+
343
+ Without an explicit `mockLogger()`, `tailor.logger.*` calls are no-ops in the `tailor-runtime` environment (they neither throw nor record).
344
+
305
345
  ### Loading Secrets from Config
306
346
 
307
347
  Pass a config path to load `defineSecretManager()` values into the mock:
@@ -313,7 +353,7 @@ export default defineConfig({
313
353
  });
314
354
  ```
315
355
 
316
- This makes `tailor.secretmanager.getSecret("vault", "key")` return the values defined in your config. You can still override with `using sm = mockSecretmanager(); sm.setSecrets(...)` in individual tests: a per-test override applies only within that test, and the config-loaded secrets remain available to every other test.
356
+ This makes `tailor.secretmanager.getSecret("vault", "key")` return the values defined in your config. You can still override with `mockSecretmanager({ secrets: ... })` in individual tests: a per-test overlay applies only within that test, and the config-loaded secrets remain available to every other test.
317
357
 
318
358
  ### Per-Project Configuration
319
359
 
@@ -355,7 +395,7 @@ export default defineConfig({
355
395
 
356
396
  ## Unit Tests
357
397
 
358
- Unit tests call `.body()` (or `.trigger()`) directly on a resolver, workflow job, or executor and stub any platform-provided globals they touch.
398
+ Unit tests call `.body()` (or `.start()`) directly on a resolver, workflow job, or executor and stub any platform-provided globals they touch.
359
399
 
360
400
  ### Testing Resolvers
361
401
 
@@ -364,7 +404,6 @@ Unit tests call `.body()` (or `.trigger()`) directly on a resolver, workflow job
364
404
  For pure logic with no external dependencies, invoke `.body()` directly:
365
405
 
366
406
  ```typescript
367
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
368
407
  import { describe, expect, test } from "vitest";
369
408
  import resolver from "../src/resolver/add";
370
409
 
@@ -372,7 +411,8 @@ describe("add resolver", () => {
372
411
  test("adds two numbers", async () => {
373
412
  const result = await resolver.body({
374
413
  input: { left: 1, right: 2 },
375
- user: unauthenticatedTailorUser,
414
+ caller: null,
415
+ invoker: null,
376
416
  env: {},
377
417
  });
378
418
  expect(result).toBe(3);
@@ -388,15 +428,16 @@ Stub the global `tailordb.Client` and queue raw query results in order. Best for
388
428
 
389
429
  > If you are running with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta), acquire `using db = mockTailordb()` to install and drive the mock `tailordb.Client` instead of `vi.stubGlobal()`.
390
430
 
431
+ > The example below uses `aroundAll` / `aroundEach`, which require Vitest ≥ 4.1.
432
+
391
433
  ```typescript
392
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
393
- import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from "vitest";
434
+ import { aroundAll, aroundEach, describe, expect, test, vi } from "vitest";
394
435
  import resolver from "../src/resolver/incrementUserAge";
395
436
 
396
437
  describe("incrementUserAge resolver", () => {
397
438
  const mockQueryObject = vi.fn();
398
439
 
399
- beforeAll(() => {
440
+ aroundAll(async (runSuite) => {
400
441
  vi.stubGlobal("tailordb", {
401
442
  Client: vi.fn(
402
443
  class {
@@ -406,9 +447,13 @@ describe("incrementUserAge resolver", () => {
406
447
  },
407
448
  ),
408
449
  });
450
+ await runSuite();
451
+ vi.unstubAllGlobals();
452
+ });
453
+ aroundEach(async (runTest) => {
454
+ await runTest();
455
+ mockQueryObject.mockReset();
409
456
  });
410
- afterAll(() => vi.unstubAllGlobals());
411
- afterEach(() => mockQueryObject.mockReset());
412
457
 
413
458
  test("increments age inside a transaction", async () => {
414
459
  // BEGIN → SELECT → UPDATE → COMMIT
@@ -419,7 +464,8 @@ describe("incrementUserAge resolver", () => {
419
464
 
420
465
  const result = await resolver.body({
421
466
  input: { email: "test@example.com" },
422
- user: unauthenticatedTailorUser,
467
+ caller: null,
468
+ invoker: null,
423
469
  env: {},
424
470
  });
425
471
 
@@ -490,7 +536,6 @@ describe("decrementUserAge", () => {
490
536
  Pass `mock.db` to functions that take a Kysely instance. When a resolver or executor calls `getDB()` internally there is no such seam, so spy the generated `getDB` and point it at the mock:
491
537
 
492
538
  ```typescript
493
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
494
539
  import { createKyselyMock } from "@tailor-platform/sdk/vitest";
495
540
  import { describe, expect, test, vi } from "vitest";
496
541
  import { getDB, type Namespace } from "../generated/db";
@@ -522,7 +567,8 @@ describe("upsertUsers resolver", () => {
522
567
  { name: "Existing", email: "exists@example.com", age: 41 },
523
568
  ],
524
569
  },
525
- user: unauthenticatedTailorUser,
570
+ caller: null,
571
+ invoker: null,
526
572
  env: { appName: "Resolver Template", version: 1 },
527
573
  });
528
574
 
@@ -538,39 +584,70 @@ Reach for [`mockTailordb`](#mocking-the-tailordb-client) instead when you want t
538
584
 
539
585
  #### Resolvers that resume a workflow
540
586
 
541
- Resolvers that call `waitPoint.resolve(...)` delegate to `tailor.workflow.resolve` at runtime. With the `tailor-runtime` environment active, use `mockWorkflow().setResolveHandler` to drive the user-supplied callback and inspect `resolveCalls`:
587
+ Resolvers that call `waitPoint.resolve(...)` delegate to `tailor.workflow.resolve` at runtime. With the `tailor-runtime` environment active, use `mockWorkflow().waitPoint(definition)` to invoke the callback with the payload that originally suspended the job:
542
588
 
543
589
  ```typescript
544
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
545
590
  import { mockWorkflow } from "@tailor-platform/sdk/vitest";
546
591
  import { describe, expect, test } from "vitest";
592
+ import { approval } from "../workflow/approval";
547
593
  import resolver from "./resolveApproval";
548
594
 
549
595
  describe("resolveApproval resolver", () => {
550
596
  test("resolves approval with approved=true", async () => {
551
597
  using wf = mockWorkflow();
552
- wf.setResolveHandler((_executionId, _key, callback) => {
553
- const result = callback({ message: "Please approve order order-1", orderId: "order-1" });
554
- expect(result).toEqual({ approved: true });
598
+ const approvalMock = wf.waitPoint(approval);
599
+ approvalMock.setResolvePayload({
600
+ message: "Please approve order order-1",
601
+ orderId: "order-1",
555
602
  });
556
603
 
557
604
  const result = await resolver.body({
558
605
  input: { executionId: "exec-1", approved: true },
559
- user: unauthenticatedTailorUser,
606
+ caller: null,
607
+ invoker: null,
560
608
  env: {},
561
609
  });
562
610
 
563
611
  expect(result).toEqual({ resolved: true });
564
- expect(wf.resolveCalls).toEqual([{ executionId: "exec-1", key: "approval" }]);
612
+ expect(approvalMock.resolve).toHaveBeenCalledWith("exec-1", expect.any(Function));
613
+ });
614
+ });
615
+ ```
616
+
617
+ `setResolvePayload` is typed from the wait-point definition. The lower-level `setResolveHandler` and `resolveCalls` APIs remain available when a test must control several wait points together.
618
+
619
+ #### Resolvers that resume failed workflows
620
+
621
+ Resolvers or executors that call `workflow.resumeWorkflowExecution(executionId)` delegate to `tailor.workflow.resumeWorkflowExecution` at runtime. With the `tailor-runtime` environment active, use `mockWorkflow().setResumeHandler` to control the returned execution ID and inspect `resumeWorkflowExecution.mock.calls`:
622
+
623
+ ```typescript
624
+ import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
625
+ import { mockWorkflow } from "@tailor-platform/sdk/vitest";
626
+ import { describe, expect, test } from "vitest";
627
+ import resolver from "./retryFailedWorkflow";
628
+
629
+ describe("retryFailedWorkflow resolver", () => {
630
+ test("resumes a failed workflow execution", async () => {
631
+ using wf = mockWorkflow();
632
+ wf.setResumeHandler("exec-resumed-123");
633
+
634
+ const result = await resolver.body({
635
+ input: { executionId: "exec-failed-456" },
636
+ user: unauthenticatedTailorUser,
637
+ env: {},
638
+ });
639
+
640
+ expect(result).toEqual({ resumedExecutionId: "exec-resumed-123" });
641
+ expect(wf.resumeWorkflowExecution.mock.calls).toEqual([["exec-failed-456"]]);
565
642
  });
566
643
  });
567
644
  ```
568
645
 
569
- `setResolveHandler` receives `(executionId, key, callback)` and decides whether to invoke the callback that's how you assert the value returned to the suspended job.
646
+ `setResumeHandler` accepts a static string (same execution ID for every call) or a function `(executionId) => string` that computes one per call. By default the mock echoes the input `executionId`.
570
647
 
571
648
  ### Testing Executors
572
649
 
573
- Function-kind executors expose their handler as `executor.operation.body(args)`. The shape of `args` is determined by the trigger — for example, `recordCreatedTrigger({ type: user })` produces `{ newRecord }` typed against the type's output. GraphQL, webhook, and workflow operation kinds are declarative and don't expose a user-authored body to test.
650
+ Function-kind executors expose their handler as `executor.operation.body(args)`. The shape of `args` is determined by the trigger — for example, `recordCreatedTrigger({ type: user })` produces `{ newRecord }` typed against the type's output, plus runtime fields such as `env`, `actor`, and `invoker`. GraphQL, webhook, and workflow operation kinds are declarative and don't expose a user-authored body to test.
574
651
 
575
652
  The `executor` template extracts shared DB access into a helper (`shared.ts`) and tests the helper directly against a mocked `tailordb.Client` (same TailorDB-mocking pattern as the resolver section). Executor handlers themselves stay thin and can be tested by spying on the helper:
576
653
 
@@ -587,6 +664,14 @@ describe("onUserCreated executor", () => {
587
664
  throw new Error("expected function operation");
588
665
  }
589
666
  await onUserCreated.operation.body({
667
+ workspaceId: "workspace-1",
668
+ appNamespace: "app",
669
+ env: {},
670
+ actor: null,
671
+ invoker: null,
672
+ event: "created",
673
+ rawEvent: "tailordb.type_record.created",
674
+ typeName: "User",
590
675
  newRecord: {
591
676
  id: "user-1",
592
677
  name: "Alice",
@@ -611,11 +696,11 @@ To exercise the full chain (executor → helper → TailorDB), drop the spy and
611
696
 
612
697
  ### Testing Workflow Jobs
613
698
 
614
- Workflow jobs expose the same `.body()` entrypoint as resolvers, plus `.trigger()` for calling them from another job or a test.
699
+ Workflow jobs expose the same `.body()` entrypoint as resolvers, plus `.start()` for calling them from another job or a test.
615
700
 
616
701
  #### Simple job
617
702
 
618
- Call `.body()` with the input and a stub `{ env: {} }`:
703
+ Call `.body()` with the input and a stub `{ env: {}, invoker: null }`:
619
704
 
620
705
  ```typescript
621
706
  import { describe, expect, test } from "vitest";
@@ -623,46 +708,54 @@ import { validateOrder } from "./order-fulfillment";
623
708
 
624
709
  describe("validateOrder", () => {
625
710
  test("accepts a valid order", () => {
626
- const result = validateOrder.body({ orderId: "order-1", amount: 100 }, { env: {} });
711
+ const result = validateOrder.body(
712
+ { orderId: "order-1", amount: 100 },
713
+ { env: {}, invoker: null },
714
+ );
627
715
  expect(result).toEqual({ valid: true, orderId: "order-1" });
628
716
  });
629
717
 
630
718
  test("rejects a non-positive amount", () => {
631
- expect(() => validateOrder.body({ orderId: "order-1", amount: 0 }, { env: {} })).toThrow(
632
- "Order amount must be positive",
633
- );
719
+ expect(() =>
720
+ validateOrder.body({ orderId: "order-1", amount: 0 }, { env: {}, invoker: null }),
721
+ ).toThrow("Order amount must be positive");
634
722
  });
635
723
  });
636
724
  ```
637
725
 
638
- #### Jobs that trigger other jobs
726
+ #### Jobs that start other jobs
639
727
 
640
- Spy on each dependent job's `.trigger()` to replace it with a deterministic result:
728
+ Use `mockWorkflow().job(definition)` to replace dependent jobs with deterministic results:
641
729
 
642
730
  ```typescript
643
- import { describe, expect, test, vi } from "vitest";
731
+ import { mockWorkflow } from "@tailor-platform/sdk/vitest";
732
+ import { describe, expect, test } from "vitest";
644
733
  import { fulfillOrder, processPayment, sendConfirmation, validateOrder } from "./order-fulfillment";
645
734
 
646
735
  describe("fulfillOrder", () => {
647
736
  test("chains validate → pay → confirm", async () => {
648
- using _validateSpy = vi.spyOn(validateOrder, "trigger").mockResolvedValue({
737
+ using wf = mockWorkflow();
738
+ const validate = wf.job(validateOrder).mockResolvedValue({
649
739
  valid: true,
650
740
  orderId: "order-1",
651
741
  });
652
- using _paymentSpy = vi.spyOn(processPayment, "trigger").mockResolvedValue({
742
+ wf.job(processPayment).mockResolvedValue({
653
743
  transactionId: "txn-order-1",
654
744
  amount: 100,
655
745
  status: "completed",
656
746
  });
657
- using _confirmSpy = vi.spyOn(sendConfirmation, "trigger").mockResolvedValue({
747
+ wf.job(sendConfirmation).mockResolvedValue({
658
748
  orderId: "order-1",
659
749
  transactionId: "txn-order-1",
660
750
  confirmed: true,
661
751
  });
662
752
 
663
- const result = await fulfillOrder.body({ orderId: "order-1", amount: 100 }, { env: {} });
753
+ const result = await fulfillOrder.body(
754
+ { orderId: "order-1", amount: 100 },
755
+ { env: {}, invoker: null },
756
+ );
664
757
 
665
- expect(validateOrder.trigger).toHaveBeenCalledWith({ orderId: "order-1", amount: 100 });
758
+ expect(validate).toHaveBeenCalledWith({ orderId: "order-1", amount: 100 });
666
759
  expect(result).toMatchObject({ confirmed: true, paymentStatus: "completed" });
667
760
  });
668
761
  });
@@ -672,58 +765,74 @@ describe("fulfillOrder", () => {
672
765
 
673
766
  #### Jobs that wait on approval
674
767
 
675
- `.wait()` calls delegate to `tailor.workflow.wait`. With the `tailor-runtime` environment active, use `mockWorkflow().setWaitHandler` to drive each branch and inspect `waitCalls`:
768
+ `.wait()` calls delegate to `tailor.workflow.wait`. With the `tailor-runtime` environment active, use `mockWorkflow().waitPoint(definition)` to drive each branch with a typed mock:
676
769
 
677
770
  ```typescript
678
771
  import { mockWorkflow } from "@tailor-platform/sdk/vitest";
679
772
  import { describe, expect, test } from "vitest";
680
- import { processWithApproval } from "./approval";
773
+ import { approval, processWithApproval } from "./approval";
681
774
 
682
775
  describe("processWithApproval", () => {
683
776
  test("returns approved status when .wait() resolves positively", async () => {
684
777
  using wf = mockWorkflow();
685
- wf.setWaitHandler({ approved: true });
778
+ const approvalMock = wf.waitPoint(approval);
779
+ approvalMock.wait.mockResolvedValue({ approved: true });
686
780
 
687
- const result = await processWithApproval.body({ orderId: "order-1" }, { env: {} });
781
+ const result = await processWithApproval.body(
782
+ { orderId: "order-1" },
783
+ { env: {}, invoker: null },
784
+ );
688
785
 
689
786
  expect(result).toEqual({ orderId: "order-1", status: "approved" });
690
- expect(wf.waitCalls[0]).toEqual({
691
- key: "approval",
692
- payload: { message: "Please approve order order-1", orderId: "order-1" },
787
+ expect(approvalMock.wait).toHaveBeenCalledWith({
788
+ message: "Please approve order order-1",
789
+ orderId: "order-1",
693
790
  });
694
791
  });
695
792
 
696
793
  test("returns rejected status when .wait() resolves negatively", async () => {
697
794
  using wf = mockWorkflow();
698
- wf.setWaitHandler({ approved: false });
795
+ wf.waitPoint(approval).wait.mockResolvedValue({ approved: false });
699
796
 
700
- const result = await processWithApproval.body({ orderId: "order-2" }, { env: {} });
797
+ const result = await processWithApproval.body(
798
+ { orderId: "order-2" },
799
+ { env: {}, invoker: null },
800
+ );
701
801
 
702
802
  expect(result.status).toBe("rejected");
703
803
  });
704
804
  });
705
805
  ```
706
806
 
707
- `setWaitHandler` accepts a static value (returned from every `.wait()` call) or a function `(key, payload) => unknown` to compute one per call. `waitCalls` captures the `key` and `payload` passed in.
807
+ The lower-level `setWaitHandler` and `waitCalls` APIs remain available when one handler must cover several wait points.
708
808
 
709
809
  #### Running a full workflow locally
710
810
 
711
- To exercise the full chain with real job bodies, just call `workflow.mainJob.trigger()` — no `mockWorkflow()` needed. Dependent jobs run their real `.body()` functions, and trigger args/results cross the same JSON boundary as the platform, so a non-serializable payload fails the test exactly as it would in production:
811
+ To exercise the full chain with real job bodies, call `runWorkflowLocally(workflow, args)`. Dependent jobs run their real `.body()` functions, and start args/results cross the same JSON boundary as the platform, so a non-serializable payload fails the test exactly as it would in production:
712
812
 
713
813
  ```typescript
814
+ import { runWorkflowLocally } from "@tailor-platform/sdk/vitest";
714
815
  import { describe, expect, test } from "vitest";
715
816
  import workflow from "./order-fulfillment";
716
817
 
717
818
  describe("order-fulfillment workflow", () => {
718
- test("mainJob.trigger() executes all jobs", async () => {
719
- const result = await workflow.mainJob.trigger({ orderId: "order-3", amount: 300 });
819
+ test("runWorkflowLocally() executes all jobs", async () => {
820
+ const result = await runWorkflowLocally(workflow, { orderId: "order-3", amount: 300 });
720
821
 
721
822
  expect(result).toMatchObject({ confirmed: true, paymentStatus: "completed" });
722
823
  });
723
824
  });
724
825
  ```
725
826
 
726
- Acquire `mockWorkflow()` only when you need to override a dependent job with `wf.setJobHandler(...)` / `wf.enqueueResult(...)` (the rest still run their real bodies), control the env via `wf.setEnv(...)`, or assert on `wf.triggeredJobs`.
827
+ Acquire `mockWorkflow()` only when you need to override a dependent definition with `wf.job(...)` / `wf.workflow(...)` (the rest still run their real bodies), control the env via `wf.setEnv(...)`, or assert on calls.
828
+
829
+ Pass `{ env }` as the third argument when job bodies need configuration values during the local run.
830
+
831
+ If you already acquired `mockWorkflow()`, you can also call `wf.setEnv(...)` to reuse the same env across local workflow runs.
832
+
833
+ Like the platform runtime, the local runner re-runs the orchestrator body once per `.start()` call (N starts means N+1 passes), so any side effects outside the start results fire on every pass. Keep the body deterministic and move repeatable side effects into the started jobs.
834
+
835
+ This helper is still a local runner. Use E2E tests when you need to verify deployed workflow scheduling, suspension, or replay behavior.
727
836
 
728
837
  **Use when:** you want to verify orchestration end to end without the cost of a real deployment.
729
838
 
@@ -823,14 +932,13 @@ Use `startWorkflow` from the CLI helpers. It starts the workflow on the deployed
823
932
  import { randomUUID } from "node:crypto";
824
933
  import { startWorkflow } from "@tailor-platform/sdk/cli";
825
934
  import { describe, expect, test } from "vitest";
826
- import config from "../tailor.config";
827
935
  import userProfileSync from "../src/workflow/sync-profile";
828
936
 
829
937
  describe("user-profile-sync workflow", () => {
830
938
  test("executes end to end", { timeout: 180_000 }, async () => {
831
939
  const { executionId, wait } = await startWorkflow({
832
940
  workflow: userProfileSync,
833
- authInvoker: config.auth.invoker("admin"),
941
+ invoker: "admin",
834
942
  arg: {
835
943
  name: "workflow-test",
836
944
  email: `wf-${randomUUID()}@example.com`,