@tailor-platform/sdk 2.0.0-next.9 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/CHANGELOG.md +629 -0
  2. package/README.md +2 -2
  3. package/dist/{application-D_oSqto2.mjs → application-CM6hKnSK.mjs} +489 -118
  4. package/dist/application-CM6hKnSK.mjs.map +1 -0
  5. package/dist/application-CXNaUNhv.mjs +3 -0
  6. package/dist/cli/commands/deploy/aigateway.d.mts +1 -1
  7. package/dist/cli/commands/deploy/application.d.mts +1 -1
  8. package/dist/cli/commands/deploy/auth.d.mts +1 -1
  9. package/dist/cli/commands/deploy/deploy.d.mts +1 -0
  10. package/dist/cli/commands/deploy/executor.d.mts +1 -1
  11. package/dist/cli/commands/deploy/function-registry.d.mts +1 -2
  12. package/dist/cli/commands/deploy/idp.d.mts +1 -1
  13. package/dist/cli/commands/deploy/label.d.mts +2 -0
  14. package/dist/cli/commands/deploy/resolver.d.mts +1 -1
  15. package/dist/cli/commands/deploy/staticwebsite.d.mts +1 -1
  16. package/dist/cli/commands/deploy/tailordb/index.d.mts +3 -1
  17. package/dist/cli/commands/deploy/types.d.mts +2 -1
  18. package/dist/cli/commands/deploy/workflow-execution-policy.d.mts +1 -2
  19. package/dist/cli/commands/deploy/workflow.d.mts +1 -1
  20. package/dist/cli/commands/executor/get.d.mts +1 -10
  21. package/dist/cli/commands/executor/jobs.d.mts +1 -38
  22. package/dist/cli/commands/executor/trigger.d.mts +1 -11
  23. package/dist/cli/commands/generate/seed/bundler.d.mts +2 -1
  24. package/dist/cli/commands/tailordb/migrate/bundler.d.mts +3 -2
  25. package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +11 -1
  26. package/dist/cli/commands/tailordb/migrate/schema-checks.d.mts +5 -0
  27. package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +1 -1
  28. package/dist/cli/commands/workflow/executions.d.mts +1 -13
  29. package/dist/cli/commands/workflow/get.d.mts +1 -10
  30. package/dist/cli/commands/workflow/start.d.mts +2 -14
  31. package/dist/cli/index.mjs +12 -6561
  32. package/dist/cli/lib.d.mts +9 -12
  33. package/dist/cli/lib.mjs +99 -42
  34. package/dist/cli/lib.mjs.map +1 -1
  35. package/dist/cli/{index.d.mts → main.d.mts} +1 -1
  36. package/dist/cli/main.mjs +6777 -0
  37. package/dist/cli/main.mjs.map +1 -0
  38. package/dist/cli/services/http-adapter/bundler.d.mts +1 -0
  39. package/dist/cli/services/workflow/bundler.d.mts +2 -1
  40. package/dist/cli/shared/client.d.mts +28 -3
  41. package/dist/cli/shared/config-loader.d.mts +11 -4
  42. package/dist/cli/shared/error-json.d.mts +23 -0
  43. package/dist/cli/shared/tsconfig-paths-plugin.d.mts +2 -0
  44. package/dist/cli/shared/type-generator.d.mts +4 -3
  45. package/dist/completion/zsh-worker.zsh +85 -22
  46. package/dist/configure/config/types.d.mts +29 -4
  47. package/dist/configure/index.d.mts +4 -3
  48. package/dist/configure/index.mjs +183 -6
  49. package/dist/configure/index.mjs.map +1 -1
  50. package/dist/configure/services/executor/index.d.mts +2 -2
  51. package/dist/configure/services/executor/trigger/event.d.mts +245 -2
  52. package/dist/configure/services/executor/trigger/index.d.mts +3 -3
  53. package/dist/configure/services/idp/index.d.mts +2 -2
  54. package/dist/configure/services/idp/permission.d.mts +1 -16
  55. package/dist/configure/services/idp/types.d.mts +5 -1
  56. package/dist/configure/services/index.d.mts +4 -3
  57. package/dist/configure/services/resolver/index.d.mts +2 -1
  58. package/dist/configure/services/resolver/permission.d.mts +64 -0
  59. package/dist/configure/services/resolver/resolver.d.mts +14 -2
  60. package/dist/configure/services/tailordb/index.d.mts +0 -1
  61. package/dist/configure/services/tailordb/permission.d.mts +1 -16
  62. package/dist/configure/services/workflow/execution-policy.d.mts +3 -3
  63. package/dist/configure/services/workflow/execution-policy.types.d.mts +1 -1
  64. package/dist/configure/services/workflow/job.d.mts +11 -2
  65. package/dist/configure/services/workflow/workflow.d.mts +10 -0
  66. package/dist/configure/types/permission-operand.types.d.mts +20 -0
  67. package/dist/{crashreport-CxHne11E.mjs → crashreport-B5LqCTfF.mjs} +2 -2
  68. package/dist/{crashreport-CxHne11E.mjs.map → crashreport-B5LqCTfF.mjs.map} +1 -1
  69. package/dist/{crashreport-0ioNRZ4K.mjs → crashreport-eI7ty7ok.mjs} +1 -1
  70. package/dist/{errors-DfnF4ibq.mjs → errors-D7583Zz7.mjs} +2 -44
  71. package/dist/errors-D7583Zz7.mjs.map +1 -0
  72. package/dist/{globals-CBZ0egXT.mjs → globals-TfAVItuK.mjs} +21 -5
  73. package/dist/globals-TfAVItuK.mjs.map +1 -0
  74. package/dist/logger-BtX0suGY.mjs +48 -0
  75. package/dist/logger-BtX0suGY.mjs.map +1 -0
  76. package/dist/{logger-BwS4ppwO.mjs → logger-CXQq9YIp.mjs} +110 -13
  77. package/dist/logger-CXQq9YIp.mjs.map +1 -0
  78. package/dist/node-builtins-CmaL2Cbq.mjs +36 -0
  79. package/dist/node-builtins-CmaL2Cbq.mjs.map +1 -0
  80. package/dist/plugin/builtin/enum-constants/index.mjs +115 -2
  81. package/dist/plugin/builtin/enum-constants/index.mjs.map +1 -0
  82. package/dist/plugin/builtin/file-utils/index.mjs +149 -2
  83. package/dist/plugin/builtin/file-utils/index.mjs.map +1 -0
  84. package/dist/plugin/builtin/kysely-type/index.mjs +274 -2
  85. package/dist/plugin/builtin/kysely-type/index.mjs.map +1 -0
  86. package/dist/plugin/builtin/seed/index.mjs +1 -1
  87. package/dist/plugin/builtin/seed/seed-type-processor.d.mts +2 -0
  88. package/dist/{register-ts-hook-DgnmGTCt.mjs → register-ts-hook-LYV7zH-e.mjs} +2949 -1001
  89. package/dist/register-ts-hook-LYV7zH-e.mjs.map +1 -0
  90. package/dist/{registry-i7EdJ-D5.mjs → registry-BIGVUrMB.mjs} +3 -3
  91. package/dist/registry-BIGVUrMB.mjs.map +1 -0
  92. package/dist/runtime/globals.d.mts +7 -0
  93. package/dist/runtime/index.d.mts +3 -1
  94. package/dist/runtime/index.mjs +3 -2
  95. package/dist/runtime/logger.d.mts +98 -0
  96. package/dist/runtime/logger.mjs +3 -0
  97. package/dist/runtime/workflow.d.mts +15 -7
  98. package/dist/runtime/workflow.mjs +1 -1
  99. package/dist/{seed-LUVr7jHL.mjs → seed-B-yckgQY.mjs} +42 -3
  100. package/dist/seed-B-yckgQY.mjs.map +1 -0
  101. package/dist/{service-DaeJlBoH.mjs → service-B5WynBHQ.mjs} +3 -3
  102. package/dist/{service-DaeJlBoH.mjs.map → service-B5WynBHQ.mjs.map} +1 -1
  103. package/dist/service-M7OYziQP.mjs +3 -0
  104. package/dist/{service-CXFce28G.mjs → service-k1xy_A5G.mjs} +30 -3
  105. package/dist/{service-CXFce28G.mjs.map → service-k1xy_A5G.mjs.map} +1 -1
  106. package/dist/{service_pb-BoLM0X4K.mjs → service_pb-D5--My_M.mjs} +5 -5
  107. package/dist/service_pb-D5--My_M.mjs.map +1 -0
  108. package/dist/{service_pb-r1T7kpJc.mjs → service_pb-i8CmnQP4.mjs} +1 -1
  109. package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +106 -1
  110. package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +24 -1
  111. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +49 -1
  112. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +89 -6
  113. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +26 -1
  114. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +101 -1
  115. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +22 -1
  116. package/dist/types/auth.generated.d.mts +14 -2
  117. package/dist/types/executor.generated.d.mts +45 -3
  118. package/dist/types/http-adapter.generated.d.mts +5 -0
  119. package/dist/types/idp.generated.d.mts +31 -1
  120. package/dist/types/resolver.generated.d.mts +30 -2
  121. package/dist/types/tailordb.generated.d.mts +15 -1
  122. package/dist/utils/test/index.d.mts +1 -2
  123. package/dist/utils/test/index.mjs +1 -169
  124. package/dist/utils/test/index.mjs.map +1 -1
  125. package/dist/vitest/environment.mjs +1 -1
  126. package/dist/vitest/index.d.mts +6 -4
  127. package/dist/vitest/index.mjs +112 -62
  128. package/dist/vitest/index.mjs.map +1 -1
  129. package/dist/vitest/mock.d.mts +2 -1
  130. package/dist/vitest/mocks/file.d.mts +1 -1
  131. package/dist/vitest/mocks/logger.d.mts +45 -0
  132. package/dist/vitest/mocks/workflow.d.mts +8 -8
  133. package/dist/vitest/setup.mjs +1 -1
  134. package/dist/{workflow-CsBvRE3g.mjs → workflow-Bamae_Yc.mjs} +5 -5
  135. package/dist/workflow-Bamae_Yc.mjs.map +1 -0
  136. package/dist/{workspace_resource_pb-Db3fv68L.mjs → workspace_resource_pb-DXnO2AT-.mjs} +13 -8
  137. package/dist/workspace_resource_pb-DXnO2AT-.mjs.map +1 -0
  138. package/docs/cli/application.md +5 -1
  139. package/docs/cli/tailordb.md +47 -13
  140. package/docs/cli-reference.md +31 -30
  141. package/docs/configuration.md +53 -1
  142. package/docs/github-actions.md +2 -2
  143. package/docs/migration/v2.md +312 -12
  144. package/docs/quickstart.md +5 -5
  145. package/docs/runtime.md +5 -1
  146. package/docs/services/executor.md +83 -3
  147. package/docs/services/idp.md +8 -6
  148. package/docs/services/resolver.md +60 -4
  149. package/docs/services/tailordb-migration.md +31 -7
  150. package/docs/services/tailordb.md +7 -5
  151. package/docs/services/workflow.md +33 -3
  152. package/docs/testing.md +34 -7
  153. package/package.json +34 -27
  154. package/dist/application-CtuzFhg8.mjs +0 -3
  155. package/dist/application-D_oSqto2.mjs.map +0 -1
  156. package/dist/cli/index.mjs.map +0 -1
  157. package/dist/enum-constants-j9QBF0cB.mjs +0 -116
  158. package/dist/enum-constants-j9QBF0cB.mjs.map +0 -1
  159. package/dist/errors-DfnF4ibq.mjs.map +0 -1
  160. package/dist/file-utils-yEiIS4nJ.mjs +0 -150
  161. package/dist/file-utils-yEiIS4nJ.mjs.map +0 -1
  162. package/dist/globals-CBZ0egXT.mjs.map +0 -1
  163. package/dist/kysely-type-DqIRgDYR.mjs +0 -275
  164. package/dist/kysely-type-DqIRgDYR.mjs.map +0 -1
  165. package/dist/logger-BwS4ppwO.mjs.map +0 -1
  166. package/dist/register-ts-hook-DgnmGTCt.mjs.map +0 -1
  167. package/dist/registry-i7EdJ-D5.mjs.map +0 -1
  168. package/dist/seed-LUVr7jHL.mjs.map +0 -1
  169. package/dist/service-DjhjpJpm.mjs +0 -3
  170. package/dist/service_pb-BoLM0X4K.mjs.map +0 -1
  171. package/dist/utils/test/mock.d.mts +0 -86
  172. package/dist/workflow-CsBvRE3g.mjs.map +0 -1
  173. package/dist/workspace_resource_pb-Db3fv68L.mjs.map +0 -1
@@ -97,7 +97,7 @@ npx tailor-sdk-skills
97
97
  After:
98
98
 
99
99
  ```sh
100
- tailor skills add
100
+ npx @tailor-platform/sdk skills add
101
101
  ```
102
102
 
103
103
  <details>
@@ -107,7 +107,10 @@ tailor skills add
107
107
  The standalone tailor-sdk-skills binary is removed in v2; call the skills add
108
108
  subcommand on the main tailor CLI instead. Replace any remaining
109
109
  tailor-sdk-skills invocations the codemod did not rewrite with
110
- `tailor skills add`.
110
+ `tailor skills add`, or `npx @tailor-platform/sdk skills add` when the
111
+ invocation runs through a package runner (npx, bunx, pnpm/yarn dlx, npm exec)
112
+ — those resolve a package name, and `npx tailor` reaches an unrelated
113
+ `tailor` package on npm.
111
114
  ```
112
115
 
113
116
  </details>
@@ -668,6 +671,70 @@ already pass a plain value unchanged.
668
671
 
669
672
  </details>
670
673
 
674
+ ## defineIdp publishUserEvents → publishEvents
675
+
676
+ **Migration:** Partially automatic
677
+
678
+ Rename the `defineIdp` option `publishUserEvents` to `publishEvents`, matching the field name TailorDB types, resolvers, and workflows already use.
679
+
680
+ Before:
681
+
682
+ ```ts
683
+ import { defineIdp } from "@tailor-platform/sdk";
684
+
685
+ export const idp = defineIdp("my-idp", {
686
+ clients: ["my-client"],
687
+ publishUserEvents: true,
688
+ });
689
+ ```
690
+
691
+ After:
692
+
693
+ ```ts
694
+ import { defineIdp } from "@tailor-platform/sdk";
695
+
696
+ export const idp = defineIdp("my-idp", {
697
+ clients: ["my-client"],
698
+ publishEvents: true,
699
+ });
700
+ ```
701
+
702
+ A shorthand option keeps reading the same local:
703
+
704
+ Before:
705
+
706
+ ```ts
707
+ defineIdp("my-idp", { clients, publishUserEvents });
708
+ ```
709
+
710
+ After:
711
+
712
+ ```ts
713
+ defineIdp("my-idp", { clients, publishEvents: publishUserEvents });
714
+ ```
715
+
716
+ <details>
717
+ <summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
718
+
719
+ ```text
720
+ In Tailor SDK v2, the IdP option `publishUserEvents` is renamed to
721
+ `publishEvents`, so all four services that publish events use one field name.
722
+ The codemod rewrites the option key on `defineIdp` calls whose callee resolves
723
+ to the SDK export, including aliased and namespace imports, and rewrites a
724
+ shorthand `{ publishUserEvents }` to `{ publishEvents: publishUserEvents }` so
725
+ it keeps reading the same local.
726
+
727
+ Also review, and migrate by hand:
728
+ - An options object built in a variable or spread into the call — the codemod
729
+ only rewrites object literals passed directly to `defineIdp`.
730
+ - A computed key (e.g. `[key]: value`) that resolves to `publishUserEvents`.
731
+ - Type annotations or interfaces that declare the option themselves.
732
+ - A file where a local declaration shadows the `defineIdp` import; the codemod
733
+ skips it because the call may not be the SDK export.
734
+ ```
735
+
736
+ </details>
737
+
671
738
  ## defineWaitPoint/defineWaitPoints → createWaitPoint/createWaitPoints
672
739
 
673
740
  **Migration:** Partially automatic
@@ -694,11 +761,11 @@ export const { approval } = createWaitPoints((define) => ({
694
761
  }));
695
762
  ```
696
763
 
697
- ## workflow.triggerWorkflow/triggerJobFunction/resumeWorkflow → startWorkflow/startJobFunction/resumeWorkflowExecution
764
+ ## workflow.triggerWorkflow/triggerJobFunction/resumeWorkflow → startWorkflow/execJobFunction/resumeWorkflowExecution
698
765
 
699
766
  **Migration:** Partially automatic
700
767
 
701
- Rename tailor.workflow call sites from the pre-alignment triggerWorkflow/triggerJobFunction/resumeWorkflow names to the canonical startWorkflow/startJobFunction/resumeWorkflowExecution names, on both the ambient tailor.workflow global and a workflow value imported from @tailor-platform/sdk/runtime(/workflow). For a renamed triggerWorkflow call, also renames a literal `invoker` option key to `authInvoker` — startWorkflow's options expect the platform shape directly, unlike the removed triggerWorkflow wrapper, which converted invoker to authInvoker internally.
768
+ Rename tailor.workflow call sites from the pre-alignment triggerWorkflow/triggerJobFunction/resumeWorkflow names to the canonical startWorkflow/execJobFunction/resumeWorkflowExecution names, on both the ambient tailor.workflow global and a workflow value imported from @tailor-platform/sdk/runtime(/workflow). For a renamed triggerWorkflow call, also renames a literal `invoker` option key to `authInvoker` — startWorkflow's options expect the platform shape directly, unlike the removed triggerWorkflow wrapper, which converted invoker to authInvoker internally.
702
769
 
703
770
  Before:
704
771
 
@@ -736,7 +803,7 @@ await workflow.startWorkflow("myWorkflow", { data: "value" }, { authInvoker: myI
736
803
  ```text
737
804
  The pre-alignment tailor.workflow names triggerWorkflow, triggerJobFunction, and
738
805
  resumeWorkflow are removed from the SDK's type surface in v2; use the canonical
739
- startWorkflow, startJobFunction, and resumeWorkflowExecution names instead. The
806
+ startWorkflow, execJobFunction, and resumeWorkflowExecution names instead. The
740
807
  codemod rewrites direct member-access call sites on the ambient tailor.workflow
741
808
  global and on a workflow value imported from @tailor-platform/sdk/runtime or
742
809
  @tailor-platform/sdk/runtime/workflow (including aliased imports). It skips a
@@ -753,7 +820,7 @@ Also review, and migrate by hand:
753
820
  - Destructured references (e.g. const { triggerWorkflow } = workflow) — the
754
821
  codemod only rewrites direct member-access calls.
755
822
  - Imported TriggerWorkflowOptions / TriggerJobFunctionOptions types — rename
756
- them to StartWorkflowOptions / StartJobFunctionOptions.
823
+ them to StartWorkflowOptions / ExecJobFunctionOptions.
757
824
  - An invoker option passed via a variable or spread (not a literal object) —
758
825
  the codemod only inspects literal object arguments; rename the invoker key
759
826
  to authInvoker in the options object's own definition.
@@ -761,6 +828,52 @@ Also review, and migrate by hand:
761
828
 
762
829
  </details>
763
830
 
831
+ ## workflow.startJobFunction → execJobFunction
832
+
833
+ **Migration:** Partially automatic
834
+
835
+ `tailor.workflow.startJobFunction` and the `StartJobFunctionOptions` type are removed in v2. Use the canonical `execJobFunction` / `ExecJobFunctionOptions`: `Exec*` blocks and returns the job's result, while `Start*` returns only an execution ID. The codemod rewrites member-access call sites on the ambient `tailor.workflow` global and on a `workflow` value imported from @tailor-platform/sdk/runtime(/workflow), and renames `StartJobFunctionOptions` imports along with the type references that resolve to them.
836
+
837
+ Before:
838
+
839
+ ```ts
840
+ import { workflow } from "@tailor-platform/sdk/runtime";
841
+
842
+ const result = workflow.startJobFunction("myJob", { data: "value" });
843
+ ```
844
+
845
+ After:
846
+
847
+ ```ts
848
+ import { workflow } from "@tailor-platform/sdk/runtime";
849
+
850
+ const result = workflow.execJobFunction("myJob", { data: "value" });
851
+ ```
852
+
853
+ <details>
854
+ <summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
855
+
856
+ ```text
857
+ startJobFunction is removed from the SDK's workflow runtime surface in v2;
858
+ execJobFunction is the canonical name for a blocking job call that returns the
859
+ job's result. The codemod rewrites direct member-access calls on the ambient
860
+ tailor.workflow global and on a workflow value imported from
861
+ @tailor-platform/sdk/runtime or @tailor-platform/sdk/runtime/workflow (including
862
+ aliased imports), and renames the StartJobFunctionOptions type. It skips a file
863
+ entirely when a local declaration shadows the workflow import or the ambient
864
+ tailor name, to avoid rewriting an unrelated same-named value.
865
+
866
+ Also review, and migrate by hand:
867
+ - Destructured references (e.g. const { startJobFunction } = workflow) — the
868
+ codemod only rewrites direct member-access calls.
869
+ - mockWorkflow().startJobFunction in tests — assert on the execJobFunction vi.fn
870
+ instead; the alias was the same mock function.
871
+ - A file that already imports ExecJobFunctionOptions alongside the removed type —
872
+ rename the remaining references by hand and drop the duplicate specifier.
873
+ ```
874
+
875
+ </details>
876
+
764
877
  ## openDownloadStream → downloadStream
765
878
 
766
879
  **Migration:** Manual
@@ -941,7 +1054,7 @@ For each flagged `.trigger(` call in these files:
941
1054
 
942
1055
  **Migration:** Partially automatic
943
1056
 
944
- Rename the CLI binary from `tailor-sdk` to `tailor` in package.json scripts, shell scripts, CI workflows, source files, generated declaration comments, and documentation. Does not rename `.tailor-sdk` directory paths or the `create-tailor-sdk` scaffolding package. Note: v2 also changes the default generated output directory from `.tailor-sdk/` to `.tailor/` and the setup lock file from `.github/tailor-sdk.lock` to `.github/tailor.lock`. Run `mv .tailor-sdk .tailor` to migrate the generated output directory (preserves auth connection state and other local files). Run `git mv .github/tailor-sdk.lock .github/tailor.lock` if the old lock file exists; without it `tailor setup check` will treat all managed workflows as missing. Exact ignore-file entries for `.tailor-sdk/` are handled by the generated-output ignore codemod.
1057
+ Rename the CLI binary from `tailor-sdk` to `tailor` in package.json scripts, shell scripts, CI workflows, source files, generated declaration comments, and documentation. Does not rename `.tailor-sdk` directory paths or the `create-tailor-sdk` scaffolding package. Note: v2 also changes the default generated output directory from `.tailor-sdk/` to `.tailor/` and the setup lock file from `.github/tailor-sdk.lock` to `.github/tailor.lock`. Run `mv .tailor-sdk .tailor` to migrate the generated output directory (preserves auth connection state and other local files). Run `git mv .github/tailor-sdk.lock .github/tailor.lock` if the old lock file exists; without it `tailor setup check` will treat all managed workflows as missing. Exact ignore-file entries for `.tailor-sdk/` are handled by the generated-output ignore codemod. If your CI workflows were generated by `tailor setup`, re-run `tailor setup` afterwards so they pin tailor-platform/actions v2 — the v1 actions invoke the removed `tailor-sdk` bin.
945
1058
 
946
1059
  Before:
947
1060
 
@@ -1253,9 +1366,9 @@ single generation pass and resolves once it completes.
1253
1366
 
1254
1367
  ## Generated seed exec.mjs → tailor seed CLI plugin
1255
1368
 
1256
- **Migration:** Manual
1369
+ **Migration:** Partially automatic
1257
1370
 
1258
- `seedPlugin` no longer generates the `exec.mjs` seed runner. Seeding and validation move to the `tailor seed` commands provided by the `@tailor-platform/sdk-plugin-seed` CLI plugin: install it as a devDependency, replace `node <distPath>/exec.mjs` invocations with `tailor seed apply` and `node <distPath>/exec.mjs validate` with `tailor seed validate`, and delete the stale generated `<distPath>/exec.mjs` file. Seed data and schema generation (`data/*.jsonl`, `data/*.schema.ts`) is unchanged, and the `tailor seed apply` options mirror the old script (`--machine-user`, `--namespace`, `--skip-idp`, `--truncate`, `--yes`, type-name arguments).
1371
+ `seedPlugin` no longer generates the `exec.mjs` seed runner. Seeding and validation move to the `tailor seed` commands provided by the `@tailor-platform/sdk-plugin-seed` CLI plugin: install it as a devDependency, replace `node <distPath>/exec.mjs` invocations with `tailor seed apply` and `node <distPath>/exec.mjs validate` with `tailor seed validate`, and delete the stale generated `<distPath>/exec.mjs` file. Seed data and schema generation (`data/*.jsonl`, `data/*.schema.ts`) is unchanged, and the `tailor seed apply` options mirror the old script (`--machine-user`, `--namespace`, `--skip-idp`, `--truncate`, `--yes`, type-name arguments), plus a new `--upsert` flag to update existing rows instead of failing on duplicate ids.
1259
1372
 
1260
1373
  Before:
1261
1374
 
@@ -1272,7 +1385,7 @@ After:
1272
1385
  ```
1273
1386
 
1274
1387
  <details>
1275
- <summary>Prompt for an AI agent (to perform this migration)</summary>
1388
+ <summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
1276
1389
 
1277
1390
  ```text
1278
1391
  seedPlugin no longer generates the exec.mjs seed runner in v2. The tailor seed
@@ -1282,11 +1395,194 @@ CLI plugin (@tailor-platform/sdk-plugin-seed) replaces it:
1282
1395
  @tailor-platform/sdk.
1283
1396
  - Replace `node <distPath>/exec.mjs [options] [types...]` invocations with
1284
1397
  `tailor seed apply [options] [types...]` (same options: --machine-user/-m,
1285
- --namespace/-n, --skip-idp, --truncate, --yes, and type-name arguments).
1398
+ --namespace/-n, --skip-idp, --truncate, --yes, and type-name arguments,
1399
+ plus a new --upsert flag to update existing rows instead of failing on
1400
+ duplicate ids).
1286
1401
  - Replace `node <distPath>/exec.mjs validate [path]` with
1287
1402
  `tailor seed validate [path]`.
1403
+ - Rewrite `fork("<distPath>/exec.mjs", ...)` call sites (test setup files
1404
+ typically fork the runner and await a hand-rolled Promise around
1405
+ `child.on("close", ...)`). The plugin is a CLI-dispatched binary rather
1406
+ than a forkable JS module, so call it synchronously instead —
1407
+ `execSync("npx @tailor-platform/sdk seed apply", { env, stdio: "inherit" })` — keeping
1408
+ the original `env` and `stdio` forwarding, and unwind the surrounding
1409
+ Promise wrapper (drop the now-unused `await`, and the `async` keyword when
1410
+ nothing else in the function awaits). Note that `execSync` throws on a
1411
+ nonzero exit, replacing the wrapper's explicit reject.
1288
1412
  - Delete the stale generated `<distPath>/exec.mjs` file; keep the data/
1289
- directory (JSONL data and generated schemas) as-is.
1413
+ directory (JSONL data and generated schemas) as-is. Nothing removes it
1414
+ automatically, and a leftover runner keeps working while no longer being
1415
+ regenerated.
1416
+ ```
1417
+
1418
+ </details>
1419
+
1420
+ ## @tailor-platform/sdk/test global mocks → @tailor-platform/sdk/vitest
1421
+
1422
+ **Migration:** Manual
1423
+
1424
+ The global platform mocks exported from `@tailor-platform/sdk/test` (`setupTailordbMock`, `setupWorkflowMock`, `setupWaitPointMock`, `setupInvokerMock`, `setupTailorErrorsMock`) and the bundled-output helper `createImportMain` are removed in v2. Use the `tailor-runtime` environment from `@tailor-platform/sdk/vitest` together with `mockTailordb` / `mockWorkflow`: the environment injects `TailorErrors` for you, `setWaitHandler` / `setResolveHandler` replace the wait-point stubs, and the invoker is driven through `globalThis.tailor.context.getInvoker` (or passed directly to `.body()` when testing the TypeScript source). No codemod ships for this migration: it replaces per-test global stubs with a Vitest environment plus disposable mocks, which changes the Vitest config, the setup shape, and the assertions of every affected test. The other `@tailor-platform/sdk/test` exports (`createTailorDBHook`, `createStandardSchema`, `unauthenticatedTailorUser`) are unchanged.
1425
+
1426
+ Job mocks move from a global stub to a disposable mock:
1427
+
1428
+ Before:
1429
+
1430
+ ```ts
1431
+ import { setupWorkflowMock } from "@tailor-platform/sdk/test";
1432
+
1433
+ const { startedJobs } = setupWorkflowMock(() => ({ ok: true }));
1434
+ ```
1435
+
1436
+ After:
1437
+
1438
+ ```ts
1439
+ import { mockWorkflow } from "@tailor-platform/sdk/vitest";
1440
+
1441
+ using wf = mockWorkflow();
1442
+ wf.setJobHandler(() => ({ ok: true }));
1443
+ // wf.startedJobs replaces the returned startedJobs array
1444
+ ```
1445
+
1446
+ <details>
1447
+ <summary>Prompt for an AI agent (to perform this migration)</summary>
1448
+
1449
+ ```text
1450
+ The global platform mocks from @tailor-platform/sdk/test are removed in v2.
1451
+ Migrate each affected test to the tailor-runtime Vitest environment:
1452
+
1453
+ 1. Add the environment for the test files that need platform globals — set
1454
+ environment: "tailor-runtime" in the Vitest project config, or add the
1455
+ // @vitest-environment tailor-runtime docblock to the file. The environment
1456
+ ships in @tailor-platform/sdk/vitest and installs TailorErrors and the base
1457
+ tailor/tailordb globals, so setupTailorErrorsMock has no replacement — delete it.
1458
+ 2. Replace setupTailordbMock(resolver) with using db = mockTailordb() and
1459
+ configure query results on that mock; read its recorded calls instead of the
1460
+ returned executedQueries / createdClients arrays.
1461
+ 3. Replace setupWorkflowMock(handler) with using wf = mockWorkflow() plus
1462
+ wf.setJobHandler(handler) (or wf.enqueueResult(...) for order-based results),
1463
+ and read wf.startedJobs.
1464
+ 4. Replace setupWaitPointMock({ onWait, onResolve }) with the same mockWorkflow()
1465
+ handle: wf.setWaitHandler / wf.setResolveHandler, asserting on wf.waitCalls /
1466
+ wf.resolveCalls.
1467
+ 5. Replace setupInvokerMock(invoker) with
1468
+ vi.spyOn(globalThis.tailor.context, "getInvoker").mockReturnValue(raw) for a
1469
+ bundled test, or pass invoker directly to .body() when unit-testing a
1470
+ resolver/executor/workflow job against the TypeScript source.
1471
+ 6. Drop createImportMain and the tests that import bundled output through it.
1472
+ Bundling integrity is the SDK's responsibility: unit-test the TypeScript
1473
+ source and cover deployed behavior with E2E tests instead.
1474
+
1475
+ See the SDK testing guide for the full environment setup.
1476
+ ```
1477
+
1478
+ </details>
1479
+
1480
+ ## Programmatic CLI name options → workflow/executor definitions
1481
+
1482
+ **Migration:** Manual
1483
+
1484
+ The name-keyed option types exported from `@tailor-platform/sdk/cli` — `GetWorkflowOptions`, `StartWorkflowOptions`, `ListWorkflowExecutionsOptions`, `GetExecutorOptions`, `TriggerExecutorOptions`, `ListExecutorJobsOptions`, `GetExecutorJobOptions`, `WatchExecutorJobOptions` — are removed in v2, together with the function overloads that accepted them. Pass the workflow or executor definition itself instead: `{ workflow: myWorkflow, invoker: "admin" }` / `{ executor: myExecutor }`, matching the `*TypedOptions` shape that types `arg` and `payload` from the definition. No codemod ships for this migration: rewriting a name string into a definition requires importing the module that defines the workflow or executor, which a source-local transform cannot resolve.
1485
+
1486
+ Before:
1487
+
1488
+ ```ts
1489
+ import { startWorkflow } from "@tailor-platform/sdk/cli";
1490
+
1491
+ const { executionId } = await startWorkflow({ name: "user-sync", machineUser: "admin" });
1492
+ ```
1493
+
1494
+ After:
1495
+
1496
+ ```ts
1497
+ import { startWorkflow } from "@tailor-platform/sdk/cli";
1498
+ import userSync from "./workflows/userSync";
1499
+
1500
+ const { executionId } = await startWorkflow({ workflow: userSync, invoker: "admin" });
1501
+ ```
1502
+
1503
+ Executor commands take the executor definition:
1504
+
1505
+ Before:
1506
+
1507
+ ```ts
1508
+ const result = await watchExecutorJob({ executorName: "daily-sync", jobId });
1509
+ ```
1510
+
1511
+ After:
1512
+
1513
+ ```ts
1514
+ const result = await watchExecutorJob({ executor: dailySync, jobId });
1515
+ ```
1516
+
1517
+ <details>
1518
+ <summary>Prompt for an AI agent (to perform this migration)</summary>
1519
+
1520
+ ```text
1521
+ The programmatic CLI functions in @tailor-platform/sdk/cli no longer accept a
1522
+ workflow or executor name; they take the definition object instead. For each
1523
+ flagged call site:
1524
+
1525
+ 1. Import the workflow or executor definition — the module whose default export
1526
+ is createWorkflow(...) or whose export is createExecutor(...) with that name.
1527
+ 2. Replace name: "my-workflow" with workflow: myWorkflow, and
1528
+ executorName: "my-executor" with executor: myExecutor. For
1529
+ listWorkflowExecutions, workflowName becomes workflow.
1530
+ 3. startWorkflow's machine user moves from machineUser to the required
1531
+ invoker, typed against the machine users declared in tailor.config.ts.
1532
+ 4. Replace imported option types with the *TypedOptions equivalent
1533
+ (e.g. GetWorkflowOptions → GetWorkflowTypedOptions<typeof myWorkflow>).
1534
+ Note that arg (startWorkflow) and payload (triggerExecutor) are now typed
1535
+ from the definition, so a mistyped argument becomes a type error.
1536
+
1537
+ When the name is only known at runtime (read from argv or an environment
1538
+ variable), the CLI command itself — `tailor workflow start <name>` /
1539
+ `tailor executor trigger <name>` — remains the name-keyed entry point.
1540
+ ```
1541
+
1542
+ </details>
1543
+
1544
+ ## tailor.d.ts Env uses value types instead of literal values
1545
+
1546
+ **Migration:** Manual
1547
+
1548
+ The `Env` interface in `tailor.d.ts` is generated from the type of each `defineConfig({ env })` value (`string`, `number`, or `boolean`) instead of the value itself, so the generated file no longer carries whatever the config resolved to when it was generated. Keys that aren't valid TypeScript identifiers are quoted, which previously produced a file that failed to parse. Run `tailor generate` to refresh the file, then widen any code that depended on the old literal types. If a `tailor.d.ts` you already committed contains a sensitive value, treat that value as exposed and rotate it; keep secrets in Secret Manager rather than `env`.
1549
+
1550
+ An env value can no longer stand in for a literal union; narrow it explicitly:
1551
+
1552
+ Before:
1553
+
1554
+ ```ts
1555
+ const stage: "production" | "staging" = env.STAGE;
1556
+ ```
1557
+
1558
+ After:
1559
+
1560
+ ```ts
1561
+ const stage = env.STAGE === "staging" ? "staging" : "production";
1562
+ ```
1563
+
1564
+ <details>
1565
+ <summary>Prompt for an AI agent (to perform this migration)</summary>
1566
+
1567
+ ```text
1568
+ Tailor SDK v2 generates the `Env` interface in `tailor.d.ts` from the type of
1569
+ each `defineConfig({ env })` value (`string`, `number`, `boolean`) instead of
1570
+ the resolved value, so `Env` properties no longer carry literal types.
1571
+
1572
+ Run `tailor generate` first to refresh `tailor.d.ts`, then review the places
1573
+ that depended on the old literal types:
1574
+
1575
+ - An env value assigned or passed where a literal union is required, e.g.
1576
+ `const stage: "production" | "staging" = env.STAGE`. Narrow it with a
1577
+ comparison or a validation helper instead of relying on the declared type.
1578
+ - A generic argument, conditional type, or template-literal type parameterized
1579
+ by an env value.
1580
+ - `as const` / `satisfies` assertions that assumed one specific literal.
1581
+
1582
+ Plain comparisons (`env.STAGE === "production"`) and arithmetic on numeric env
1583
+ values keep working and need no change. Do not restore the old behavior by
1584
+ editing `tailor.d.ts`: it is generated and will be overwritten, and embedding
1585
+ env values there is what leaked configured secrets into version control.
1290
1586
  ```
1291
1587
 
1292
1588
  </details>
@@ -1295,6 +1591,10 @@ CLI plugin (@tailor-platform/sdk-plugin-seed) replaces it:
1295
1591
 
1296
1592
  These v2 changes alter runtime or CLI behavior; no source change is needed.
1297
1593
 
1594
+ ### publishEvents recomputed from the executors in each deploy
1595
+
1596
+ An unset `publishEvents` is recomputed on every `deploy` from the executors taking part in the run, in both directions: adding a subscribing trigger turns publishing on, and removing the last one turns it back off. Previously a workflow or job kept publishing once it had been enabled, so a workflow whose subscribing trigger is already gone stops publishing on the next `deploy` — declare `publishEvents: true` on it if something outside this project consumes those events. `deploy` also stops instead of applying when a subscription cannot be satisfied: when a trigger names a resource no config in the run declares, when a workflow or job combines `publishEvents: false` with a subscribing trigger, and when a config that resolves without an `id` subscribes across configs. Each of those errors names the resource and both ways to resolve it.
1597
+
1298
1598
  ### CLI tokens stored in the OS keyring
1299
1599
 
1300
1600
  CLI login tokens are stored in the OS keyring by default when available, falling back to the platform config file when it is not. No source change is required; re-login if you need tokens moved into the keyring.
@@ -33,13 +33,13 @@ cd example-app
33
33
  Before deploying your app, you need to create a workspace:
34
34
 
35
35
  ```bash
36
- npx tailor login
37
- npx tailor workspace create --name <workspace-name> --region <workspace-region>
38
- npx tailor workspace list
36
+ npx @tailor-platform/sdk login
37
+ npx @tailor-platform/sdk workspace create --name <workspace-name> --region <workspace-region>
38
+ npx @tailor-platform/sdk workspace list
39
39
 
40
40
  # Or with Bun:
41
- # bunx tailor login
42
- # bunx tailor workspace create --name <workspace-name> --region <workspace-region>
41
+ # bun tailor login
42
+ # bun tailor workspace create --name <workspace-name> --region <workspace-region>
43
43
 
44
44
  # OR
45
45
  # Create a new workspace using Tailor Platform Console
package/docs/runtime.md CHANGED
@@ -20,6 +20,7 @@ import {
20
20
  context,
21
21
  file,
22
22
  aigateway,
23
+ logger,
23
24
  } from "@tailor-platform/sdk/runtime";
24
25
 
25
26
  const utf8 = iconv.convert(sjisBuffer, "Shift_JIS", "UTF-8");
@@ -38,6 +39,8 @@ const invoker = context.getInvoker();
38
39
  const { metadata } = await file.upload("my-namespace", "Document", "attachment", recordId, bytes);
39
40
 
40
41
  const { url } = await aigateway.get("my-aigateway");
42
+
43
+ logger.info("order processed", { orderId: "o-1", total: 99.5 });
41
44
  ```
42
45
 
43
46
  ## Subpath imports
@@ -81,10 +84,11 @@ The runtime entry re-exports the following namespaces. Detailed signatures, para
81
84
  - `secretmanager` — secret-vault access (`getSecret`, `getSecrets`)
82
85
  - `authconnection` — OAuth-style connection tokens (`getConnectionToken`)
83
86
  - `idp` — IdP user management (`new Client({ namespace })`)
84
- - `workflow` — workflow & job control (`startWorkflow`, `resumeWorkflowExecution`, `startJobFunction`, `wait`, `resolve`)
87
+ - `workflow` — workflow & job control (`startWorkflow`, `resumeWorkflowExecution`, `execJobFunction`, `wait`, `resolve`)
85
88
  - `context` — execution context (`getInvoker`)
86
89
  - `file` — `tailordb.file` BLOB API (`upload`, `download`, `downloadAsBase64`, `delete`, `getMetadata`, `downloadStream`, `uploadStream`)
87
90
  - `aigateway` — AI Gateway URL resolution (`get`)
91
+ - `logger` — structured logging with severity and attributes; the message is written to standard output, the full entry with its attributes is exported over OpenTelemetry where the attributes are queryable (`debug`, `info`, `warn`, `error`, `setAttributes`)
88
92
 
89
93
  ## Testing
90
94
 
@@ -136,9 +136,9 @@ When the project defines multiple IdPs, pass `idp` to target a specific one. The
136
136
  idpUserCreatedTrigger({ idp: "my-idp" });
137
137
  ```
138
138
 
139
- Omitting `idp` is allowed only when the project has exactly one IdP; otherwise `apply` fails with an error listing the configured IdPs.
139
+ Omitting `idp` is allowed only when the project has exactly one IdP; otherwise `deploy` fails with an error listing the configured IdPs.
140
140
 
141
- These triggers require the IdP to publish user lifecycle events. The SDK enables `publishUserEvents` automatically during `apply` on each IdP that is targeted by an `idpUser` trigger; set the value explicitly on `defineIdp()` to override. See [IdP service - publishUserEvents](./idp.md#publishuserevents).
141
+ These triggers require the IdP to publish user lifecycle events. `deploy` enables `publishEvents` automatically on each IdP targeted by an `idpUser` trigger taking part in the same run, and turns it back off once no such trigger remains; set the value explicitly on `defineIdp()` to pin it. See [IdP service - publishEvents](./idp.md#publishevents).
142
142
 
143
143
  ### Auth Access Token Triggers
144
144
 
@@ -152,6 +152,37 @@ Fire on auth access token lifecycle events:
152
152
  authAccessTokenIssuedTrigger();
153
153
  ```
154
154
 
155
+ ### Workflow Execution Triggers
156
+
157
+ Fire when a workflow execution changes state. Use the single-event helpers or `workflowExecutionTrigger()` for multiple events:
158
+
159
+ ```typescript
160
+ import { createExecutor, workflowExecutionTrigger } from "@tailor-platform/sdk";
161
+ import orderWorkflow from "../workflows/order";
162
+
163
+ export default createExecutor({
164
+ name: "order-workflow-finished",
165
+ trigger: workflowExecutionTrigger({
166
+ workflow: orderWorkflow,
167
+ events: ["completed", "retried"],
168
+ }),
169
+ operation: {
170
+ kind: "function",
171
+ body: async (args) => {
172
+ if (args.event === "completed" && !args.success) {
173
+ console.error(args.error);
174
+ }
175
+ },
176
+ },
177
+ });
178
+ ```
179
+
180
+ The available workflow events are `started`, `completed`, `retried`, `resumed`, `wait_started`, and `wait_resolved`. To observe job-level events, use `workflowJobExecutionStartedTrigger()`, `workflowJobExecutionCompletedTrigger()`, `workflowJobExecutionWaitStartedTrigger()`, `workflowJobExecutionWaitResolvedTrigger()`, or `workflowJobExecutionTrigger()`.
181
+
182
+ `completed` events include `success`; when it is `false`, `error` contains the failure message. A job released from a wait point emits `wait_resolved` instead of `completed`.
183
+
184
+ These triggers require the workflow to publish execution events. `deploy` enables `publishEvents` automatically on each targeted workflow, and on every job of a workflow targeted by a `workflowJobExecution*` trigger, and turns it back off once no such trigger remains; set the value explicitly to pin it. See [Workflow service - Execution Events](./workflow.md#execution-events).
185
+
155
186
  ### Multi-Event Triggers
156
187
 
157
188
  Handle multiple event types in a single executor using multi-event trigger factories. These accept an `events` array of short event names:
@@ -200,7 +231,14 @@ idpUserTrigger({ events: ["created", "deleted"], idp: "my-idp" });
200
231
  authAccessTokenTrigger({ events: ["issued", "revoked"] });
201
232
  ```
202
233
 
203
- The `event` field on args matches the short event name (e.g., `"created"`, `"updated"`, `"deleted"`, `"issued"`, `"refreshed"`, `"revoked"`), enabling type narrowing. The `rawEvent` field contains the full event type string (e.g., `"tailordb.type_record.created"`).
234
+ #### `workflowExecutionTrigger()` and `workflowJobExecutionTrigger()`
235
+
236
+ ```typescript
237
+ workflowExecutionTrigger({ workflow: orderWorkflow, events: ["started", "completed"] });
238
+ workflowJobExecutionTrigger({ workflow: orderWorkflow, events: ["started", "wait_resolved"] });
239
+ ```
240
+
241
+ The `event` field on args matches the short event name, enabling type narrowing. Record triggers use names such as `"created"`, auth token triggers use `"issued"`, and workflow triggers use `"started"`, `"completed"`, and `"wait_resolved"`. The `rawEvent` field contains the full event type string (e.g., `"tailordb.type_record.created"`).
204
242
 
205
243
  ## Operation Types
206
244
 
@@ -554,3 +592,45 @@ interface AuthAccessTokenContext {
554
592
  userId: string; // The user associated with the token
555
593
  }
556
594
  ```
595
+
596
+ ### Workflow Execution Event Payload
597
+
598
+ Workflow execution triggers receive execution context:
599
+
600
+ ```typescript
601
+ interface WorkflowExecutionContext {
602
+ workspaceId: string; // Workspace identifier
603
+ env: TailorEnv; // Environment variables from tailor.config.ts
604
+ actor: TailorActor | null; // Principal that triggered the workflow
605
+ workflowId: string; // Workflow resource ID
606
+ workflowName: string; // Workflow name
607
+ workflowExecutionId: string; // Workflow execution ID
608
+ event: "started" | "completed" | "retried" | "resumed" | "wait_started" | "wait_resolved";
609
+ rawEvent: string; // Full event type
610
+ }
611
+ ```
612
+
613
+ Completed events narrow on `success`. Failed executions include `error`; retried executions include `retryCount` and `retryAfter`.
614
+
615
+ ```typescript
616
+ body: async (args) => {
617
+ if (args.event === "completed" && !args.success) {
618
+ console.error(args.error);
619
+ }
620
+ };
621
+ ```
622
+
623
+ ### Workflow Job Execution Event Payload
624
+
625
+ Workflow job execution triggers include every `WorkflowExecutionContext` field above, plus job-specific fields:
626
+
627
+ ```typescript
628
+ interface WorkflowJobExecutionContext {
629
+ workflowJobExecutionId: string; // Job execution ID
630
+ jobFunctionName: string; // Name passed to createWorkflowJob
631
+ event: "started" | "completed" | "wait_started" | "wait_resolved";
632
+ rawEvent: string; // Full event type
633
+ }
634
+ ```
635
+
636
+ `wait_started` events include `waitKey`, plus JSON-serialized `waitPayload` when the wait point recorded one; `wait_resolved` events include `waitKey`.
@@ -195,7 +195,7 @@ defineIdp("my-idp", {
195
195
 
196
196
  - `enableMfa` - Make TOTP MFA available for users in this namespace. Default `false`. When enabled, users can register an authenticator app (Google Authenticator, 1Password, etc.) from the IdP self-service page.
197
197
  - `requireMfa` - Force password-authenticated users to enroll and pass an MFA challenge on each sign-in. Default `false`. Social sign-in (`allowGoogleOauth` / `allowMicrosoftOauth`) is not affected; the upstream provider's MFA covers those sessions.
198
- - `allowedReturnOrigins` - Origins the IdP self-service pages (such as `/mfa/settings`) are allowed to redirect back to. Each entry is either a literal origin (`https://app.example.com`, scheme + host + optional port, no path/query/fragment) or a static-website placeholder `<name>:url` (e.g. `website.url`) that the CLI resolves to the deployed website's URL at apply time. Required when `enableMfa` is `true`.
198
+ - `allowedReturnOrigins` - Origins the IdP self-service pages (such as `/mfa/settings`) are allowed to redirect back to. Each entry is either a literal origin (`https://app.example.com`, scheme + host + optional port, no path/query/fragment) or a static-website placeholder `<name>:url` (e.g. `website.url`) that the CLI resolves to the deployed website's URL at deployment time. Required when `enableMfa` is `true`.
199
199
  - `mfaIssuer` - Label shown next to the user account in authenticator apps when TOTP is enrolled. Up to 64 characters. Falls back to `"Tailor Platform IdP"` when empty.
200
200
 
201
201
  **Constraints:** the following combinations are rejected at parse time.
@@ -319,21 +319,23 @@ defineIdp("my-idp", {
319
319
 
320
320
  **Values:** `"en"` or `"ja"`.
321
321
 
322
- ### publishUserEvents
322
+ ### publishEvents
323
323
 
324
324
  Publish IdP user lifecycle events (`idp.user.created`, `idp.user.updated`, `idp.user.deleted`). These events are consumed by executors that use `idpUserCreatedTrigger`, `idpUserUpdatedTrigger`, `idpUserDeletedTrigger`, or `idpUserTrigger`.
325
325
 
326
326
  ```typescript
327
327
  defineIdp("my-idp", {
328
328
  clients: ["my-client"],
329
- publishUserEvents: true,
329
+ publishEvents: true,
330
330
  });
331
331
  ```
332
332
 
333
- **Auto-configuration:** When `publishUserEvents` is omitted, the SDK enables it automatically during `apply` for each IdP that is targeted by an executor's `idpUser` trigger. Targeting is per-IdP: an executor specifies which IdP it subscribes to via the trigger's `idp` option (required in multi-IdP projects). Set the value explicitly to override:
333
+ **Auto-configuration:** When `publishEvents` is omitted, `deploy` sets it from the executors taking part in the same run: `true` while one of their `idpUser` triggers targets this IdP, and `false` once none does. Removing the last such trigger turns publishing back off on the next `deploy`. Targeting is per-IdP: an executor specifies which IdP it subscribes to via the trigger's `idp` option (required in multi-IdP projects). Set the value explicitly to override:
334
334
 
335
- - `publishUserEvents: true`: always publish events.
336
- - `publishUserEvents: false`: never publish events. `apply` rejects this with an error if any executor's `idpUser` trigger targets this IdP — either remove `publishUserEvents: false` or remove the matching trigger.
335
+ - `publishEvents: true`: always publish events.
336
+ - `publishEvents: false`: never publish events. `deploy` rejects this with an error if an `idpUser` trigger taking part in the same run targets this IdP — either remove `publishEvents: false` or remove the matching trigger.
337
+
338
+ **Sharing an IdP across configs:** an executor in another config auto-enables publishing the same way, as long as both configs take part in the same `deploy` (`--config a,b`). `deploy` records that dependency, so deploying the owning config alone later asks for confirmation instead of silently turning publishing off — it fails outright in a non-interactive environment. Set `publishEvents: true` on the IdP to keep it on regardless of which configs take part.
337
339
 
338
340
  ## Using idp.provider()
339
341