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

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 (208) hide show
  1. package/CHANGELOG.md +161 -0
  2. package/dist/application-Dtqap5jM.mjs +3 -0
  3. package/dist/{client-CobIRHl-.mjs → application-XuMWK4eq.mjs} +5869 -25
  4. package/dist/application-XuMWK4eq.mjs.map +1 -0
  5. package/dist/{assert-CKfwrmCV.mjs → assert-DBxo8jPo.mjs} +1 -2
  6. package/dist/{assert-CKfwrmCV.mjs.map → assert-DBxo8jPo.mjs.map} +1 -1
  7. package/dist/{authconnection-D8SJGMpj.mjs → authconnection-D2MhtTN5.mjs} +2 -3
  8. package/dist/{authconnection-D8SJGMpj.mjs.map → authconnection-D2MhtTN5.mjs.map} +1 -1
  9. package/dist/{authconnection-BIYzEh2p.d.mts → authconnection-DvUQAjQS.d.mts} +1 -1
  10. package/dist/{brand-DlnJ375c.mjs → brand-Eo4pLXPJ.mjs} +1 -2
  11. package/dist/{brand-DlnJ375c.mjs.map → brand-Eo4pLXPJ.mjs.map} +1 -1
  12. package/dist/cli/index.mjs +241 -237
  13. package/dist/cli/index.mjs.map +1 -1
  14. package/dist/cli/lib.d.mts +547 -620
  15. package/dist/cli/lib.mjs +9 -11
  16. package/dist/cli/lib.mjs.map +1 -1
  17. package/dist/completion/zsh-worker.zsh +4108 -0
  18. package/dist/configure/index.d.mts +9 -7
  19. package/dist/configure/index.mjs +76 -40
  20. package/dist/configure/index.mjs.map +1 -1
  21. package/dist/{context-s0lxhu8_.mjs → context-Bd266-ru.mjs} +2 -3
  22. package/dist/context-Bd266-ru.mjs.map +1 -0
  23. package/dist/{context-CUBwSBq4.d.mts → context-C2lEi9uw.d.mts} +7 -28
  24. package/dist/{crashreport-D1wKBJ8N.mjs → crashreport-BMWcxeSE.mjs} +1 -2
  25. package/dist/{crashreport-BhD0y14F.mjs → crashreport-DFq-vsU0.mjs} +21 -14
  26. package/dist/{crashreport-BhD0y14F.mjs.map → crashreport-DFq-vsU0.mjs.map} +1 -1
  27. package/dist/{enum-constants-C7DaWeQo.mjs → enum-constants-j9QBF0cB.mjs} +1 -2
  28. package/dist/enum-constants-j9QBF0cB.mjs.map +1 -0
  29. package/dist/{errors-EsY4XO6O.mjs → errors-Dtf2WPaW.mjs} +1 -2
  30. package/dist/{errors-EsY4XO6O.mjs.map → errors-Dtf2WPaW.mjs.map} +1 -1
  31. package/dist/{field-C4zdJLW5.mjs → field-DOsJCPFa.mjs} +1 -2
  32. package/dist/field-DOsJCPFa.mjs.map +1 -0
  33. package/dist/{file-B58Dm-2P.mjs → file-BbdFGdMV.mjs} +3 -12
  34. package/dist/file-BbdFGdMV.mjs.map +1 -0
  35. package/dist/{file-BzK8z3X-.d.mts → file-Dq3NIt_F.d.mts} +3 -42
  36. package/dist/{file-utils-BHPxPXmn.mjs → file-utils-CYZnO1pX.mjs} +6 -7
  37. package/dist/file-utils-CYZnO1pX.mjs.map +1 -0
  38. package/dist/{globals-ByrCoDip.mjs → globals-Cf0sxIt8.mjs} +53 -5
  39. package/dist/globals-Cf0sxIt8.mjs.map +1 -0
  40. package/dist/http-adapter.generated-DFsXDdm5.d.mts +581 -0
  41. package/dist/{iconv-kwrmd1U_.d.mts → iconv-Co-TOPuH.d.mts} +1 -1
  42. package/dist/{iconv-DreIffeM.mjs → iconv-D2vi8G36.mjs} +2 -3
  43. package/dist/{iconv-DreIffeM.mjs.map → iconv-D2vi8G36.mjs.map} +1 -1
  44. package/dist/{idp-Ch95ag8h.mjs → idp-BDbK5gjm.mjs} +2 -3
  45. package/dist/{idp-Ch95ag8h.mjs.map → idp-BDbK5gjm.mjs.map} +1 -1
  46. package/dist/{idp-BlBPtXJ-.d.mts → idp-DrhVrLmV.d.mts} +1 -1
  47. package/dist/{index-CLxubakC.d.mts → index-BI-_j9Z3.d.mts} +49 -261
  48. package/dist/{index-CPRnOjjt.d.mts → index-C4JirJH8.d.mts} +2 -2
  49. package/dist/{index-CQZVJ5SX.d.mts → index-CZfWhr0a.d.mts} +2 -2
  50. package/dist/{index-DRhMpdnA.d.mts → index-Cg8VKAdN.d.mts} +8 -8
  51. package/dist/{index-CfRFkXIO.d.mts → index-DYRjoLXD.d.mts} +2 -2
  52. package/dist/index-lFpcjHPU.d.mts +201 -0
  53. package/dist/{index-DUupuPhZ.d.mts → index-nW7hE6oE.d.mts} +2 -2
  54. package/dist/{interceptor-DOqRkCya.mjs → interceptor-D-q1rvRl.mjs} +1 -2
  55. package/dist/{interceptor-DOqRkCya.mjs.map → interceptor-D-q1rvRl.mjs.map} +1 -1
  56. package/dist/kysely/index.mjs +0 -1
  57. package/dist/kysely/index.mjs.map +1 -1
  58. package/dist/{kysely-type-D1e0Vwkd.mjs → kysely-type-DR8uzZTA.mjs} +2 -3
  59. package/dist/kysely-type-DR8uzZTA.mjs.map +1 -0
  60. package/dist/{logger-DpJyJvNz.mjs → logger-CxF-Ex5d.mjs} +1 -2
  61. package/dist/{logger-DpJyJvNz.mjs.map → logger-CxF-Ex5d.mjs.map} +1 -1
  62. package/dist/{mock-DMgIygjE.mjs → mock-FPxmnt-y.mjs} +9 -56
  63. package/dist/mock-FPxmnt-y.mjs.map +1 -0
  64. package/dist/{multiline-Cf9ODpr1.mjs → multiline-sfHpTZZK.mjs} +1 -2
  65. package/dist/{multiline-Cf9ODpr1.mjs.map → multiline-sfHpTZZK.mjs.map} +1 -1
  66. package/dist/{package-json-DcQApfPQ.mjs → package-json-8b0O9TlX.mjs} +1 -2
  67. package/dist/{package-json-DcQApfPQ.mjs.map → package-json-8b0O9TlX.mjs.map} +1 -1
  68. package/dist/package-json-Cv2Z-TqQ.mjs +3 -0
  69. package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
  70. package/dist/plugin/builtin/enum-constants/index.mjs +1 -2
  71. package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
  72. package/dist/plugin/builtin/file-utils/index.mjs +1 -2
  73. package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
  74. package/dist/plugin/builtin/kysely-type/index.mjs +1 -2
  75. package/dist/plugin/builtin/seed/index.d.mts +1 -1
  76. package/dist/plugin/builtin/seed/index.mjs +1 -2
  77. package/dist/plugin/index.d.mts +4 -5
  78. package/dist/plugin/index.mjs +0 -1
  79. package/dist/plugin/index.mjs.map +1 -1
  80. package/dist/registry-DH4m7eYo.mjs +53 -0
  81. package/dist/registry-DH4m7eYo.mjs.map +1 -0
  82. package/dist/{repl-editor-CJG3sz7A.mjs → repl-editor-DmGr9zMw.mjs} +2 -3
  83. package/dist/{repl-editor-CJG3sz7A.mjs.map → repl-editor-DmGr9zMw.mjs.map} +1 -1
  84. package/dist/{chunk-BkoGK1jX.mjs → rolldown-runtime-DXywRVcq.mjs} +0 -1
  85. package/dist/runtime/authconnection.d.mts +1 -1
  86. package/dist/runtime/authconnection.mjs +1 -2
  87. package/dist/runtime/context.d.mts +1 -1
  88. package/dist/runtime/context.mjs +1 -2
  89. package/dist/runtime/file.d.mts +2 -2
  90. package/dist/runtime/file.mjs +2 -3
  91. package/dist/runtime/globals.d.mts +8 -41
  92. package/dist/runtime/globals.mjs +0 -1
  93. package/dist/runtime/iconv.d.mts +1 -1
  94. package/dist/runtime/iconv.mjs +1 -2
  95. package/dist/runtime/idp.d.mts +1 -1
  96. package/dist/runtime/idp.mjs +1 -2
  97. package/dist/runtime/index.d.mts +8 -8
  98. package/dist/runtime/index.mjs +7 -8
  99. package/dist/runtime/secretmanager.d.mts +1 -1
  100. package/dist/runtime/secretmanager.mjs +1 -2
  101. package/dist/runtime/workflow.d.mts +2 -2
  102. package/dist/runtime/workflow.mjs +1 -2
  103. package/dist/{runtime-C7qTBDD2.mjs → runtime-CY4JvrDj.mjs} +1069 -542
  104. package/dist/runtime-CY4JvrDj.mjs.map +1 -0
  105. package/dist/{schema-1msIhXwA.mjs → schema-Dtw9Orye.mjs} +18 -16
  106. package/dist/schema-Dtw9Orye.mjs.map +1 -0
  107. package/dist/{secret-file-CWzF8rry.mjs → secret-file-VSVGy1V0.mjs} +27 -3
  108. package/dist/{secret-file-CWzF8rry.mjs.map → secret-file-VSVGy1V0.mjs.map} +1 -1
  109. package/dist/{secretmanager-CKLB3wAQ.d.mts → secretmanager-B3n4KHfm.d.mts} +1 -1
  110. package/dist/{secretmanager-B9h-U_8U.mjs → secretmanager-BVxw3ih_.mjs} +2 -3
  111. package/dist/{secretmanager-B9h-U_8U.mjs.map → secretmanager-BVxw3ih_.mjs.map} +1 -1
  112. package/dist/seed/index.mjs +0 -1
  113. package/dist/seed/index.mjs.map +1 -1
  114. package/dist/{seed-BH2FbrPV.mjs → seed-izIEyP3z.mjs} +7 -19
  115. package/dist/seed-izIEyP3z.mjs.map +1 -0
  116. package/dist/service-DCqIWibD.mjs +3 -0
  117. package/dist/{service-DMohAx8a2.mjs → service-DU1mVzri2.mjs} +3 -4
  118. package/dist/{service-DMohAx8a2.mjs.map → service-DU1mVzri2.mjs.map} +1 -1
  119. package/dist/{service-wI3Hvrgx.mjs → service-DjyqbCaJ.mjs} +9 -10
  120. package/dist/service-DjyqbCaJ.mjs.map +1 -0
  121. package/dist/{telemetry-BQbbVo2t.mjs → telemetry-CdqJEzkj.mjs} +2 -3
  122. package/dist/{telemetry-BQbbVo2t.mjs.map → telemetry-CdqJEzkj.mjs.map} +1 -1
  123. package/dist/telemetry-ClwW5ohF.mjs +3 -0
  124. package/dist/test-env-key-D7UkZp99.mjs +75 -0
  125. package/dist/test-env-key-D7UkZp99.mjs.map +1 -0
  126. package/dist/type-source-DH_LH20p.mjs +13 -0
  127. package/dist/type-source-DH_LH20p.mjs.map +1 -0
  128. package/dist/types-74etvaxy.mjs +4 -0
  129. package/dist/{plugin-C_FyVSdl.d.mts → types-BDRml5C3.d.mts} +128 -188
  130. package/dist/{types-CmzfQP_m.mjs → types-BQijbo4m.mjs} +10 -11
  131. package/dist/types-BQijbo4m.mjs.map +1 -0
  132. package/dist/types-BX4q6Mo6.d.mts +339 -0
  133. package/dist/types-BZ7QKVE8.d.mts +21 -0
  134. package/dist/{tailordb-BlBGmQK-.d.mts → types-CdcQh4Z2.d.mts} +92 -242
  135. package/dist/utils/test/index.d.mts +6 -14
  136. package/dist/utils/test/index.mjs +4 -14
  137. package/dist/utils/test/index.mjs.map +1 -1
  138. package/dist/vitest/environment.mjs +1 -2
  139. package/dist/vitest/environment.mjs.map +1 -1
  140. package/dist/vitest/index.d.mts +42 -5
  141. package/dist/vitest/index.mjs +133 -4
  142. package/dist/vitest/index.mjs.map +1 -1
  143. package/dist/vitest/setup.mjs +2 -3
  144. package/dist/vitest/setup.mjs.map +1 -1
  145. package/dist/{workflow--aPbA8Uq.mjs → workflow-BOmaZwwG.mjs} +9 -5
  146. package/dist/workflow-BOmaZwwG.mjs.map +1 -0
  147. package/dist/{workflow-CMamswkK.d.mts → workflow-BVy4XWjS.d.mts} +15 -10
  148. package/dist/workflow.generated-ClEjBYhm.d.mts +671 -0
  149. package/docs/cli/application.md +0 -2
  150. package/docs/cli/completion.md +3 -0
  151. package/docs/cli/crashreport.md +0 -2
  152. package/docs/cli/executor.md +53 -0
  153. package/docs/cli/function.md +1 -1
  154. package/docs/cli/setup.md +35 -33
  155. package/docs/cli/user.md +3 -3
  156. package/docs/cli/workflow.md +157 -20
  157. package/docs/cli/workspace.md +3 -3
  158. package/docs/cli-reference.md +26 -20
  159. package/docs/configuration.md +0 -2
  160. package/docs/github-actions.md +29 -16
  161. package/docs/migration/v2.md +475 -0
  162. package/docs/plugin/custom.md +2 -2
  163. package/docs/plugin/index.md +1 -1
  164. package/docs/runtime.md +4 -4
  165. package/docs/services/aigateway.md +97 -0
  166. package/docs/services/auth.md +31 -14
  167. package/docs/services/executor.md +3 -5
  168. package/docs/services/resolver.md +8 -10
  169. package/docs/services/tailordb.md +15 -13
  170. package/docs/services/workflow.md +17 -19
  171. package/docs/testing.md +75 -56
  172. package/package.json +18 -17
  173. package/dist/actor-J2gJ0eK5.d.mts +0 -24
  174. package/dist/application-76hhIhnJ.mjs +0 -5594
  175. package/dist/application-76hhIhnJ.mjs.map +0 -1
  176. package/dist/application-av2raLs6.mjs +0 -4
  177. package/dist/cli/skills.d.mts +0 -1
  178. package/dist/cli/skills.mjs +0 -22
  179. package/dist/cli/skills.mjs.map +0 -1
  180. package/dist/client-C68VWo4g.mjs +0 -4
  181. package/dist/client-CobIRHl-.mjs.map +0 -1
  182. package/dist/context-s0lxhu8_.mjs.map +0 -1
  183. package/dist/enum-constants-C7DaWeQo.mjs.map +0 -1
  184. package/dist/env-B-g-qgE4.d.mts +0 -7
  185. package/dist/field-C4zdJLW5.mjs.map +0 -1
  186. package/dist/file-B58Dm-2P.mjs.map +0 -1
  187. package/dist/file-utils-BHPxPXmn.mjs.map +0 -1
  188. package/dist/globals-ByrCoDip.mjs.map +0 -1
  189. package/dist/job-BpsFXPbi.mjs +0 -54
  190. package/dist/job-BpsFXPbi.mjs.map +0 -1
  191. package/dist/kysely-type-D1e0Vwkd.mjs.map +0 -1
  192. package/dist/mock-DMgIygjE.mjs.map +0 -1
  193. package/dist/package-json-wzO6nV9O.mjs +0 -4
  194. package/dist/registry-D0uB0OrK.mjs +0 -178
  195. package/dist/registry-D0uB0OrK.mjs.map +0 -1
  196. package/dist/runtime-C7qTBDD2.mjs.map +0 -1
  197. package/dist/schema-1msIhXwA.mjs.map +0 -1
  198. package/dist/seed-BH2FbrPV.mjs.map +0 -1
  199. package/dist/service-BHQIerYh.mjs +0 -4
  200. package/dist/service-wI3Hvrgx.mjs.map +0 -1
  201. package/dist/telemetry-w92bvGdC.mjs +0 -4
  202. package/dist/types-2Be3wSMc.mjs +0 -5
  203. package/dist/types-CmzfQP_m.mjs.map +0 -1
  204. package/dist/workflow--aPbA8Uq.mjs.map +0 -1
  205. package/dist/workflow.generated-Bf1tWylx.d.mts +0 -1416
  206. package/docs/generator/builtin.md +0 -257
  207. package/docs/generator/custom.md +0 -147
  208. package/docs/generator/index.md +0 -66
@@ -0,0 +1,97 @@
1
+ # AI Gateway
2
+
3
+ AI Gateway provides a unified endpoint for accessing multiple LLM providers (Azure OpenAI, Google Vertex AI Gemini, Anthropic via Vertex AI) through a single OpenAI-compatible API, with platform-managed credentials and workspace-scoped authentication.
4
+
5
+ ## Overview
6
+
7
+ AI Gateway provides:
8
+
9
+ - A unified, OpenAI-compatible endpoint for multiple LLM providers
10
+ - Mandatory authentication via your workspace's auth (request tokens are resolved against the configured auth namespace)
11
+ - Per-workspace isolation: each gateway is provisioned with its own platform-assigned URL
12
+ - Optional CORS allow-list for browser-based clients
13
+ - Built-in usage tracking and rate limiting (configured platform-side)
14
+
15
+ ## Configuration
16
+
17
+ Configure an AI Gateway using `defineAIGateway()`:
18
+
19
+ **Definition Rules:**
20
+
21
+ - **Multiple gateways allowed**: You can define multiple AI Gateways in your config file
22
+ - **Configuration location**: Define in `tailor.config.ts` and add to the `aiGateways` array
23
+ - **Uniqueness**: Gateway names must be unique across all AI Gateways
24
+ - **Name pattern**: `name` must match `^[a-z0-9][a-z0-9-]{1,28}[a-z0-9]$` (lowercase alphanumeric and hyphens, 3-30 characters)
25
+
26
+ ```typescript
27
+ import { defineAIGateway, defineConfig } from "@tailor-platform/sdk";
28
+
29
+ const aiGateway = defineAIGateway("my-aigateway", {
30
+ authNamespace: "default",
31
+ });
32
+
33
+ export default defineConfig({
34
+ aiGateways: [aiGateway],
35
+ });
36
+ ```
37
+
38
+ ## Options
39
+
40
+ ### authNamespace
41
+
42
+ The auth namespace used to resolve request tokens against your workspace's auth configuration. Must match an existing auth namespace.
43
+
44
+ ```typescript
45
+ defineAIGateway("my-aigateway", {
46
+ authNamespace: "default",
47
+ });
48
+ ```
49
+
50
+ ### cors
51
+
52
+ Optional list of allowed origins for browser-based clients. Each entry is one of:
53
+
54
+ - `*` — any origin (any scheme, any host)
55
+ - `http(s)://*` — any host on the given scheme
56
+ - `http(s)://*.example.com` — any subdomain of `example.com` on the given scheme
57
+ - `http(s)://app.example.com` — an exact origin
58
+
59
+ An optional `:port` may be appended in all URL forms. Omitting `cors` (or passing `[]`) disables cross-origin access — browsers will block any cross-origin reads.
60
+
61
+ ```typescript
62
+ defineAIGateway("my-aigateway", {
63
+ authNamespace: "default",
64
+ cors: ["https://app.example.com", "https://*.example.com"],
65
+ });
66
+ ```
67
+
68
+ ## Complete Example
69
+
70
+ ```typescript
71
+ import {
72
+ defineAIGateway,
73
+ defineAuth,
74
+ defineConfig,
75
+ defineStaticWebSite,
76
+ } from "@tailor-platform/sdk";
77
+
78
+ const website = defineStaticWebSite("my-frontend", {
79
+ description: "Frontend application",
80
+ });
81
+
82
+ const aiGateway = defineAIGateway("my-aigateway", {
83
+ authNamespace: "default",
84
+ cors: [website.url],
85
+ });
86
+
87
+ const auth = defineAuth("my-auth", {
88
+ // ...auth configuration...
89
+ });
90
+
91
+ export default defineConfig({
92
+ name: "my-app",
93
+ auth,
94
+ staticWebsites: [website],
95
+ aiGateways: [aiGateway],
96
+ });
97
+ ```
@@ -139,18 +139,18 @@ export const user = db.type("User", {
139
139
  });
140
140
  ```
141
141
 
142
- The `attributeList` values are accessible via `user.attributeList` as a tuple:
142
+ The `attributeList` values are accessible via the runtime principal's `attributeList` as a tuple:
143
143
 
144
144
  ```typescript
145
145
  // In a resolver
146
146
  body: (context) => {
147
- const [organizationId, teamId] = context.user.attributeList;
147
+ const [organizationId, teamId] = context.caller?.attributeList ?? [];
148
148
  },
149
149
 
150
150
  // In TailorDB hooks
151
151
  .hooks({
152
152
  field: {
153
- create: ({ user }) => user.attributeList[0], // First UUID from list
153
+ create: ({ invoker }) => invoker?.attributeList[0] ?? null, // First UUID from list
154
154
  },
155
155
  })
156
156
  ```
@@ -160,7 +160,7 @@ body: (context) => {
160
160
  When you want to use machine users without defining a `userProfile`, define `machineUserAttributes` instead. These attributes are used for:
161
161
 
162
162
  - type-safe `machineUsers[*].attributes`
163
- - `context.user.attributes` typing (via `tailor.d.ts`)
163
+ - runtime principal `attributes` typing (via `tailor.d.ts`)
164
164
 
165
165
  ```typescript
166
166
  import { defineAuth, t } from "@tailor-platform/sdk";
@@ -200,12 +200,12 @@ machineUsers: {
200
200
  },
201
201
  ```
202
202
 
203
- **attributes**: Values for attributes enabled in `userProfile.attributes` (or all fields defined in `machineUserAttributes` when `userProfile` is omitted). All enabled fields must be set here. These values are accessible via `user.attributes`:
203
+ **attributes**: Values for attributes enabled in `userProfile.attributes` (or all fields defined in `machineUserAttributes` when `userProfile` is omitted). All enabled fields must be set here. These values are accessible via the runtime principal's `attributes`:
204
204
 
205
205
  ```typescript
206
206
  // In a resolver
207
207
  body: (context) => {
208
- const role = context.user.attributes?.role;
208
+ const role = context.caller?.attributes.role;
209
209
  },
210
210
  ```
211
211
 
@@ -230,25 +230,25 @@ machineUsers: {
230
230
  },
231
231
  ```
232
232
 
233
- These values are accessible via `user.attributeList`:
233
+ These values are accessible via the runtime principal's `attributeList`:
234
234
 
235
235
  ```typescript
236
236
  // In a resolver
237
237
  body: (context) => {
238
- const [organizationId, teamId] = context.user.attributeList;
238
+ const [organizationId, teamId] = context.caller?.attributeList ?? [];
239
239
  },
240
240
 
241
241
  // In TailorDB hooks
242
242
  .hooks({
243
243
  field: {
244
- create: ({ user }) => user.attributes?.role === "ADMIN" ? "default" : null,
244
+ create: ({ invoker }) => invoker?.attributes.role === "ADMIN" ? "default" : null,
245
245
  },
246
246
  })
247
247
 
248
248
  // In TailorDB validate
249
249
  .validate({
250
250
  field: [
251
- ({ user }) => user.attributes?.role === "ADMIN",
251
+ ({ invoker }) => invoker?.attributes.role === "ADMIN",
252
252
  "Only admins can set this field",
253
253
  ],
254
254
  })
@@ -269,7 +269,7 @@ tailor-sdk machineuser token <name>
269
269
 
270
270
  ### Specifying a machine user invoker
271
271
 
272
- Resolvers, executors, and `workflow.trigger()` accept an `authInvoker` option that chooses which machine user runs the operation. Pass the machine user name as a plain string — it is type-narrowed to the names you registered in `machineUsers`.
272
+ Resolvers, executors, and `workflow.trigger()` accept an `invoker` option that chooses which machine user runs the operation. Pass the machine user name as a plain string — it is type-narrowed to the names you registered in `machineUsers`.
273
273
 
274
274
  ```typescript
275
275
  // tailor.config.ts
@@ -298,7 +298,7 @@ export default createResolver({
298
298
  // Trigger workflow with machine user permissions
299
299
  const workflowRunId = await myWorkflow.trigger(
300
300
  { id: input.id },
301
- { authInvoker: "admin-machine-user" },
301
+ { invoker: "admin-machine-user" },
302
302
  );
303
303
  return { workflowRunId };
304
304
  },
@@ -310,8 +310,6 @@ export default createResolver({
310
310
 
311
311
  Type narrowing is provided by the generated `tailor.d.ts` (the `MachineUserNameRegistry` interface). Run `tailor-sdk generate` (or `apply`) after defining new machine users to refresh it.
312
312
 
313
- > **Deprecated:** The `auth.invoker("<name>")` helper is still available for backward compatibility. Prefer the string form — it does not require importing `auth` from `tailor.config.ts` into runtime files, avoiding bundling config-layer (Node-only) dependencies.
314
-
315
313
  ## OAuth 2.0 Clients
316
314
 
317
315
  Configure OAuth 2.0 clients for third-party applications:
@@ -515,6 +513,25 @@ export const auth = defineAuth("my-auth", {
515
513
 
516
514
  **invoker**: The machine user whose permissions are used to execute the hook. Must reference a machine user defined in the same auth configuration.
517
515
 
516
+ ### Federated identity claims
517
+
518
+ When a user signs in through a Built-in IdP OAuth provider (Google or Microsoft), the upstream provider's profile is available on `claims.federated_identity`. It is `undefined` for password logins, so guard before reading it. Commonly present claims (`name`, `given_name`, `family_name`, `picture`, `locale`) are typed; any other claim the provider issues is forwarded as-is. Availability varies by provider (for example, Microsoft does not issue `picture`).
519
+
520
+ ```typescript
521
+ hooks: {
522
+ beforeLogin: {
523
+ handler: async ({ claims }) => {
524
+ const federated = claims.federated_identity;
525
+ if (federated?.provider === "google") {
526
+ // Populate the user record from the upstream profile
527
+ const avatarUrl = federated.claims.picture;
528
+ }
529
+ },
530
+ invoker: "hook-invoker",
531
+ },
532
+ }
533
+ ```
534
+
518
535
  ## CLI Commands
519
536
 
520
537
  Manage Auth resources using the CLI:
@@ -219,7 +219,7 @@ createExecutor({
219
219
  });
220
220
  ```
221
221
 
222
- Executor callbacks receive the trigger args, including `env` from `defineConfig({ env })`. `function` and `jobFunction` `body` args also include an `invoker` field: the principal running this function, overridden by `authInvoker` when set; `null` for anonymous calls. Other operation kinds (`graphql`, `webhook`, `workflow`) receive `env` through their callback args but do not pass `invoker` into those callbacks.
222
+ Executor callbacks receive the trigger args, including `env` from `defineConfig({ env })`. `function` and `jobFunction` `body` args also include an `invoker` field: the principal running this function, or the machine user configured through the operation `invoker` option; `null` for anonymous calls. Other operation kinds (`graphql`, `webhook`, `workflow`) receive `env` through their callback args but do not pass `invoker` into those callbacks.
223
223
 
224
224
  ### Job Function Operation
225
225
 
@@ -331,7 +331,7 @@ createExecutor({
331
331
 
332
332
  ### Authentication for Operations
333
333
 
334
- GraphQL and Workflow operations can specify an `authInvoker` to execute with machine user credentials. Pass the machine user name as a plain string — it is type-narrowed to the names defined in your auth config:
334
+ GraphQL and Workflow operations can specify an `invoker` to execute with machine user credentials. Pass the machine user name as a plain string — it is type-narrowed to the names defined in your auth config:
335
335
 
336
336
  ```typescript
337
337
  import { createExecutor, scheduleTrigger } from "@tailor-platform/sdk";
@@ -342,13 +342,11 @@ export default createExecutor({
342
342
  operation: {
343
343
  kind: "graphql",
344
344
  query: `mutation { cleanupOldRecords { count } }`,
345
- authInvoker: "batch-processor",
345
+ invoker: "batch-processor",
346
346
  },
347
347
  });
348
348
  ```
349
349
 
350
- > **Deprecated:** `auth.invoker("batch-processor")` still works, but is deprecated. Prefer the string form to avoid importing config-layer modules into runtime files.
351
-
352
350
  ## Event Payloads
353
351
 
354
352
  Each trigger type provides specific context data in the callback functions.
@@ -208,7 +208,7 @@ Validation functions receive:
208
208
 
209
209
  - `value` - The field value being validated
210
210
  - `data` - The entire input object
211
- - `user` - The user performing the operation
211
+ - `invoker` - The principal performing the operation
212
212
 
213
213
  You can specify validation as:
214
214
 
@@ -234,13 +234,13 @@ Validation runs automatically before the `body` function executes. When validati
234
234
  Define actual resolver logic in the `body` function. Function arguments include:
235
235
 
236
236
  - `input` - Input data from GraphQL request
237
- - `user` - The user who called this resolver; unaffected by `authInvoker`
238
- - `invoker` - The principal running this function; equals `user` by default, or the machine user set by `authInvoker`. `null` for anonymous calls.
237
+ - `caller` - The user or machine user who called this resolver; unaffected by `invoker`. `null` for anonymous calls.
238
+ - `invoker` - The principal running this function; equals `caller` by default, or the machine user configured through the resolver `invoker` option. `null` for anonymous calls.
239
239
  - `env` - Environment variables declared in `tailor.config.ts`
240
240
 
241
241
  ### Using Kysely for Database Access
242
242
 
243
- If you're generating Kysely types with a generator, you can use `getDB` to execute typed queries:
243
+ If you're generating Kysely types with `kyselyTypePlugin`, you can use `getDB` to execute typed queries:
244
244
 
245
245
  ```typescript
246
246
  import { getDB } from "../generated/tailordb";
@@ -306,7 +306,7 @@ createResolver({
306
306
 
307
307
  - When `publishEvents: true`, resolver execution events are published
308
308
  - When not specified, it is **automatically set to `true`** if an executor uses this resolver with `resolverExecutedTrigger`
309
- - When explicitly set to `false` while an executor uses this resolver, an error is thrown during `tailor apply`
309
+ - When explicitly set to `false` while an executor uses this resolver, an error is thrown during `tailor-sdk deploy`
310
310
 
311
311
  **Use cases:**
312
312
 
@@ -352,7 +352,7 @@ createResolver({
352
352
 
353
353
  ## Authentication
354
354
 
355
- Specify an `authInvoker` to execute the resolver with machine user credentials. Pass the machine user name as a plain string — it is type-narrowed to the names you defined in your auth config:
355
+ Specify an `invoker` to execute the resolver with machine user credentials. Pass the machine user name as a plain string — it is type-narrowed to the names you defined in your auth config:
356
356
 
357
357
  ```typescript
358
358
  import { createResolver, t } from "@tailor-platform/sdk";
@@ -365,12 +365,10 @@ export default createResolver({
365
365
  // Executes as "batch-processor" machine user
366
366
  return { result: "ok" };
367
367
  },
368
- authInvoker: "batch-processor",
368
+ invoker: "batch-processor",
369
369
  });
370
370
  ```
371
371
 
372
372
  The machine user name is looked up in the auth service configured on your app (`machineUsers` in `defineAuth`). The namespace is resolved automatically — no need to import `auth` from `tailor.config.ts` in resolver files.
373
373
 
374
- > **Deprecated:** `auth.invoker("batch-processor")` still works, but is deprecated. Importing `auth` into runtime files pulls config-layer (Node-only) dependencies into the bundle.
375
-
376
- **Note:** `authInvoker` controls the permissions for database operations and other platform actions. The `user` object passed to `body` still reflects the original caller, while `invoker` reflects the principal actually running the body.
374
+ **Note:** The `invoker` option controls the permissions for database operations and other platform actions. The `caller` object passed to `body` still reflects the original caller, while the `invoker` body field reflects the principal actually running the body.
@@ -260,7 +260,7 @@ Add hooks to execute functions during data creation or update. Hooks receive thr
260
260
 
261
261
  - `value`: User input if provided, otherwise existing value on update or null on create
262
262
  - `data`: Entire record data (for accessing other field values)
263
- - `user`: User performing the operation
263
+ - `invoker`: Principal performing the operation
264
264
 
265
265
  #### Field-level Hooks
266
266
 
@@ -268,7 +268,7 @@ Set hooks directly on individual fields:
268
268
 
269
269
  ```typescript
270
270
  db.string().hooks({
271
- create: ({ user }) => user.id,
271
+ create: ({ invoker }) => invoker?.id ?? "",
272
272
  update: ({ value }) => value,
273
273
  });
274
274
  ```
@@ -323,7 +323,7 @@ Add validation rules to fields. Validators receive three arguments (executed aft
323
323
 
324
324
  - `value`: Field value after hook transformation
325
325
  - `data`: Entire record data after hook transformations (for accessing other field values)
326
- - `user`: User performing the operation
326
+ - `invoker`: Principal performing the operation
327
327
 
328
328
  Validators return `true` for success, `false` for failure. Use array form `[validator, errorMessage]` for custom error messages.
329
329
 
@@ -409,6 +409,8 @@ export const user = db.type("User", {
409
409
  });
410
410
  ```
411
411
 
412
+ `db.fields.timestamps()` adds non-null `createdAt` and `updatedAt` datetime fields. Both fields are populated when a record is created; provided values are preserved so seed data can use historical timestamps. `updatedAt` is also refreshed automatically when a record is updated.
413
+
412
414
  ## Type Modifiers
413
415
 
414
416
  ### Composite Indexes
@@ -461,7 +463,7 @@ db.type("User", {
461
463
 
462
464
  - When `publishEvents: true`, record creation/update/deletion events are published
463
465
  - When not specified, it is **automatically set to `true`** if an executor uses this type with `recordCreatedTrigger`, `recordUpdatedTrigger`, or `recordDeletedTrigger`
464
- - When explicitly set to `false` while an executor uses this type, an error is thrown during `tailor apply`
466
+ - When explicitly set to `false` while an executor uses this type, an error is thrown during `tailor-sdk deploy`
465
467
 
466
468
  **Use cases:**
467
469
 
@@ -516,8 +518,8 @@ const user = db.type("User", {
516
518
  ...db.fields.timestamps(),
517
519
  });
518
520
 
519
- // Pick id and createdAt, making them optional
520
- user.pickFields(["id", "createdAt"], { optional: true });
521
+ // Pick id, createdAt, and updatedAt, making them optional
522
+ user.pickFields(["id", "createdAt", "updatedAt"], { optional: true });
521
523
  ```
522
524
 
523
525
  Available options:
@@ -532,8 +534,8 @@ Available options:
532
534
  Return all fields except the specified ones:
533
535
 
534
536
  ```typescript
535
- // All fields except id and createdAt
536
- user.omitFields(["id", "createdAt"]);
537
+ // All fields except id, createdAt, and updatedAt
538
+ user.omitFields(["id", "createdAt", "updatedAt"]);
537
539
  ```
538
540
 
539
541
  #### Common Pattern: Input Schema Composition
@@ -548,9 +550,9 @@ export default createResolver({
548
550
  name: "createUser",
549
551
  operation: "mutation",
550
552
  input: {
551
- // id/createdAt are optional (auto-generated), other fields are required
552
- ...user.pickFields(["id", "createdAt"], { optional: true }),
553
- ...user.omitFields(["id", "createdAt"]),
553
+ // id/createdAt/updatedAt are optional (auto-generated), other fields are required
554
+ ...user.pickFields(["id", "createdAt", "updatedAt"], { optional: true }),
555
+ ...user.omitFields(["id", "createdAt", "updatedAt"]),
554
556
  },
555
557
  output: t.object({ id: t.uuid() }),
556
558
  body: async (context) => {
@@ -567,8 +569,8 @@ import { t } from "@tailor-platform/sdk";
567
569
  import { invoice } from "../../tailordb/invoice";
568
570
 
569
571
  const schemaType = t.object({
570
- ...invoice.pickFields(["id", "createdAt"], { optional: true }),
571
- ...invoice.omitFields(["id", "createdAt", "invoiceNumber", "sequentialId"]),
572
+ ...invoice.pickFields(["id", "createdAt", "updatedAt"], { optional: true }),
573
+ ...invoice.omitFields(["id", "createdAt", "updatedAt", "invoiceNumber", "sequentialId"]),
572
574
  });
573
575
  ```
574
576
 
@@ -105,11 +105,11 @@ import { sendNotification } from "./jobs/send-notification";
105
105
 
106
106
  export const mainJob = createWorkflowJob({
107
107
  name: "main-job",
108
- body: async (input: { customerId: string }) => {
109
- const customer = await fetchCustomer.trigger({
108
+ body: (input: { customerId: string }) => {
109
+ const customer = fetchCustomer.trigger({
110
110
  customerId: input.customerId,
111
111
  });
112
- const notification = await sendNotification.trigger({
112
+ const notification = sendNotification.trigger({
113
113
  message: "Order processed",
114
114
  recipient: customer.email,
115
115
  });
@@ -130,31 +130,31 @@ Using `.trigger()` inside a loop works correctly, as long as the loop is determi
130
130
  // ✅ OK: deterministic loop — same calls in the same order on every execution
131
131
  const regions = ["us", "eu", "ap"];
132
132
  for (const region of regions) {
133
- const result = await fetchData.trigger({ region });
133
+ const result = fetchData.trigger({ region });
134
134
  results.push(result);
135
135
  }
136
136
  ```
137
137
 
138
138
  ```typescript
139
139
  // ❌ Bad: non-deterministic — argument changes between executions
140
- await processJob.trigger({ timestamp: Date.now() });
140
+ processJob.trigger({ timestamp: Date.now() });
141
141
 
142
142
  // ✅ OK: call Date.now() in separated job
143
- const timestamp = await timestampJob.trigger();
144
- await processJob.trigger({ timestamp });
143
+ const timestamp = timestampJob.trigger();
144
+ processJob.trigger({ timestamp });
145
145
  ```
146
146
 
147
147
  ```typescript
148
148
  // ❌ Bad: non-deterministic — external data may change between executions
149
149
  const items = await fetch("https://api.example.com/items").then((r) => r.json());
150
150
  for (const item of items) {
151
- await processItem.trigger({ id: item.id });
151
+ processItem.trigger({ id: item.id });
152
152
  }
153
153
 
154
154
  // ✅ OK: call fetch("https://api.example.com/items").then((r) => r.json()); in separated job
155
- const items = await fetchItemsJob.trigger();
155
+ const items = fetchItemsJob.trigger();
156
156
  for (const item of items) {
157
- await processItem.trigger({ id: item.id });
157
+ processItem.trigger({ id: item.id });
158
158
  }
159
159
  ```
160
160
 
@@ -178,15 +178,15 @@ import { sendNotification } from "./jobs/send-notification";
178
178
  // Jobs must be named exports
179
179
  export const processOrder = createWorkflowJob({
180
180
  name: "process-order",
181
- body: async (input: { customerId: string }, { env, invoker }) => {
181
+ body: (input: { customerId: string }, { env, invoker }) => {
182
182
  // `env` contains values from `tailor.config.ts` -> `env`.
183
- // `invoker` is the principal running this job, overridden by `authInvoker`
184
- // when set; `null` for anonymous calls.
183
+ // `invoker` is the principal running this job, or the machine user
184
+ // configured through the trigger `invoker` option; `null` for anonymous calls.
185
185
  // Trigger other jobs by calling .trigger() on the job object.
186
- const customer = await fetchCustomer.trigger({
186
+ const customer = fetchCustomer.trigger({
187
187
  customerId: input.customerId,
188
188
  });
189
- await sendNotification.trigger({
189
+ sendNotification.trigger({
190
190
  message: "Order processed",
191
191
  recipient: customer.email,
192
192
  });
@@ -356,7 +356,7 @@ export default createWorkflow({
356
356
  You can start a workflow execution from a resolver using `workflow.trigger()`.
357
357
 
358
358
  - `workflow.trigger(args, options?)` returns a workflow run ID (`Promise<string>`).
359
- - To run with machine-user permissions, pass `{ authInvoker: "<machine-user>" }`. The name is type-narrowed to the machine users defined in your auth config.
359
+ - To run with machine-user permissions, pass `{ invoker: "<machine-user>" }`. The name is type-narrowed to the machine users defined in your auth config.
360
360
 
361
361
  ```typescript
362
362
  import { createResolver, t } from "@tailor-platform/sdk";
@@ -372,7 +372,7 @@ export default createResolver({
372
372
  body: async ({ input }) => {
373
373
  const workflowRunId = await orderProcessingWorkflow.trigger(
374
374
  { orderId: input.orderId, customerId: input.customerId },
375
- { authInvoker: "manager-machine-user" },
375
+ { invoker: "manager-machine-user" },
376
376
  );
377
377
 
378
378
  return { workflowRunId };
@@ -383,8 +383,6 @@ export default createResolver({
383
383
  });
384
384
  ```
385
385
 
386
- > **Deprecated:** `auth.invoker("manager-machine-user")` still works but is deprecated. Using the string form avoids importing `auth` into runtime code.
387
-
388
386
  See the full working example in the repository: [example/resolvers/triggerWorkflow.ts](https://github.com/tailor-platform/sdk/blob/main/example/resolvers/triggerWorkflow.ts).
389
387
 
390
388
  ## File Organization