@tailor-platform/sdk 2.21.0 → 2.23.0

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 (119) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/agent-skills/tailor/SKILL.md +3 -1
  3. package/dist/aigateway-DsWDjzk4.mjs.map +1 -1
  4. package/dist/application-BtZ8hmx9.mjs +1 -0
  5. package/dist/{application-D4913edS.mjs → application-m2G91kKI.mjs} +29 -29
  6. package/dist/application-m2G91kKI.mjs.map +1 -0
  7. package/dist/assert-WeXvmG4j.mjs.map +1 -1
  8. package/dist/authconnection-CynFBIv8.mjs.map +1 -1
  9. package/dist/brand-C8nMKhJC.mjs.map +1 -1
  10. package/dist/cli/commands/deploy/app-id-lock.d.mts +31 -0
  11. package/dist/cli/lib.d.mts +2 -2
  12. package/dist/cli/lib.mjs +1 -1
  13. package/dist/cli/lib.mjs.map +1 -1
  14. package/dist/cli/main.mjs +41 -41
  15. package/dist/cli/main.mjs.map +1 -1
  16. package/dist/cli/shared/client.d.mts +17 -2
  17. package/dist/cli/shared/logger.d.mts +9 -0
  18. package/dist/cli/shared/tailordb-namespaces.d.mts +1 -1
  19. package/dist/completion/zsh-worker.zsh +13 -7
  20. package/dist/configure/config/index.d.mts +2 -0
  21. package/dist/configure/index.mjs.map +1 -1
  22. package/dist/context-D0QjfxzD.mjs.map +1 -1
  23. package/dist/crashreport-CBaRJl5h.mjs +1 -0
  24. package/dist/{crashreport-BAz-ph5O.mjs → crashreport-DFpRn-LS.mjs} +4 -4
  25. package/dist/crashreport-DFpRn-LS.mjs.map +1 -0
  26. package/dist/date-Dri6Yas-.mjs.map +1 -1
  27. package/dist/errors-CpvSChyL.mjs +7 -0
  28. package/dist/errors-CpvSChyL.mjs.map +1 -0
  29. package/dist/es-builtins-SfvXRVoG.mjs.map +1 -1
  30. package/dist/field-parse-DhnFs9WG.mjs.map +1 -1
  31. package/dist/file-DKBOj5q4.mjs.map +1 -1
  32. package/dist/globals-BCmGX05J.mjs.map +1 -1
  33. package/dist/guards-yDXyKC9F.mjs +2 -0
  34. package/dist/guards-yDXyKC9F.mjs.map +1 -0
  35. package/dist/iconv-DlFMt2gW.mjs.map +1 -1
  36. package/dist/idp-G_ojPBB5.mjs.map +1 -1
  37. package/dist/interceptor-DQg3cR_9.mjs.map +1 -1
  38. package/dist/kysely/index.mjs.map +1 -1
  39. package/dist/kysely-type-C-iyFFH7.mjs.map +1 -1
  40. package/dist/logger-DP2BjQ93.mjs.map +1 -1
  41. package/dist/logger-Db-YRTwK.mjs +9 -0
  42. package/dist/logger-Db-YRTwK.mjs.map +1 -0
  43. package/dist/{manager-C0dE7pd0.mjs → manager-8-JOvuLl.mjs} +2 -2
  44. package/dist/manager-8-JOvuLl.mjs.map +1 -0
  45. package/dist/multiline-EyzjEwn9.mjs.map +1 -1
  46. package/dist/node-builtins-DYfhPBnz.mjs.map +1 -1
  47. package/dist/package-json-C690ceex.mjs.map +1 -1
  48. package/dist/platform-serialize-DkiTdHOt.mjs.map +1 -1
  49. package/dist/plugin/builtin/enum-constants/index.mjs.map +1 -1
  50. package/dist/plugin/builtin/file-utils/index.mjs.map +1 -1
  51. package/dist/plugin/index.mjs +1 -1
  52. package/dist/plugin/index.mjs.map +1 -1
  53. package/dist/register-ts-hook-ztnEFW6n.mjs +922 -0
  54. package/dist/register-ts-hook-ztnEFW6n.mjs.map +1 -0
  55. package/dist/registry-BijIDRVA.mjs.map +1 -1
  56. package/dist/repl-editor-DGJBfIt1.mjs.map +1 -1
  57. package/dist/schema-CRtAmDcl.mjs.map +1 -1
  58. package/dist/secret-file-C9wp_FCX.mjs.map +1 -1
  59. package/dist/secretmanager-5olfnI1b.mjs.map +1 -1
  60. package/dist/secretmanager-vHQoXdQz.mjs.map +1 -1
  61. package/dist/seed/index.mjs +7 -6
  62. package/dist/seed/index.mjs.map +1 -1
  63. package/dist/seed-C3P_T_Eh.mjs.map +1 -1
  64. package/dist/service-Bx-7Lz06.mjs +1 -0
  65. package/dist/{service-BrGSi2IQ.mjs → service-CL1Bp4It.mjs} +3 -3
  66. package/dist/service-CL1Bp4It.mjs.map +1 -0
  67. package/dist/{service-8xznUrPU.mjs → service-DFmt9UJP.mjs} +2 -2
  68. package/dist/service-DFmt9UJP.mjs.map +1 -0
  69. package/dist/service_pb-ZClWtj1X.mjs +2 -0
  70. package/dist/service_pb-ZClWtj1X.mjs.map +1 -0
  71. package/dist/service_pb-dB3RrGeh.mjs +1 -0
  72. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +83 -1
  73. package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +7 -1
  74. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +79 -7
  75. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +40 -1
  76. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +119 -2
  77. package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +7 -0
  78. package/dist/tailordb-ddl-DqInYupv.mjs.map +1 -1
  79. package/dist/telemetry-Bklv9kQY.mjs.map +1 -1
  80. package/dist/type-source--ZNcV8RJ.mjs.map +1 -1
  81. package/dist/user-agent-vdHYF3QL.mjs.map +1 -1
  82. package/dist/utils/test/index.mjs.map +1 -1
  83. package/dist/vitest/environment.mjs.map +1 -1
  84. package/dist/vitest/index.mjs.map +1 -1
  85. package/dist/vitest/mocks/file.d.mts +1 -1
  86. package/dist/vitest/setup.mjs.map +1 -1
  87. package/dist/wait-point-invoker-eiP-IIux.mjs.map +1 -1
  88. package/dist/wait-point-registry-B-ESkTZX.mjs.map +1 -1
  89. package/dist/workflow-Cs9ISw6j.mjs.map +1 -1
  90. package/dist/{workspace_resource_pb-D2njwgsE.mjs → workspace_resource_pb-CxR_6fyN.mjs} +2 -2
  91. package/dist/workspace_resource_pb-CxR_6fyN.mjs.map +1 -0
  92. package/docs/cli/application.md +23 -5
  93. package/docs/cli/function.md +2 -2
  94. package/docs/cli-reference.md +22 -12
  95. package/docs/configuration.md +1 -1
  96. package/docs/github-actions.md +90 -24
  97. package/docs/migration/v2.md +70 -5
  98. package/docs/plugin/index.md +1 -1
  99. package/package.json +10 -10
  100. package/dist/application-D4913edS.mjs.map +0 -1
  101. package/dist/application-DBHaxmJE.mjs +0 -1
  102. package/dist/crashreport-BAz-ph5O.mjs.map +0 -1
  103. package/dist/crashreport-BfOkOFgc.mjs +0 -1
  104. package/dist/errors-sNtg2Mv3.mjs +0 -7
  105. package/dist/errors-sNtg2Mv3.mjs.map +0 -1
  106. package/dist/guards-DsX7dJCP.mjs +0 -2
  107. package/dist/guards-DsX7dJCP.mjs.map +0 -1
  108. package/dist/logger-Cp5U2IDI.mjs +0 -9
  109. package/dist/logger-Cp5U2IDI.mjs.map +0 -1
  110. package/dist/manager-C0dE7pd0.mjs.map +0 -1
  111. package/dist/register-ts-hook-YtsAGTMD.mjs +0 -921
  112. package/dist/register-ts-hook-YtsAGTMD.mjs.map +0 -1
  113. package/dist/service-8xznUrPU.mjs.map +0 -1
  114. package/dist/service-BrGSi2IQ.mjs.map +0 -1
  115. package/dist/service-DWMm-4Vm.mjs +0 -1
  116. package/dist/service_pb-DNskuJQC.mjs +0 -1
  117. package/dist/service_pb-y2GYIgfs.mjs +0 -2
  118. package/dist/service_pb-y2GYIgfs.mjs.map +0 -1
  119. package/dist/workspace_resource_pb-D2njwgsE.mjs.map +0 -1
@@ -167,12 +167,20 @@ Before applying changes, `deploy` shows a preview of the planned resource change
167
167
  - `-` means the resource will be deleted
168
168
  - `±` means the resource will be replaced
169
169
 
170
+ An update marked `[forced by SDK version]` shows no configuration difference from what is deployed. It is applied again only because resources of this application were last deployed with a different SDK version.
171
+
170
172
  After the detailed list, a summary line is printed:
171
173
 
172
174
  ```text
173
175
  Plan: 5 to create, 3 to update, 1 to delete
174
176
  ```
175
177
 
178
+ When some updates are forced by the SDK version, the summary line also shows how many:
179
+
180
+ ```text
181
+ Plan: 0 to create, 12 to update (11 forced by SDK version), 0 to delete
182
+ ```
183
+
176
184
  Use `--dry-run` to preview the plan without applying anything. In dry-run mode the plan is written to **stdout**, so it can be captured in CI without `2>&1`:
177
185
 
178
186
  ```bash
@@ -189,9 +197,16 @@ Pass the global `--json` / `-j` flag to get machine-readable output.
189
197
 
190
198
  ```json
191
199
  {
192
- "summary": { "create": 2, "update": 1, "delete": 0, "replace": 0 },
200
+ "summary": { "create": 2, "update": 2, "delete": 0, "replace": 0, "forcedBySdkVersion": 1 },
193
201
  "changes": [
194
- { "action": "create", "name": "Order", "labels": ["table"], "namespace": "tailordb" }
202
+ { "action": "create", "name": "Order", "labels": ["table"], "namespace": "tailordb" },
203
+ {
204
+ "action": "update",
205
+ "name": "Customer",
206
+ "labels": ["table"],
207
+ "namespace": "tailordb",
208
+ "forcedBySdkVersion": true
209
+ }
195
210
  ],
196
211
  "warnings": [
197
212
  { "type": "unmanaged", "resourceType": "tailorDB", "name": "LegacyType" },
@@ -201,15 +216,18 @@ Pass the global `--json` / `-j` flag to get machine-readable output.
201
216
  }
202
217
  ```
203
218
 
204
- - `summary` — counts of each change type.
205
- - `changes` — planned resource changes, each with `action`, `name`, and optional `labels` / `namespace`.
219
+ - `summary` — counts of each change type. `forcedBySdkVersion` counts the updates forced by the SDK version, which are also included in `update`.
220
+ - `changes` — planned resource changes, each with `action`, `name`, and optional `labels` / `namespace`. An update forced by the SDK version also has `forcedBySdkVersion: true`.
206
221
  - `warnings` — resources not in config (`type: "unmanaged"`) or secrets with missing values (`type: "skippedSecret"`). Unmanaged resources require confirmation in apply mode (apply is cancelled if declined); skipped secrets are non-blocking.
207
222
  - `conflicts` — resources owned by another application that conflict with the current config. Require confirmation in apply mode; apply is cancelled if declined.
208
223
 
209
224
  **Apply** (`--json`): writes a JSON object to stdout:
210
225
 
211
226
  ```json
212
- { "summary": { "create": 1, "update": 2, "delete": 0, "replace": 0 }, "status": "applied" }
227
+ {
228
+ "summary": { "create": 1, "update": 2, "delete": 0, "replace": 0, "forcedBySdkVersion": 0 },
229
+ "status": "applied"
230
+ }
213
231
  ```
214
232
 
215
233
  ## remove
@@ -129,9 +129,9 @@ $ tailor function logs <execution-id> --follow
129
129
 
130
130
  **Notes**
131
131
 
132
- Execution details include `logEntries`, the structured log lines (message, severity, timestamp) recorded while the function ran. They are available while the execution is still running, whereas the flat `logs` string is filled in only after completion. The human-readable view shows the structured entries when present and falls back to `logs` otherwise.
132
+ Execution details include `logEntries`, the structured log lines (message, severity, timestamp) recorded while the function ran. They are available while the execution is still running. The `logs` string joins their messages with newlines.
133
133
 
134
- Use `--follow` to keep polling a running execution and print new log entries as they arrive until it completes. Polling continues while the execution is suspended at a wait point, and indefinitely unless `--timeout` is set. On environments where no structured entries are returned, `--follow` shows the flat `logs` string once the execution completes. With `--json`, `--follow` waits for completion and then emits the final execution details once.
134
+ Use `--follow` to keep polling a running execution and print new log entries as they arrive until it completes. Polling continues while the execution is suspended at a wait point, and indefinitely unless `--timeout` is set. With `--json`, `--follow` waits for completion and then emits the final execution details once.
135
135
 
136
136
  When viewing a specific execution that failed, the command displays error details with the stack trace mapped back to your original source files (clickable file links and code snippets, matching `function run` output).
137
137
 
@@ -12,12 +12,12 @@ tailor <command> [options]
12
12
 
13
13
  <a id="global-options"></a>
14
14
 
15
- | Option | Alias | Description | Required | Default |
16
- | ------------------------------------------- | ----- | --------------------------------------------------- | -------- | ------- |
17
- | `--env-file <ENV_FILE>` | `-e` | Path to the environment file (error if not found) | No | - |
18
- | `--env-file-if-exists <ENV_FILE_IF_EXISTS>` | - | Path to the environment file (ignored if not found) | No | - |
19
- | `--verbose` | - | Enable verbose logging | No | `false` |
20
- | `--json` | `-j` | Output as JSON | No | `false` |
15
+ | Option | Alias | Description | Required | Default | Env |
16
+ | ------------------------------------------- | ----- | --------------------------------------------------- | -------- | ------- | -------------------- |
17
+ | `--env-file <ENV_FILE>` | `-e` | Path to the environment file (error if not found) | No | - | - |
18
+ | `--env-file-if-exists <ENV_FILE_IF_EXISTS>` | - | Path to the environment file (ignored if not found) | No | - | - |
19
+ | `--verbose` | - | Enable verbose logging | No | `false` | - |
20
+ | `--json` | `-j` | Output as JSON | No | `false` | `TAILOR_JSON_OUTPUT` |
21
21
 
22
22
  ### Progress and Detailed Logs
23
23
 
@@ -34,6 +34,14 @@ human-readable text or empty stdout.
34
34
  Commands that only perform side effects and do not define a structured result may leave stdout empty
35
35
  even when `--json` is passed.
36
36
 
37
+ Set `TAILOR_JSON_OUTPUT=true` (or `1`) to default every command to JSON without passing `--json`
38
+ each time. This is intended for agents, scripts, and CI steps that parse CLI output. An explicit
39
+ flag always wins, so `--json=false` forces table output even when the variable is enabled. The values
40
+ `true`, `True`, `TRUE`, `t`, `T`, and `1` enable JSON; `false`, `False`, `FALSE`, `f`, `F`, and `0`
41
+ keep table output. Other values are rejected. JSON mode also disables interactive prompts, so set the
42
+ variable per invocation or per job rather than exporting it from a shell profile; a command that
43
+ needed a prompt names what selected JSON when it refuses.
44
+
37
45
  Errors, warnings, progress, and diagnostic messages are written to stderr. After argument parsing,
38
46
  a command failure under `--json` emits a JSON error envelope to stderr. Failures you can act on — an
39
47
  invalid or missing option, a resource that does not exist, an invalid configuration, or an unmet
@@ -96,14 +104,15 @@ is unchanged. Workflows that already echo their own `::error::` around the CLI k
96
104
  those messages describe the workflow's own checks, which can fail even when the CLI succeeds.
97
105
 
98
106
  When the failure has a known source, the annotation carries it: `seed validate` reports the
99
- offending JSONL file and line, and a rejected config reports its file — or, when the config or a
100
- file it imports cannot be parsed, that file and the line it failed on. Locations are written
101
- relative to `GITHUB_WORKSPACE`; a file outside it is annotated without a location rather than with
102
- a path the runner cannot resolve.
107
+ offending JSONL file and line, including a line that is not valid JSON, and a rejected config
108
+ reports its file — or, when the config or a file it imports cannot be parsed, that file and the line
109
+ it failed on. Locations are written relative to `GITHUB_WORKSPACE`; a file outside it is annotated
110
+ without a location rather than with a path the runner cannot resolve.
103
111
 
104
112
  For a JSONL file containing a blank line, the annotation's line and the line printed in the report
105
113
  text differ: the annotation counts every line in the file, while the printed line counts only the
106
- records. The annotation points at the row as an editor numbers it.
114
+ records. The annotation points at the row as an editor numbers it. A line that is not valid JSON is
115
+ printed with the line an editor shows, so both agree.
107
116
 
108
117
  `generate` and `deploy` do not group their per-service progress.
109
118
 
@@ -225,7 +234,8 @@ Resolution rules:
225
234
  then forwarded, so when the same flag appears on both sides the later one wins. A flag the host
226
235
  does not define — including one only some commands declare, such as `--profile` — still has to be
227
236
  typed after the plugin's own subcommand. `--help` and `--version` are answered by the host CLI and
228
- never dispatch a plugin.
237
+ never dispatch a plugin. Setting `TAILOR_JSON_OUTPUT=true` also works, which plugins inherit from
238
+ the environment.
229
239
 
230
240
  Because resolution is based on `node_modules/.bin` and `PATH`, any package manager that populates
231
241
  `node_modules/.bin` works for project-local plugins — npm, pnpm (its content-addressable store is
@@ -403,7 +403,7 @@ export default defineConfig({
403
403
 
404
404
  ### Plugins
405
405
 
406
- Configure plugins using `definePlugins()`. Plugins must be exported as a named export.
406
+ Configure plugins using `definePlugins()`, exported as `export const plugins`.
407
407
 
408
408
  ```typescript
409
409
  import { definePlugins } from "@tailor-platform/sdk";
@@ -68,7 +68,9 @@ What it does:
68
68
  applies the config; it does not re-run the PR plan.
69
69
  - On **`workflow_dispatch`** with `dry-run: true`: runs plan only (useful for
70
70
  rollback verification — see [Rollback](#rollback)). With `dry-run: false`
71
- (default) it deploys, like a push.
71
+ (default) it deploys the selected branch, like a push. Pass
72
+ `--restrict-dispatch` to deploy only the target branch this way (see
73
+ [Restricting manual deploys](#restricting-manual-deploys)).
72
74
 
73
75
  Fork pull requests cannot read repository secrets. For forks, the plan step is
74
76
  automatically skipped; `generate-check` and other non-secret checks still run.
@@ -129,7 +131,9 @@ What it does:
129
131
  before the deploy job starts.
130
132
  - On **`workflow_dispatch`**: the `tailor-tag-guard` result is ignored — the
131
133
  plan job runs regardless of branch reachability (useful for rolling back to
132
- any tag). `dry-run: true` stops before the deploy job.
134
+ any tag). `dry-run: true` stops before the deploy job. With
135
+ `--restrict-dispatch`, the deploy job runs only for a tag that passes the
136
+ guard (see [Restricting manual deploys](#restricting-manual-deploys)).
133
137
 
134
138
  ### Choosing `--branch` for the tag target
135
139
 
@@ -190,20 +194,53 @@ Running a workflow setup subcommand creates or updates:
190
194
  The workflow file. The `name:` field is set to `Tailor (<workspace-name>)` so
191
195
  you can distinguish multiple workspaces in the Actions UI.
192
196
 
193
- Jobs and steps whose `id` starts with `tailor-` are managed by the SDK. Do not
194
- edit or rename them — the SDK tracks them by id.
195
-
196
- You can add your own jobs and steps around the managed ones. To add
197
- project-specific setup (such as private registry authentication or a system
198
- dependency), add a step _before_ the managed `tailor-setup` step. For
199
- post-install extras (such as `playwright install`), add a step _after_ it.
200
-
201
- Note that re-running `setup` currently regenerates the whole file: if
202
- the file differs from what the SDK last wrote — whether you edited a managed
203
- step or added your own — the command stops and reports the conflict. Pass
204
- `--force` to discard your edits and regenerate from the current template, then
205
- re-apply your own steps. (Preserving user-added steps across regeneration is
206
- planned.)
197
+ See [Customizing the generated workflow](#customizing-the-generated-workflow)
198
+ for what you can edit.
199
+
200
+ ### Customizing the generated workflow
201
+
202
+ The SDK owns the jobs and steps whose `id` starts with `tailor-`, and the
203
+ top-level keys it writes (`name:`, `on:`, and `permissions:` in a workflow; the
204
+ metadata, inputs, and outputs of a composite action). Do not edit or rename
205
+ them. Everything else is yours, and re-running `setup` keeps it:
206
+
207
+ - **Your own jobs and steps.** Add them anywhere, without the `tailor-` prefix.
208
+ A step you add inside a managed job stays right after the managed step it
209
+ followed. For example, add private registry authentication or a system
210
+ dependency _before_ the managed `tailor-setup` step, and post-install extras
211
+ (such as `playwright install`) _after_ it. A job of your own can depend on a
212
+ managed job with `needs: tailor-deploy`.
213
+ - **Your own top-level keys**, such as a workflow-level `env:` or `defaults:`.
214
+ - **Runtime settings of managed jobs:** `runs-on`, `timeout-minutes`,
215
+ `container`, and `env`.
216
+ - **These inputs of managed steps:** `ignore` on `tailor-generate-check` and
217
+ `tailor-drift-check`, `fail-on-drift` on `tailor-drift-check`,
218
+ `install-command` on `tailor-install`, `node-version-file` on
219
+ `tailor-setup`, `label` on `tailor-plan`, and `user-mapping` on
220
+ `tailor-notify` and on a coordinator's steps that call an app action.
221
+ - **The `run:` command of the `build-site` step** in a composite action.
222
+
223
+ Comments above your own jobs and steps and at the end of the file are kept too.
224
+ Comments inside managed jobs and steps, and edits to the header comment, are
225
+ not kept.
226
+
227
+ `setup check` reports an edit to a managed part, and re-running `setup` stops
228
+ on it. Revert the edit, or pass `--force` to reset the managed parts to the
229
+ current template; `--force` still keeps your own jobs, steps, and settings.
230
+ A managed job or step you renamed counts as your own, so `--force` adds the
231
+ managed one back next to it; rename it back instead of forcing. To start over
232
+ from a clean template, delete the file and re-run `setup`.
233
+
234
+ When a template update removes a managed job that contains steps of yours, or
235
+ a job of yours `needs` a removed job, `setup` stops and names them. Move those
236
+ steps into a job of your own (or update the `needs`) and re-run. `--force` drops
237
+ steps left inside a removed job. It also stops when a new template version adds
238
+ a managed job or step whose id you already use; rename yours, or pass `--force`
239
+ to let the managed one replace it.
240
+
241
+ Files generated by an older SDK version are compared as a whole, so the first
242
+ re-run after upgrading stops if you edited the file in any way. Re-run once with
243
+ `--force` to switch it to this model; your own jobs and steps are kept.
207
244
 
208
245
  ### `.github/tailor.lock`
209
246
 
@@ -277,7 +314,8 @@ gh secret set TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET --env my-app-stg
277
314
  Setting them at the environment level isolates each target's credentials and
278
315
  keeps them alongside that environment's `TAILOR_PLATFORM_WORKSPACE_ID`
279
316
  variable. You can also set them as repository-level secrets if every target
280
- shares one machine user.
317
+ shares one machine user, but then any workflow on any branch can read them, so
318
+ the environment's protection rules no longer guard your deploys.
281
319
 
282
320
  ## GitHub Environments (approval gate)
283
321
 
@@ -309,8 +347,32 @@ or an out-of-band deploy. With `dry-run` off, a branch-target dispatch goes
309
347
  straight to deploy (like a push), while a tag-target dispatch runs plan first
310
348
  and then deploys.
311
349
 
312
- For tag targets, you can select any branch or tag when dispatching manually. The tag-guard check is skipped for manual dispatches, so
313
- you can deploy any commit regardless of branch membership.
350
+ By default you can select any branch or tag when dispatching manually, and it
351
+ deploys that ref. For tag targets, the tag-guard check is skipped for manual
352
+ dispatches, so you can deploy any commit regardless of branch membership.
353
+
354
+ ### Restricting manual deploys
355
+
356
+ Pass `--restrict-dispatch` to `setup ci branch`, `setup ci tag`, or
357
+ `setup ci coordinate` to limit what a manual dispatch with `dry-run` off can
358
+ deploy:
359
+
360
+ - **Branch target:** only the target branch. Dispatching another branch skips
361
+ the deploy job.
362
+ - **Tag target:** only a tag. With `--branch`, the tag must also pass the
363
+ reachability guard. The tag does not have to match `--tag-pattern`.
364
+
365
+ Dry runs stay available from any ref. Re-run `setup` with the flag each time you
366
+ regenerate the workflow; it is not carried over from the previous run.
367
+
368
+ The flag guards against deploying the wrong ref by mistake. It is not an access
369
+ control: a manual dispatch runs the workflow file from the selected ref, so
370
+ anyone who can push a branch can remove the check there. To enforce which refs
371
+ can deploy, configure **Deployment branches and tags** on the target's GitHub
372
+ Environment and keep the machine-user secrets on that environment. Because the
373
+ plan job also enters the environment, allow `refs/pull/*/merge` as well so pull
374
+ request plans keep running, and note that dry runs from other branches are then
375
+ rejected too.
314
376
 
315
377
  ## Monorepo setup
316
378
 
@@ -365,6 +427,8 @@ git push origin v1.2.4
365
427
 
366
428
  For tag targets, the tag-guard step is bypassed on manual dispatch, so you can
367
429
  dispatch from any ref. Environment approval (if configured) applies as usual.
430
+ With `--restrict-dispatch`, step 4 deploys only a tag that passes the guard, and
431
+ a branch target deploys only its target branch, so use Option 1 there.
368
432
 
369
433
  ### Rollback limitations
370
434
 
@@ -445,7 +509,8 @@ subcommand.
445
509
 
446
510
  `tailor setup check` audits the workflows recorded in
447
511
  `.github/tailor.lock` against your current config and repository, without
448
- writing anything. It reports when a workflow file is missing or hand-edited, a
512
+ writing anything. It reports when a workflow file is missing or its SDK-managed
513
+ parts were edited by hand, a
449
514
  newer template is available, `tailor.config.ts` is no longer under the recorded
450
515
  `--dir`, or the repository default branch no longer matches a branch target's
451
516
  trigger. It exits non-zero when it finds drift, so you can run it in CI. Each
@@ -474,10 +539,11 @@ itself at runtime.
474
539
  ## Updating the generated workflow
475
540
 
476
541
  When you upgrade the SDK, re-run the relevant workflow setup subcommand with
477
- the same flags to pick up template improvements. If the SDK detects that you
478
- have hand-edited a managed section, it stops and asks you to use `--force` to
479
- overwrite your edits, or to move your customizations into your own steps before
480
- regenerating.
542
+ the same flags to pick up template improvements. Your own jobs, steps, and
543
+ settings are kept (see
544
+ [Customizing the generated workflow](#customizing-the-generated-workflow)). If
545
+ you edited a managed part, the command stops; revert the edit or pass `--force`
546
+ to reset it.
481
547
 
482
548
  The `.github/tailor.lock` file records the flags used at generation time,
483
549
  so you can check what arguments were used previously.
@@ -84,18 +84,83 @@ After:
84
84
  import { definePlugins } from "@tailor-platform/sdk";
85
85
  import { kyselyTypePlugin } from "@tailor-platform/sdk/plugin/kysely-type";
86
86
 
87
- export const generators = definePlugins(kyselyTypePlugin({ distPath: "db.ts" }));
87
+ export const plugins = definePlugins(kyselyTypePlugin({ distPath: "db.ts" }));
88
88
  ```
89
89
 
90
90
  <details>
91
91
  <summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
92
92
 
93
93
  ```text
94
- defineGenerators() is replaced by definePlugins() in v2. The codemod rewrites the
95
- known plugin tuples (kysely-type, enum-constants, file-utils, seed). For any
96
- remaining defineGenerators([...]) the codemod left in place — a plugin it does not
94
+ defineGenerators() is replaced by definePlugins() in v2, exported as `plugins` — the
95
+ only export name the SDK reads plugins from. The codemod rewrites the known plugin
96
+ tuples (kysely-type, enum-constants, file-utils, seed) and renames the export variable
97
+ to `plugins` (left alone when the file already binds `plugins` to something else). For
98
+ any remaining defineGenerators([...]) the codemod left in place — a plugin it does not
97
99
  know, or a non-tuple/spread form — convert it to definePlugins(pluginFn(config)),
98
- importing the matching plugin from its @tailor-platform/sdk/plugin/<name> subpath.
100
+ importing the matching plugin from its @tailor-platform/sdk/plugin/<name> subpath, and
101
+ assign the result to `export const plugins`.
102
+ Merge any remaining exported plugin arrays into `plugins`, including bindings
103
+ exported separately with `export { ... }`, and update their importing files.
104
+ Only tailor.config module exports are renamed automatically; preserve helper-module
105
+ exports and expose their plugins under the canonical config export manually.
106
+ ```
107
+
108
+ </details>
109
+
110
+ ## generator/generators → plugins export rename
111
+
112
+ **Migration:** Partially automatic
113
+
114
+ Rename the plugin config export (and its imports) from generator/generators to plugins
115
+
116
+ Before:
117
+
118
+ ```ts
119
+ import { definePlugins } from "@tailor-platform/sdk";
120
+ import myPlugin from "./plugins/my-plugin";
121
+
122
+ export const generators = definePlugins(myPlugin());
123
+ ```
124
+
125
+ After:
126
+
127
+ ```ts
128
+ import { definePlugins } from "@tailor-platform/sdk";
129
+ import myPlugin from "./plugins/my-plugin";
130
+
131
+ export const plugins = definePlugins(myPlugin());
132
+ ```
133
+
134
+ Also updates other files that import the export by its old name.
135
+
136
+ Before:
137
+
138
+ ```ts
139
+ import { generator } from "./tailor.config";
140
+ ```
141
+
142
+ After:
143
+
144
+ ```ts
145
+ import { plugins } from "./tailor.config";
146
+ ```
147
+
148
+ <details>
149
+ <summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
150
+
151
+ ```text
152
+ The SDK only reads plugins from an export named `plugins`; `generator`/`generators` is
153
+ already `definePlugins()` but under the old name. This codemod renames the export (and
154
+ any `import { generator[s] } from ".../tailor.config"` elsewhere) to `plugins`. It
155
+ leaves a file untouched when it already binds `plugins` to something else, or when a
156
+ bare (unaliased) import's local usages cannot be safely told apart from an unrelated
157
+ same-named binding in that file — rename those by hand to `plugins`.
158
+ Multiple arrays or bindings exported separately with `export { ... }` need manual
159
+ consolidation into the `plugins` export; update their importing files as well.
160
+ Only tailor.config module exports are renamed automatically. Review aliased SDK
161
+ factory calls and helper-module re-exports manually, preserving the helper API.
162
+ Indirect config exports, namespace/dynamic imports, and wildcard re-exports are
163
+ conservatively reported for review; keep unrelated values and canonical references unchanged.
99
164
  ```
100
165
 
101
166
  </details>
@@ -33,7 +33,7 @@ export default defineConfig({
33
33
  });
34
34
  ```
35
35
 
36
- **Important**: The `plugins` export must be a named export (not default).
36
+ **Important**: `definePlugins()` must be assigned to a named export called exactly `plugins` (not default, and not any other name).
37
37
 
38
38
  ### Attaching Plugins to Tables
39
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/sdk",
3
- "version": "2.21.0",
3
+ "version": "2.23.0",
4
4
  "description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -164,13 +164,13 @@
164
164
  "@opentelemetry/resources": "2.11.0",
165
165
  "@opentelemetry/sdk-trace-node": "2.11.0",
166
166
  "@opentelemetry/semantic-conventions": "1.43.0",
167
- "@oxc-project/types": "0.149.0",
167
+ "@oxc-project/types": "0.151.0",
168
168
  "@politty/zod": "0.3.0",
169
169
  "@secretlint/core": "13.0.5",
170
170
  "@secretlint/secretlint-rule-preset-recommend": "13.0.5",
171
171
  "@standard-schema/spec": "1.1.0",
172
172
  "@tailor-platform/function-kysely-tailordb": "0.1.3",
173
- "@toiroakr/lines-db": "0.12.7",
173
+ "@toiroakr/lines-db": "0.13.0",
174
174
  "@toiroakr/read-multiline": "0.4.1",
175
175
  "@urql/core": "6.0.3",
176
176
  "amaro": "1.2.1",
@@ -178,7 +178,7 @@
178
178
  "date-fns": "4.4.0",
179
179
  "es-toolkit": "1.52.0",
180
180
  "find-up-simple": "1.0.1",
181
- "get-east-asian-width": "1.6.0",
181
+ "get-east-asian-width": "1.7.0",
182
182
  "get-tsconfig": "4.14.3",
183
183
  "globals": "17.12.0",
184
184
  "graphql": "17.0.2",
@@ -186,19 +186,19 @@
186
186
  "kysely": "0.29.6",
187
187
  "mime-types": "3.0.2",
188
188
  "open": "11.0.4",
189
- "oxc-parser": "0.149.0",
189
+ "oxc-parser": "0.151.0",
190
190
  "p-limit": "7.3.3",
191
191
  "pathe": "2.0.3",
192
192
  "pgsql-ast-parser": "12.0.2",
193
193
  "pkg-types": "2.3.3",
194
- "rolldown": "1.2.9",
194
+ "rolldown": "1.2.11",
195
195
  "semver": "7.8.5",
196
196
  "sql-highlight": "6.1.0",
197
197
  "std-env": "4.2.0",
198
198
  "temporal-polyfill": "1.0.5",
199
199
  "temporal-spec": "1.0.1",
200
200
  "ts-cron-validator": "1.1.5",
201
- "type-fest": "5.9.0",
201
+ "type-fest": "5.10.0",
202
202
  "xdg-basedir": "5.1.0",
203
203
  "zod": "4.6.5"
204
204
  },
@@ -213,9 +213,9 @@
213
213
  "@typescript/native-preview": "7.0.0-dev.20260707.2",
214
214
  "@vitest/coverage-v8": "5.0.1",
215
215
  "eslint-plugin-zod": "4.14.2",
216
- "oxfmt": "0.67.0",
217
- "oxlint": "1.82.0",
218
- "oxlint-tsgolint": "7.0.2002",
216
+ "oxfmt": "0.70.0",
217
+ "oxlint": "1.85.0",
218
+ "oxlint-tsgolint": "7.0.2003",
219
219
  "sonda": "0.14.0",
220
220
  "tsdown": "0.23.0",
221
221
  "typescript": "6.0.3",