mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-16 16:03:14 +00:00
0a343485008d07bd08068447936084329ac02bef
324
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
88c3cc0ced |
feat: guide the AI when no resource type fits a service (#11615)
* feat: guide the AI when no resource type fits a service Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: report a failed resource type search and model a synced instance in evals Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep named resource types first and list only related names on search failure Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: point the sync note at the hub sync button only Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: list the instance's resource types when the search finds nothing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: let the user create a resource type instead of syncing the hub Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: make the linked-variable resource the default, not the only option Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: add a cli eval for a service without a hub resource type Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: keep the resource type search fresh and serve it without embeddings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: let the global chat create a resource type after the user confirms it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: simulate create_resource_type in global evals and fix the in-house API checklists Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: reuse unchanged custom resource type vectors and match names case-insensitively Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: add the unsynced note whatever the resource type search returns Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: carry the no-type rule into flow inputs and script parameters, and ask the chat to relay the sync Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: tell script chat to hand the user the schema it cannot create Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: skip the resource type fingerprint query when no index is loaded Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: index resource types locally when the hub's embeddings cannot be fetched Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: match short service names in the resource type text fallback Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: name custom resource types with the c_ prefix the Resources page uses Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: require the c_ prefix in in-house API evals and a real sync mention Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: cover workspace scoping of the resource type text search Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: say the form adds the c_ prefix unless an admin turns it off Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: refresh resource type names and the resources tab after the chat creates a type Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf: fingerprint resource types without sorting every schema Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: tell the global chat in each message when the hub's types are not synced Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: send users who cannot deploy to an admin for a resource type, and have the cli list types first Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015YR13nJWziUSWktZwhC7dx * refactor: move the resource type search index changes to their own pull request Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015YR13nJWziUSWktZwhC7dx --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b7b3306195 |
feat: read data as the job's identity, viewer is opt-in per runnable (#11744)
* feat: connect a data table as the job's own identity unless the runnable opts into its viewer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: key cached results by the data table mode and keep the flag across ai edits Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: hash the cache key's mode and viewer as fixed fields so no argument name can forge them Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: update ee-repo-ref to 2f74548ad1ec50c8e1faf17e42d5648160e833f1 This commit updates the EE repository reference after PR #878 was merged in windmill-ee-private. Previous ee-repo-ref: 4ad768a777fff9f1ecc86a2803bc27d80f8242d6 New ee-repo-ref: 2f74548ad1ec50c8e1faf17e42d5648160e833f1 Automated by sync-ee-ref workflow. * feat: rename the flag to viewer_data_access and apply it to object storage permission rules Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: describe viewer_data_access as covering object storage rules too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: update ee-repo-ref to 0ffb633473c5465513576afc6f54d18f93c7f1e1 This commit updates the EE repository reference after PR #879 was merged in windmill-ee-private. Previous ee-repo-ref: e9e06a9eb94168f46b378276b01fa0117dc7d8ed New ee-repo-ref: 0ffb633473c5465513576afc6f54d18f93c7f1e1 Automated by sync-ee-ref workflow. * feat: show the viewer data access control as an icon button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
2c6de9d896 |
fix: keep the app editor's parent_version out of deployed apps (#11719)
* fix: keep the app editor's parent_version out of deployed apps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: drop parent_version when deploying an app draft Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
4942149b05 |
feat: encrypt workspace secrets with AES-256-GCM (#11678)
* feat: encrypt workspace secrets with AES-256-GCM Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: note the aead gate covers workers only and is one-way Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: skip secrets the upgrade cannot store and clear its guard on panic Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: start aead secret writes one release after read support Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 06610ecc950ed64a2709d7f1aa8c7b49a95fdbae This commit updates the EE repository reference after PR #869 was merged in windmill-ee-private. Previous ee-repo-ref: 599eae0034b34c5e0d3d42df37cf18bbe01f9b49 New ee-repo-ref: 06610ecc950ed64a2709d7f1aa8c7b49a95fdbae Automated by sync-ee-ref workflow. * feat: widen variable.value to fit AES-GCM ciphertext of the longest legacy secret Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: refuse legacy secrets longer than 15000 chars so every secret can be upgraded Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: cap legacy secrets at 15000 chars with a check constraint so every writer is covered Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
36ea2da0bf |
warn when a raw app sql viewer-identity input is not a ctx field (#11704)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
26afeecbd5 |
feat(cli): declare app sandbox and frontend api scopes in app yaml (#11703)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
54eeb451e4 |
refactor: remove vue as a full-code app framework (#11690)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
cda78830fd |
feat: stop offering deno for new scripts, ship it only on full images (#11648)
* feat: stop offering deno for new scripts and ship it only on full images Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep deno in the integration test worker and narrow the missing-deno error Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep deno selectable on existing deno scripts when the saved order omits it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: drop the deno workloads from the benchmark suite Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: run bun instead of deno in tests that are not about the deno runtime Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: drop the deno cases from the integration suite Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: update the app policy hash for the bun inline script Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1c2667cd55 |
feat: add wmill user list and document post-suspend approvers context (#11600)
* feat: add wmill user list and document post-suspend approvers context Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: approvers holds the resume url approver string when set Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate cli skills for approvers wording Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: update ee-repo-ref to acb254ac509aff244849c09e50a8d39aae185138 This commit updates the EE repository reference after PR #852 was merged in windmill-ee-private. Previous ee-repo-ref: 9cc330f1a8e80bc075a6ad9839966d3b344f8ddd New ee-repo-ref: acb254ac509aff244849c09e50a8d39aae185138 Automated by sync-ee-ref workflow. * fix: drop name column from wmill user list, usr has no name Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: approvalPage resumes record the logged-in user as approver Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
818ddd5d31 |
feat: default new raw apps to react 19 and ask for the data setup (#11586)
* feat: default new raw apps to react 19 and ask for the data setup Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: say what app new --schema writes and soften the already-set-up wording Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: resolve bare init_app table names in the app schema, fix --schema help Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
e7fc1b2e2e |
feat: restricted job tokens per script and flow (#11484)
* feat: restricted job tokens (job_token_scopes on scripts and flows) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: admit flow-run reads, skip dedicated workers, gate on worker version Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep restricted jobs off flow runners, preserve scopes on rename and promotion Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep restricted jobs off every dedicated handoff, confine progress flow id Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: exclude restricted runnables from dedicated worker startup Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: gate restrictions on the release after 1.821.0 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: store per-job scopes on job_perms instead of v2_job, pin inline runs to the checked version Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: step-level job_token_scopes for flow steps and agent tools Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: fail closed on perms read errors, refuse restricted queue imports, gate step scopes in previews Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: carry a job's scopes on its completion so a re-run keeps the caller's cap Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: carry a zombie job's scopes into its completion Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: leave a zombie for the next sweep when its scopes cannot be read Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * docs: correct the QueuedJobV2 completion comment Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: validate step scopes in batch flows, fail closed on unvalidated step scopes Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: refuse flows with step or tool restrictions at push while an older worker is live Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: apply the step-scope worker gate to flow restarts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: list the job token toggle with the other step and flow settings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * chore: pin the EE companion merged with EE main Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * perf: skip scope lookups for unrestricted jobs; list job token setting last Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * style: rustfmt scopes tests Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: confine restricted job tokens to their own run lineage; drop remaining extra lookups Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * chore: update ee-repo-ref to 259ad3bfeef5285ba80eedc86309b11dca001220 This commit updates the EE repository reference after PR #843 was merged in windmill-ee-private. Previous ee-repo-ref: 2b77c0225dca441235daf7bf0a06ba968df0c927 New ee-repo-ref: 259ad3bfeef5285ba80eedc86309b11dca001220 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
99e96d3f78 |
fix: let instances withhold signing secrets from the settings API (#11483)
* fix: never return the instance signing secrets from the settings API Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: tell wmill instance get-config users that jwt_secret is not exported Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: point ee-repo-ref at the oidc signing key fix Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: block rsa_keys from agent workers and keep get-config stdout pure yaml Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep server secrets in exports by default behind EXPORT_SERVER_SECRETS Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 43b2ce8866a393b2666b17647ddb1466afc70bb1 This commit updates the EE repository reference after PR #842 was merged in windmill-ee-private. Previous ee-repo-ref: 3a0d0c3f45eeb9f5fe8d50ce3798239aa9101a22 New ee-repo-ref: 43b2ce8866a393b2666b17647ddb1466afc70bb1 Automated by sync-ee-ref workflow. * fix: withhold server secrets on any non-true EXPORT_SERVER_SECRETS value Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
4beb1f9420 |
feat: add trigger, tag, run-as and digest claims to job OIDC tokens (#11481)
* feat: add trigger, tag, run-as and digest claims to job OIDC tokens Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: parse digest floats exactly and derive the codebase digest like push Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: give flows that reference flow nodes no digest and keep --json clean Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: list flow step digests from module positions only Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test: skip the pulled module-script digest check on windows Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 71b8c1042fd8188c2d2882476f12b671cb5ba421 This commit updates the EE repository reference after PR #840 was merged in windmill-ee-private. Previous ee-repo-ref: ba1870536789a43c5b6ec18522a93edb9cb07f3d New ee-repo-ref: 71b8c1042fd8188c2d2882476f12b671cb5ba421 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
7f1beadf79 |
feat: add wmill datatable migrate status (#11465)
* feat: add wmill datatable migrate status Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: show unpushed local migrations in datatable migrate status Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: move pushLocalMigrations doc comment back onto its function Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1d8d4a16b4 |
fix(cli): resolve fork specific items from the parent workspace entry (#11436)
* test(cli): stop CLI tests resolving a just-published windmill-client Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test: quote the Windows cert path in the pg attach assertion Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(cli): note when the windmill-client pin must move Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cli): resolve fork specific items from the parent workspace entry Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cli): keep fork resolution to the id-guarded inference Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
054109d855 |
fix: create workspace forks in the background, with progress (#11406)
* fix: create a fork in the background so a proxy timeout cannot cut it create_fork copies the whole workspace inside the request, which can run past the route timeout of an ingress in front of Windmill (Envoy's 15s default), and the UI then reports a failure for a fork still being made. create_fork?background=true now returns once the request is validated and records the copy in workspace_fork_creation, which the new fork_creation_status endpoint reads. The wizard and AI-session forks use it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: drain background forks on shutdown and fork in the background from the CLI Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: settle fork polls by the fork's existence, adopt in-flight creations Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: show which part of the copy a fork being created is in The background copy reports its phase (data tables, settings, resources, scripts, flows, apps, drafts, triggers) through a watch channel. The heartbeat task records it on the fork's creation row as soon as it changes, and fork_creation_status returns it. The fork wizard shows it on its button, and the CLI logs each step. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: join a retried fork creation server-side, settle status by the fork's existence A retry from the same user and parent joins the creation in flight instead of being refused, so clients no longer match the refusal's wording, and another requester can never adopt it. The status route reports a fork that exists under its parent as completed, whatever its run's record says. Clients give up on failing polls after a time window rather than a count, which a rolling deploy can exhaust. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: drop fork-creation joins and existence probes A second request for a fork being created is refused again; only the AI-session fork, whose request never varies, waits for its own earlier one. Clients recognise a server without background forks by its synchronous answer instead of probing for a workspace by id, which could name another parent's fork. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: poll a background fork by the id of its own attempt create_fork?background=true answers with a creation id, and the status route reads that attempt only, for the user who started it. A retry that reuses the fork id is a new attempt, so a poller never reads another attempt's outcome. The AI-session fork no longer adopts a creation in flight, which it could not tell apart from someone else's. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: record a fork's completion in its own commit, resume a session's fork after reload The attempt is marked complete in the transaction that creates the fork, so the status never infers completion from a workspace that may belong to another request. An AI session keeps the creation id on its pending fork and, after a reload mid-copy, waits for that attempt instead of requesting the fork again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
ede4103b00 |
feat: share AI guidance with the CLI skills and lint flow groups (#11397)
* feat: lint AI agent tool names and flow groups in wmill lint * refactor: assemble chat and CLI AI guidance from one topic table * feat: share flow groups, reuse and pipeline guidance with the CLI skills * feat: share raw app, data table and secret guidance between chat and CLI * docs: document the shared AI guidance source for contributors * fix: keep wmill lint running on flows with malformed collections * fix: reject skill descriptions that are not plain YAML text * fix: tighten fence typos, script base scope and app prompt order * fix: skip tool name checks on agent steps linked to a saved agent * fix: catch any misspelled prompt fence and soften the tool name claim * fix: align cli eval harness with the files and steps wmill init adds * fix: drop cli eval checks that expect unrequested deploy commands * fix: list ansible as mainless and c# Main in script base guidance |
||
|
|
8741843d2e |
feat: external instance cluster for data tables and Ducklake catalogs (#11197)
* fix pg_dump stuck on version 17 on nix * fix(datatables): refuse a malformed role annotation instead of ignoring it `-- Role operator`, `-- role operator;` and `-- role operator -- why` all failed the annotation parser's exact-match rule, so the query fell through to the data table's default role and ran, silently, under a login the author did not choose. Naming a role exists precisely to not do that. A leading comment whose first word is `role` is now an annotation attempt: the keyword matches case-insensitively, one trailing `;` is tolerated, and anything else is an error naming the line. Only callers that already know the target is a `datatable://` reference ever run this, so ordinary SQL keeps its comments. Also bumps the dev shell's postgres client to 18 — it trailed the server the dev database runs, which takes out every data table export, clone and fork-with-data. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): refuse a malformed role query string instead of ignoring it `?Role=analytics`, `?role=` and `?x=1&role=…` all fell through the reference parser's exact-match rule, so the connection resolved to the data table's default role and ran under a login the caller never asked for — the URI half of the same trap as a malformed `-- role` annotation. The key now matches case-insensitively, and anything else in the query string is an error naming it; `role` is the only parameter a reference takes. Callers that only need the entry keep a lenient `datatable_ref_name`, since they never act on the role. The DuckDB `ATTACH` parser propagates it rather than attaching under the default. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): carry the role annotation into the row_to_json retry The retry rebuilds its SQL from `pruneComments(code)`, so the leading comment block never reached the second attempt — and with it the `-- role <name>` line that decides which login the query runs as. The retry connected as the data table's default role instead, so a query the first attempt was denied could succeed on the second, reported as "recovered with the row_to_json fix". Carry the leading comment block over. The retry itself is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * chore(datatables): don't mount the roles UI until the ACL editor lands Enforcement ships first. The permissions drawer is what turns roles on, and the catalog section is what creates them — both are only useful once there is a way to grant a role the privileges it needs, which arrives with the ACL editor. Left mounted they would offer a feature whose other half does not exist. The two components are complete and reviewed; only their call sites here are commented out, with a note pointing the follow-up PRs at them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): honour `-- role: x`, and fix the DuckDB attach test Two review findings, both real. `attach_datatable_parses_name_and_role` never compiled: `parse_attach_datatable` returns `Result<Option<_>>` now and one call site kept a single `unwrap`. Its `?Role=analytics` case also asserted a refusal, contradicting the parser in the same commit, which matches the key case-insensitively. Replaced with the cases that are genuinely malformed, and a positive one for the cased key. `-- role: analytics` fell through to the default role — the silent fallback the strict parser exists to remove, for the spelling most likely to be typed. The keyword now accepts an optional colon, attached or spaced, while a word that merely starts with it (`rolebased`) is still not an attempt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): clone a fork's pointer instead of failing after the copy Forking a fork with cloning left an orphan database. The preflight resolves the pointer and sees the governing entry, so both endpoints ran and filled the new database; `apply_forked_datatable` then refused the inherited pointer and rolled the fork back, stranding a registered `wm_fork_*` that no entry names and whose name blocks the retry. Refusing earlier would have been the smaller change, but forking a fork and cloning worked before pointers existed, so it would trade an orphan for a regression. Resolve what the pointer names and write the terminal entry the clone needs: the whole `database` object rather than a patch of its `resource_path`, since a pointer has none, and `reference` removed with it. Also accepts `-- role=x` and `-- Role = x`, two more spellings that fell through to the default role. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): refuse to roll back the catalog while roles exist The down migration dropped the table and left every role behind: live Postgres logins whose passwords only that table carried, so after a revert Windmill could neither use, disable nor delete them, and re-applying could not recreate them because the names were taken. Cleaning up here is not possible either — dropping a role means reassigning what it owns in every instance database, and a migration runs in one — so it now refuses while the catalog is non-empty and says to delete the roles through instance settings, which does the cluster work. Also enforces the instance-only invariant the resolved-pointer clone relies on rather than only asserting it in a comment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * refactor(datatables): settle clonability in one place, before anything is created A clone is three stages a workspace apart — `create_pg_database`, then `import_pg_database`, then `apply_forked_datatable` inside the fork transaction. Only the third can roll back, and `CREATE DATABASE` is not transactional, so any refusal that lives there strands a registered `wm_fork_*` that no entry names and whose name blocks the retry. That orphan has now been fixed three times, most recently reintroduced by a guard added one commit ago. Patching each new refusal into the first endpoint is not the fix; having two places that can refuse is. `ensure_datatable_is_clonable` now answers every reason a copy can be refused and returns what it resolved, and the stage that writes the entry only does the work. Also takes an ACCESS EXCLUSIVE lock before the rollback guard counts, so a role created concurrently cannot slip between the check and the drop. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): let a retried clone reclaim its own leftover database A clone creates its target database one request before it copies into it, and the fork that would name it is written a request after that. Any failure in between — a pg_dump error, a bad restore, a dropped connection, the source's roles changing mid-flow — left a registered `wm_fork_*` that no entry names, and every retry then failed on its name. This predates data table roles. `create_pg_database` now reclaims such a leftover before creating: only a `wm_fork_*` database Windmill registered as a data table database and that no data table or ducklake entry names, in any workspace, archived ones included. The drop never terminates connections, so a clone still copying into it makes the reclaim fail instead of being cut off. It is limited to callers who administer the source — reaching it is not enough, since on a data table without roles every member reaches it — and anyone else gets the refusal an existing database always got. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Revert "fix(datatables): let a retried clone reclaim its own leftover database" This reverts commit |
||
|
|
9b46b21f51 |
feat(cli): include extra paths in codebase digest for monorepo imports (#11327)
* feat(cli): hash codebase extra_digest_paths and warn on uncovered bundle inputs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): cache codebase digest only once complete, skip entry in warning Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): accept string extra_digest_paths, always print uncovered-input warning Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): clarify extra_digest_paths resolution and missing-path error Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
841f7e1436 |
fix(cli): sync workspace dependency files on Windows and fix CLI tests (#11288)
* fix(cli): sync workspace dependency files on Windows Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(cli): pin workspace dependency path parsing on both separators Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(cli): classify workspace dependency files on either separator Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(cli): check out the fork deploy clone without autocrlf Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e1e3692fbc |
feat: data table roles in the DB manager and raw apps (#11139)
* feat(datatables): put a data table's connection under Postgres roles A data table backed by the instance database resolved to exactly one Postgres connection, `custom_instance_user`, for everyone who could reach it at all. There was no way to say this job reads, that one writes, this one never sees the salaries table. A data table role is now a real Postgres login on the cluster, defined once for the instance by a superadmin and named exactly as they named it. A script that declares `-- role analytics` connects as `analytics`, and Postgres decides what it may touch — grants are ordinary SQL. Windmill answers only "may this caller ask for this role", from the tenant lists on the data table entry: `u/alice`, `g/analysts`, `f/finance` or `*`. A data table with no `permissions` block behaves exactly as before. Everything that opens a connection on someone's behalf goes through one chokepoint, `get_datatable_resource_from_db`, which takes the identity explicitly and fails closed when there is none. The role logs in as itself — never `SET ROLE`, which a script could `RESET ROLE` its way out of. A fork's data table entry becomes a pointer at the workspace that governs it rather than a copy of it. The settings clone used to hand a fork a byte-identical entry naming the parent's database, which a fork admin could edit to grant themselves `admin` there; a pointer has nothing local to edit, and its tenants are evaluated as a member of the governing workspace, by email. `permissions` is stripped from the workspace export and ignored on import: tenants name principals of one workspace, and a settings push is not where an access decision should be made. Operations that see the whole database whatever the roles grant stay with the governing workspace's admins: editing the roles, a migration that declares none, and opening a replication stream for a Postgres trigger or capture. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): gate the paths that reach a whole database as admin Auditing what still resolved through the unchecked resolver turned up three that act for a caller and hand back the admin connection: `resolve_pg_source_checked` (behind schema export, the full-schema read, database creation, import and the forked-database drop), the connection test, and the schema snapshot a fork clone takes of its parent. On a data table under roles each let any workspace member — or a fork admin who is nobody in the governing workspace — read or copy the whole database whatever its roles grant. All three now require admin reach on the governing workspace. A dump taken under a restricted role would be a silently truncated copy rather than an error, so refusing is the only right answer for the copy paths. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): confine roles to the instance database, and stop a fork reaching the parent's bookkeeping A data table role is a login on Windmill's own Postgres. Nothing stopped a workspace admin putting a *resource-backed* data table under roles, at which point the executor dialled the host that resource names — one the admin chose — with the role's real cluster password, and `CONNECT` is granted to every registered instance database. Both ends now refuse: the permissions endpoint rejects the save, and the chokepoint refuses to substitute credentials on a non-instance entry rather than trusting the record it read. Two more places reached the governing database without answering to it. The initial-migration generator returned a `pg_dump` of the whole schema to any member. And the migration rename/delete cascade followed a fork's pointer into the parent, so a fork admin renaming or removing their own local entry relabelled or wiped the parent's `_wm_migrations` — after which the parent re-runs every migration from zero. The remote half is now skipped when the entry resolves into another workspace, which is also just correct: a fork renaming what it calls a data table changes nothing about the data table. Also: revoking a tenant now bounces the replication streams of every workspace holding an entry that resolves here, not only the governing one, so a fork's trigger stops rather than living on inside its open connection; the instance role catalog and the governing workspace's tenant lists are no longer returned to someone who cannot edit them; and the tenant rename dedup collapses non-adjacent duplicates, per role rather than once any role changed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): fail loudly where a role or a pointer can be left half-recorded Three ways the feature could end up in a state nobody could see or undo. Creating a role writes the cluster first and the catalog second, but the catalog write was an `UPDATE` that matched nothing when the instance Postgres settings row was absent — leaving a live login with a password nobody recorded: invisible to the catalog, un-recreatable because the name is taken, and un-deletable because there is no entry to delete. It now errors, so the operation is retryable once the row is restored. Deleting a workspace only nulls the fork lineage; the data table entries pointing at it are left resolving to nothing. Sweeping them is not an option — turning a pointer back into a copy would hand each fork the database outright — so the delete now names the data tables it stranded, and resolving one says which workspace is missing rather than reporting a data table this workspace never had. `InstanceDatatableRole` derived `Debug` while holding a Postgres password; it is now hand-written so `{:?}` on the catalog cannot put a live credential in a log line. Adds the two branches the reviews found unpinned: a caller who is not a member of the governing workspace at all, and `NoIdentity` — the compatibility path for an agent worker that predates this and sends no job id. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): unbreak two operator messages and two comments that described other code The two strings this branch added for states an operator hits once — the catalog write that matched nothing, and the delete that stranded a pointer — were collapsed from their multi-line form with the indentation left in, so both rendered with a fourteen-space gap mid-sentence. `list_datatables` claimed to report a chain it cannot follow and then dropped it; it does drop it, and the comment now says why that is the right place to stay quiet. The non-superadmin check in `edit_datatable_config` was introduced as also covering references, which it does not and need not: `reference` is overwritten from the stored entry for every caller before the check runs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): serialize role catalog mutations, and state each helper's authorization contract The catalog is one JSON document, so create, rename, enable and delete are all read-modify-write. Two concurrent creates read the same snapshot, both succeed in the cluster, and the second write drops the first — leaving a live Postgres login with a password nobody recorded, which is the exact state the delete path exists to prevent. Every mutation now runs in one transaction holding an advisory lock across the read, the cluster DDL and the write, so a lost update cannot happen and a failure rolls the whole thing back. The DDL helpers take that transaction rather than the pool, which is what makes the lock cover them. Their statements moved off `sqlx::raw_sql`: the simple protocol is only needed for genuinely multi-statement SQL, and its future is not `Send`, which an axum handler holding the transaction requires. Each of these is one statement anyway. The new cross-crate surface now says what callers must do. `read_role_catalog` returns plaintext credentials; `create`/`rename`/`set_login`/`drop_instance_role` and `converge_connect_grants` mutate cluster-wide state; `read_datatable_entry` reads a workspace's raw config. All of them are superadmin-gated by their current handlers, but nothing said so at the definition, which is where the next caller looks. Also: the roles table reloads after a failed login toggle instead of leaving it claiming a flip that did not land; the rename affordance is the design-system `Button`, not a raw one; and `resolve_datatable_pg_as_caller` drops a `role` parameter no caller ever filled — browsing resolves as the data table's default until the database manager grows a picker. Why role passwords stay a plain `String` while the instance user's password beside them is a `StringOrSecretRef`, asked three times across reviews: that one is a secret ref because an operator supplies it and may want it from their own backend, while these are minted here and never entered by anyone, so there is nothing for a ref to point at. Encrypting generated secrets at rest is a separate change that would take the replication password with it. Now said at the field. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): give the role catalog its own row, out of reach of the config machinery Putting it inside `custom_instance_pg_databases` was the wrong call, and it cost two ways. The catalog serializes a generated Postgres password per role, and that row is the operator-facing instance config, so the passwords reached `get_instance_config` and its YAML editor — a live cluster credential in a response body, a UI field and any log of either. Worse in the other direction: `to_settings_map` strips the catalog, so a full-row upsert of that key writes the row back without it and the catalog is gone, while the cluster keeps every login it described. `custom_instance_replication_pwd` is the precedent and says exactly why — a generated secret, written only by the server, never operator-authored, hidden so the config machinery cannot read, rewrite or drop it. The catalog is the same thing, so it now has the same shape: `datatable_roles`, in `HIDDEN_SETTINGS`, `PROTECTED_SETTINGS` and the agent-worker denylist. No redaction to keep in step with three code paths, and no way for a neighbouring write to take it out. Two races on the same shared documents. `edit_datatable_config` read the stored data tables outside its transaction and then wrote the whole `datatable` document, so a permissions save committing in between was silently rolled back; it now reads under `FOR UPDATE`. And `set_datatable_permissions` validated role ids against the catalog before opening its transaction, so a deletion in between let it write a deleted role back — including as the default, which every later job then fails on; it now holds the catalog lock and the settings row across validation and write. Completes the authorization contracts the previous commit claimed but did not finish: `read_datatable_entry` (which it named and missed), `resolve_governing_datatable`, whose whole job is to answer for a workspace the caller may not belong to, and `converge_connect_grants_with`, which had not inherited its wrapper's. Also the generic Python SDK reference: `_format_py_params` learned the bare `*` last time, but `extract_py_functions` is a second formatter and still rendered `datatable(name, role)`, so code written from that page passed a keyword-only argument positionally. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): make the concurrency test pin the handlers, and the contracts describe what is enforced The concurrency test reimplemented the read-modify-write inline, so deleting the lock from all three handlers left it green — it pinned Postgres, not the code it was written for. It now drives `create_datatable_role` twice concurrently and asserts the catalog kept both names. Checked the way the last one should have been: removing the lock from the handler makes it fail with "wmtest_a_… is a live cluster login the catalog forgot". The contracts added last commit were stricter than this PR's own callers, which is worse than none — the next reader sees a rule already broken and learns to ignore it. `read_role_catalog` said superadmin-only while two of its four callers are open to any workspace member, and `converge_connect_grants` said superadmin while `set_datatable_permissions` reaches it as a workspace admin. Both were fine on substance: the rule that actually holds is about the credential never reaching a response, log, audit record or export, not about who may call. They now say that. `read_datatable_entry` gets the same treatment rather than the one the earlier message claimed for it: it is the primitive every resolution goes through, so it is deliberately open, and what must not escape is `permissions` — it names the governing workspace's users, groups and folders. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): close the last ways a role or a pointer can be left pointing at nothing The raw settings readers hand back whatever is in the row, so moving the catalog into its own `global_settings` key protected the config machinery and left `GET /settings/global/datatable_roles` and the settings listing returning every live password. Both now filter that one key. The neighbouring `custom_instance_replication_pwd` has the same shape and is not touched here: it predates this and widening the fix to it is a decision about an operator workflow, not a consequence of this change. Three ways a save could leave something resolving to nothing: A permissioned data table could be moved to a PostgreSQL resource. The block was carried across as a server-owned field, the runtime refuses roles on a resource-backed table, so the save succeeded and every job afterwards failed. Refused instead — turning roles off first is one step, and it keeps discarding an access decision something somebody chose. Renaming a governing data table left every fork pointing at the old name: the data table disappears from their pickers and their jobs stop, with nothing in the renaming workspace to suggest why. The rename now follows into the pointers in the same transaction. Deleting one cannot be followed the same way, so it is reported instead — the response names what it stranded, the way deleting a workspace does, and the fork's own error already says which workspace is gone. Also: `ensure_instance_db_grant_options_unchecked` claimed superadmin while the permissions handler reaches it as a workspace admin (the same class fixed last commit, one instance missed); the role entry kept an `instance_config_schema` derive it no longer needs; `write_role_catalog` was the one writer of that table not stamping `updated_at`; and the concurrency test dropped its roles only on success — a failing run is exactly the one that creates them without recording them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * refactor(datatables): put the role catalog in its own table, not in global_settings Five findings across three rounds were all the same choice. A set of live Postgres credentials was living in `global_settings`, which has generic read, list, write, config-export and CLI round-trip paths that know nothing about what they carry: the passwords reached the instance config and its YAML editor, a full-row upsert of a neighbouring key erased the catalog, `GET /settings/global/{key}` and the settings listing returned them raw, and this round the redaction that fixed the last two turned `wmill instance push` into something that wipes every password — a fix breaking the assumption the previous fix made. `POST /settings/global/datatable_roles` could also empty it outside the lock. The approved plan offered a table or `global_settings`, so this is the other option it already allowed rather than a new design. `datatable_role` is a table: no generic settings path can read it, list it, export it, write it or round-trip it, so none of the five needs a guard. The redaction, the hidden/protected/agent-denylist entries and the JSON document all go with it. One row per role also removes the read-modify-write the concurrency work was about: two concurrent creates are two inserts, and the unique index on `name` is what settles a collision. The advisory lock stays for the one window rows do not cover — `CREATE ROLE` is invisible to another transaction until commit, so without it both creates pass their `pg_roles` check. Also from this round: rename mappings are checked against the configuration they claim to describe, since fork pointers are rewritten from them — a caller could otherwise submit `main -> missing` against an unchanged config and repoint every fork of `main` at a name nothing has, and `A -> B` plus `B -> C` moved what pointed at `A` all the way to `C`. And the warning naming forks a delete stranded reached the response but not the screen: both the data table settings save and the workspace delete now show it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): validate a rename against the save it describes, and re-check under the locks Three from the round, all about deciding on state that could already have moved. A permission save resolved the data table and checked it was instance-backed before taking any lock, then wrote under one. A config save committing in between could move the table onto a PostgreSQL resource — recreating exactly what the transition guard refuses — or rename it, in which case the write targeted a key that no longer existed and reported success having changed nothing. It now re-resolves and re-checks on the locked state. Rename validation checked that the source existed before and the target existed after, which still accepts `main -> decoy` against a save that keeps both: every fork of `main` then follows onto a different data table, silently, because it keeps resolving. The rule is now the actual old-to-new key transition — a source may only survive if another rename took its name, and a target may only pre-exist if another rename freed it. That also stops two sources sharing one target, and it admits a swap, which the previous guard refused: `datatables` is keyed by name, so a swap cannot be done one save at a time, and refusing it was a regression against main. The pointer cascade now runs in two passes through a temporary name, the way the migration cascade one layer down already handles the same shape, so `A -> B` with `B -> C` moves each pointer once from what it named before the save. The tenant mutators say what they are for: they write an access decision for any workspace named, with an arbitrary mutation, and exist for the transaction that frees or renames a principal. Editing a decision on purpose belongs in the permissions endpoint. Carried in the same change: the stranded-fork list is a field rather than a phrase to grep out of a success string; the pointer cascade matches with `EXISTS` instead of a `LIKE` over the whole document, so a workspace whose pointers name something else is not rewritten to a byte-identical value under an exclusive lock; and `InstanceDatatableRole` drops the serde derives left over from the JSON document, one of which would emit `pwd`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): cascade on the leave route that is used, gate migrations before the admin connection, and drop a role atomically The tenant cascade on leaving went onto `/users/leave`. The UI and the generated client call `/workspaces/leave` — a different handler in a different crate with the same name — which deleted the membership and left `u/<username>` in the tenant lists. Leaving and rejoining therefore restored the access the leave was supposed to end, and a later account taking the username would have inherited it. The regression test drives the route the client actually calls; without the fix it fails with "leaving kept the tenant". The migration endpoints authorized too late. `run_datatable_migrations` opened the data table's admin connection, created `_wm_migrations` and read it before reaching the per-migration role check — so with nothing pending, nothing was checked at all. Rollback returned before its check when nothing was applied, and the status endpoint had none. All three now ask, before any connection is opened, whether the caller can reach the data table as any role at all; which role a given migration runs as is still decided per migration, and by the executor after that. Deleting a role committed the cluster drop and the catalog row, then swept the tenant lists in separate transactions. A sweep failing part-way left workspaces naming a role nothing can connect as, while the retry answered `NotFound` because the catalog entry was already gone. The sweep now runs in the same transaction, so the drop, the row and every tenant list commit together. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): refuse to copy a data table that is under roles pg_dump carries no roles and the import runs with --no-privileges, so a copied data table arrives owned by the admin connection with no GRANT for any role. The settings clone brings `permissions` across, so the fork's tenants pass Windmill's check, connect as the role they were given, and are denied by Postgres on everything: an entry that reads as configured and answers nothing. Refuse the copy — in the import endpoint before any data moves, and in the fork path the CLI takes. Replaying the source's owners and ACLs into the clone is what lifts this, and is a change of its own. Dropping `permissions` from the copy instead would be the unsafe half, since the copy holds the parent's rows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): refuse the clone's database too, not only its data A clone is two endpoints: `create_pg_database` then `import_pg_database`. Only the second refused a data table under roles, so a fork asking to clone one created and registered an empty `wm_fork_…` instance database and then failed — and nothing collects it, since `drop_forked_datatable_databases` only drops entries carrying `forked_from` and no entry names this one. Refuse in both, so the clone stops before a database exists. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * nit worker error msg * fix pg_dump stuck on version 17 on nix * fix(datatables): refuse a malformed role annotation instead of ignoring it `-- Role operator`, `-- role operator;` and `-- role operator -- why` all failed the annotation parser's exact-match rule, so the query fell through to the data table's default role and ran, silently, under a login the author did not choose. Naming a role exists precisely to not do that. A leading comment whose first word is `role` is now an annotation attempt: the keyword matches case-insensitively, one trailing `;` is tolerated, and anything else is an error naming the line. Only callers that already know the target is a `datatable://` reference ever run this, so ordinary SQL keeps its comments. Also bumps the dev shell's postgres client to 18 — it trailed the server the dev database runs, which takes out every data table export, clone and fork-with-data. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): refuse a malformed role query string instead of ignoring it `?Role=analytics`, `?role=` and `?x=1&role=…` all fell through the reference parser's exact-match rule, so the connection resolved to the data table's default role and ran under a login the caller never asked for — the URI half of the same trap as a malformed `-- role` annotation. The key now matches case-insensitively, and anything else in the query string is an error naming it; `role` is the only parameter a reference takes. Callers that only need the entry keep a lenient `datatable_ref_name`, since they never act on the role. The DuckDB `ATTACH` parser propagates it rather than attaching under the default. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): carry the role annotation into the row_to_json retry The retry rebuilds its SQL from `pruneComments(code)`, so the leading comment block never reached the second attempt — and with it the `-- role <name>` line that decides which login the query runs as. The retry connected as the data table's default role instead, so a query the first attempt was denied could succeed on the second, reported as "recovered with the row_to_json fix". Carry the leading comment block over. The retry itself is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * chore(datatables): don't mount the roles UI until the ACL editor lands Enforcement ships first. The permissions drawer is what turns roles on, and the catalog section is what creates them — both are only useful once there is a way to grant a role the privileges it needs, which arrives with the ACL editor. Left mounted they would offer a feature whose other half does not exist. The two components are complete and reviewed; only their call sites here are commented out, with a note pointing the follow-up PRs at them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): honour `-- role: x`, and fix the DuckDB attach test Two review findings, both real. `attach_datatable_parses_name_and_role` never compiled: `parse_attach_datatable` returns `Result<Option<_>>` now and one call site kept a single `unwrap`. Its `?Role=analytics` case also asserted a refusal, contradicting the parser in the same commit, which matches the key case-insensitively. Replaced with the cases that are genuinely malformed, and a positive one for the cased key. `-- role: analytics` fell through to the default role — the silent fallback the strict parser exists to remove, for the spelling most likely to be typed. The keyword now accepts an optional colon, attached or spaced, while a word that merely starts with it (`rolebased`) is still not an attempt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): clone a fork's pointer instead of failing after the copy Forking a fork with cloning left an orphan database. The preflight resolves the pointer and sees the governing entry, so both endpoints ran and filled the new database; `apply_forked_datatable` then refused the inherited pointer and rolled the fork back, stranding a registered `wm_fork_*` that no entry names and whose name blocks the retry. Refusing earlier would have been the smaller change, but forking a fork and cloning worked before pointers existed, so it would trade an orphan for a regression. Resolve what the pointer names and write the terminal entry the clone needs: the whole `database` object rather than a patch of its `resource_path`, since a pointer has none, and `reference` removed with it. Also accepts `-- role=x` and `-- Role = x`, two more spellings that fell through to the default role. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): refuse to roll back the catalog while roles exist The down migration dropped the table and left every role behind: live Postgres logins whose passwords only that table carried, so after a revert Windmill could neither use, disable nor delete them, and re-applying could not recreate them because the names were taken. Cleaning up here is not possible either — dropping a role means reassigning what it owns in every instance database, and a migration runs in one — so it now refuses while the catalog is non-empty and says to delete the roles through instance settings, which does the cluster work. Also enforces the instance-only invariant the resolved-pointer clone relies on rather than only asserting it in a comment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * refactor(datatables): settle clonability in one place, before anything is created A clone is three stages a workspace apart — `create_pg_database`, then `import_pg_database`, then `apply_forked_datatable` inside the fork transaction. Only the third can roll back, and `CREATE DATABASE` is not transactional, so any refusal that lives there strands a registered `wm_fork_*` that no entry names and whose name blocks the retry. That orphan has now been fixed three times, most recently reintroduced by a guard added one commit ago. Patching each new refusal into the first endpoint is not the fix; having two places that can refuse is. `ensure_datatable_is_clonable` now answers every reason a copy can be refused and returns what it resolved, and the stage that writes the entry only does the work. Also takes an ACCESS EXCLUSIVE lock before the rollback guard counts, so a role created concurrently cannot slip between the check and the drop. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): let a retried clone reclaim its own leftover database A clone creates its target database one request before it copies into it, and the fork that would name it is written a request after that. Any failure in between — a pg_dump error, a bad restore, a dropped connection, the source's roles changing mid-flow — left a registered `wm_fork_*` that no entry names, and every retry then failed on its name. This predates data table roles. `create_pg_database` now reclaims such a leftover before creating: only a `wm_fork_*` database Windmill registered as a data table database and that no data table or ducklake entry names, in any workspace, archived ones included. The drop never terminates connections, so a clone still copying into it makes the reclaim fail instead of being cut off. It is limited to callers who administer the source — reaching it is not enough, since on a data table without roles every member reaches it — and anyone else gets the refusal an existing database always got. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Revert "fix(datatables): let a retried clone reclaim its own leftover database" This reverts commit |
||
|
|
974b0265f8 |
fix(cli): read wmill.yaml from the branch a git-sync deploy writes to (#11236)
* fix(cli): read wmill.yaml from the branch a git-sync deploy writes to Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(cli): create the stateful dir once the deploy branch's config is read Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
df61dea5fa |
fix: keep instance groups when editing auto-invite (#11217)
* fix: keep instance groups when editing auto-invite and push them from sync Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: compare settings.yaml without undeclared instance groups on push Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: read a missing auto_invite as empty when diffing settings.yaml on push Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: update ee-repo-ref to f2fced19fcae81de7f6dac545010ce404c052e1b This commit updates the EE repository reference after PR #813 was merged in windmill-ee-private. Previous ee-repo-ref: cf4258c1232720ca3b82db2b22ea1fb4bca9533e New ee-repo-ref: f2fced19fcae81de7f6dac545010ce404c052e1b Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
54553b2add |
fix(cli): resolve lockgen imports through modules a push leaves alone (#11160)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
129c045595 |
fix(cli): keep the workspace color when settings are synced from git (#11144)
* fix(cli): keep the workspace color when settings are synced from git Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs(cli): name the sync direction consistently in the identity-field comments Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(cli): apply the workspace color from settings.yaml only when the file sets one Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
42f489685b |
feat: store resource type display names and label hub integrations (#11113)
* feat: label resource types and integrations with hub display names Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: load hub integration names in the app and flow pickers Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: load hub resource type names where drawers title a type Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: store resource type display names and drop the hardcoded list Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: leave display_name out of the fork comparison Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: ignore over-long synced display names, move name loaders Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: share the hub integration list cache, backfill admins only Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: keep a name over a nameless duplicate, retry failed hub reads Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
a95e950529 |
feat(cli): list, get and restore trashed items with wmill trash (#11125)
* feat(cli): list, get and restore trashed items from the CLI * docs(cli): tell agents a sync push deletion is restorable with wmill trash * refactor(cli): share the ApiError formatting and type trash flags as integers |
||
|
|
d54a66f15c |
fix(cli): say where a sync push deleted variable or resource went (#10851)
* fix(cli): keep variables and resources a sync push repo never tracked `wmill sync push` archives a script it no longer finds locally, but hard-deletes a variable or a resource: the credentials go for good. A remote-only one is equally a deletion being deployed and one the repository never had, provisioned on the instance or written by a script at runtime, and reading the second as a deletion is unrecoverable. Committed history tells them apart. A push whose changeset deletes a variable or resource now asks what this branch has ever tracked at `*.variable.*` / `*.resource.*`; anything it has never recorded is kept on the remote (prompted for on a TTY), and a real deletion, recorded before the commit that removed it, still applies. Where the history cannot be read (shallow clone, sparse checkout, no repository) there is no evidence either way, so the deletion stands as before with a warning naming the remedy — the git-sync "Pull from repo" job runs in a depth-1 clone and must keep deploying the deletions it always has. `--delete-untracked-secrets` / `deleteUntrackedSecrets` opts a mirror-semantics pipeline back into deleting them unattended. Fixes GIT-980 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): classify secret-bearing deletions the way the push itself does Three ways the suffix match missed: - A fileset child can be any file, `inner.resource.yaml` included, and its deletion re-pushes the parent rather than deleting anything. Classifying with the push's own `getTypeStrFromPath`, behind the same fileset exclusion the apply loop uses, keeps the two in step. - Deleting `f/x.resource.file.ini` deletes the resource `f/x` outright, so without that file in the pathspecs every file resource walked past the check. Its two files now count as the one resource they delete. - A `specificItems` item is committed as `y.<workspace>.variable.yaml` while `elementsToMap` collapses it to the base path the changeset carries, so a deletion the user did commit read as never tracked. The history is searched under both names. `gitRecordedPaths` also reads its history with `core.quotePath=false`: a path with a non-ASCII byte came back C-quoted and matched nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): judge held-back deletions per object, not per file `DELETE /variables/delete` takes the resource at the same path down with it, and `DELETE /resources/delete` does the same to the variables its value references, so a tracked deletion could destroy an untracked object the push had just reported it was keeping. A file resource had the same shape from the other end: two files for one resource, either survivor deleting it. The unit is the server-side object. One file left unaccounted for by history now holds the whole object back, so nothing in a group reported as kept is deleted. The residual is a resource whose value references a variable at another path, which stays possible and is called out in the PR. Also corrects what the messages claim. Deleting a variable or resource is not irrecoverable: both move to the workspace trash, which keeps them for three days (migrations/20260326000000_trashbin.up.sql, CE since v1.665.0). The asymmetry with a script is real but narrower, and the prompt defaults to No, so it should say what it actually costs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): warn when sync push deletes variables the repo never tracked `sync push` deletes a remote variable or resource that has no local file. An object the repository has never tracked was provisioned outside it, by hand or by a script at runtime, rather than deleted from it, and the change list said nothing to tell the two apart. The push still deploys every deletion — that is what the repo-is-the-mirror contract means, and a shallow clone (the git-sync "Pull from repo" job, a default actions/checkout) could not tell them apart anyway. What changes is that the preview names the ones this branch's history has no record of, before the prompt that confirms them, and points at the excludes that stop them recurring. Deleting is also not final, which the CLI was alone in not saying: both handlers move the item to the workspace trash first, restorable for three days (migrations/20260326000000_trashbin.up.sql, CE since v1.665.0). A push that deleted any now says so. This replaces the earlier hold-back design. Keeping objects back changed what a push deploys, needed a flag and a wmill.yaml key to opt out of, and could claim to keep an object that a linked deletion then cascaded onto. Reporting cannot. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): name the paths the untracked-deletion warning is about A push can delete a tracked and a never-tracked resource together, where "1 resource" identified neither. The warning lists the paths instead of counting them, so the reader knows which one to exclude. Outside a git checkout it no longer opens "This branch's history", which contradicted the reason it went on to give, and it drops the pronouns that disagreed with a plural count. The history walk is skipped under --json-output, where both notices are silenced and its result had no reader. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): vouch for an object with any file in history, not just deleted ones The tracked set was built from the deletions being judged, so a companion file the push was not deleting could not vouch for its object: a file resource whose `.resource.yaml` stays while its content file goes was reported as never tracked, though the repository plainly owned it. It is built from the whole history now, which also turns the workspace-specific lookup around — history is normalized to base paths, the form the changeset already carries, instead of each candidate being searched for under two names. The warning also prints one line per server-side object rather than per file, so a file resource is the one deletion it is rather than two. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): name both kinds at a shared path, gate the history path conversion Three from review: A variable and a resource at one path are judged together, since deleting either takes both, but they are two objects to name — keying the printed lines by path alone dropped one of them. `fromWorkspaceSpecificPath` strips a `.<workspace>` segment wherever it finds one, so a history entry that merely looks workspace-suffixed was re-keyed onto a different object, whose history then vouched for it. Only a path `specificItems` claims is converted now. Not reachable from a server object (the backend rejects `.` in paths), but history holds whatever was committed. `secretBearingKey` lost its last caller when the tracked set moved to object paths; removed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): identify a secret-bearing object by kind as well as path A variable and a resource can share a path and are still two backend objects: `DELETE /variables/delete` drops the same-path resource unconditionally, while `DELETE /resources/delete` drops only the variables its value references. Keying tracked history by path alone let a committed variable vouch for a resource the repository never had, which then went unmentioned. The cascade is a reason to report both, not to treat them as one. A file resource's two files keep one id. `git log HEAD` also fails on a repository with no commits, which was reported as "its history could not be read. Check that git runs correctly in this directory" — true of neither. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(cli): tighten the comments on the untracked-deletion warning Halves the prose without dropping a constraint: the trashbin retention is stated where the message says it rather than twice more in doc comments, and the two stacked comments at the print site had come to contradict each other, one still describing a same-path variable and resource as judged together. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): say where a deleted variable or resource went `sync push` deletes a remote variable or resource that has no local file, and said nothing more. Both handlers move the item to the workspace trash first, restorable for three days (migrations/20260326000000_trashbin.up.sql, CE since v1.665.0), and the CLI was the one surface never to mention it — the report behind this concluded the deletion was final and there was nothing to restore. A push that deleted any now ends with where they went and how long they have. Drops the untracked-deletion warning this branch carried: distinguishing a deletion the repo deployed from an object it never owned needs the branch's git history, and roughly 130 lines to read it and be right about the answer, for a claim the trash already softens. Two fixes it turned up in the data-table migration guard, which reads history the same way, are kept: a path with a non-ASCII byte came back C-quoted and matched nothing, and a repository with no commits was reported as one where git does not run. Fixes GIT-980 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): name the trashbin correctly and say who can restore The tab is labelled Trashbin, not Trash, and `restore_trash_item` requires admin, so a non-admin reading the old line would go looking for a control they do not have. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor(cli): move the migration-guard git fixes to their own PR They fix `gitRecordedDatatableMigrationPaths`, which this PR no longer touches. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): don't count a .lock deletion the push skips The apply loop `continue`s past a non-raw-app, non-dbt `.lock` deletion before reaching the delete switch, so nothing happens on the server. The classifier did not mirror that, and `f/x.resource.file.lock` reaches it as a resource through `isFileResource` — a resource type whose format_extension is literally `lock` would have the notice announce a deletion the push never performed. A raw-app or dbt `.lock`, the two that loop does not skip, classifies as its bundle's own kind well before the file-resource check, so a suffix test is enough. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(cli): state what the classification tests protect The header described the change rather than the invariant. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
0af7675588 |
fix: keep an app's deployed policy on wmill push (#11049)
* fix: keep an app's deployed policy on wmill push Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: keep a first push's file-stated app policy Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: deploy a file-stated viewer app as viewer, not publisher Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: never put a repo-stated run identity on the wire Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: send the deployed run identity only when the push may claim it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: let a file-stated execution mode win in both directions Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * refactor: drop the app-file execution mode helper with no caller Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * feat: warn before a raw-app push takes over the run-as user Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: keep an app's run-as user when a push only deletes one of its files Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * refactor: settle an app's ownership check before any content parsing Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: share one rule for which raw-app files a push sends Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: stop tracking raw-app files no push ever sends Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * test: bundle for real instead of stubbing the module for every suite Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * docs: record why a module mock cannot be undone by afterAll Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: keep tracking a runnable whose file shares a bundle-excluded name Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * test: pin both halves of the backend runnable rule Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
8820b9fc64 |
feat: report script metadata with no content file in wmill lint (#11053)
Claude-Session: https://claude.ai/code/session_01PENfHNJceAbrcUsgfFCjXN Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0b37226078 |
fix: chain redeploys onto a retired path's version history (#11029)
* fix: chain auto_parent onto the archived lineage tip at a path Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GoTAmRTjG2KAH4g4mco6T5 * fix: check descendants unscoped and drop the hash-guard move Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GoTAmRTjG2KAH4g4mco6T5 * fix: widen retired-path adoption, lock it, drop inherited grants Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMhCSFeWSezY61g6woQiz2 * fix: check lineage linearity unscoped, under the parent lock Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GoTAmRTjG2KAH4g4mco6T5 * fix: do not name a lineage conflict the caller cannot read Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GoTAmRTjG2KAH4g4mco6T5 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
448fce93f7 |
fix: make the native trigger disable/enable toggle actually save (#11024)
* feat: let a native trigger be disabled without deleting it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: show and control the native trigger pause outside the flow editor Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: create a native trigger already paused instead of pausing it after Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: correct the native trigger enabled comments for create-time init Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
f081fb1070 |
feat: recognize // volume: mounts in PHP scripts (#11018)
* feat: recognize `// volume:` mounts in PHP scripts Volume annotations were parsed for every language but PHP, so a PHP script could not mount a workspace volume. Two things stood in the way: PHP had no entry in the comment-prefix maps, and a PHP script opens with `<?php`, which ends the leading comment block the parsers scan before any annotation is read. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T3FR7iS9nRhpFt615cnuQ7 * fix: tolerate a PHP opener that carries code, drop the inert CLI hunk The open-tag skip matched `<?php` exactly, so `<?php declare(strict_types=1);` still ended the leading comment block and every annotation below it was silently ignored. Match the tag as a case-insensitive prefix and skip the whole line. The CLI local-graph hunk could never fire: PHP has no wasm asset parser, so `fallbackParse` handles it, and its own header scan stops at `<?php` — the script is dropped as a non-pipeline-member before any volume asset is read. Making only the CLI PHP-aware would also put the local graph out of parity with the deployed one, whose `parse_pipeline_annotations` stops there too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T3FR7iS9nRhpFt615cnuQ7 * docs: correct the CLI mirror comment, state the own-line annotation rule Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T3FR7iS9nRhpFt615cnuQ7 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
5f3f99ba69 |
fix(cli): keep permissioned_as on single-item push, as sync push does (#11000)
* fix(cli): keep permissioned_as on single-item push, as sync push does * fix(cli): resolve syncBehavior from the target workspace, not the branch alone * refactor(cli): share the workspace-name resolution between sync and single-item push * test(cli): import the moved workspace-name helper from its new home |
||
|
|
7643e9bd77 |
fix(cli): say which workspace id is targeted, and when wmill.yaml is bypassed (#11006)
* fix(cli): say which workspace id is targeted and when wmill.yaml is bypassed Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QaQ3UtkbHA6pxqQStqRQQj * fix(cli): make the wmill.yaml lookup for diagnostics side-effect free Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QaQ3UtkbHA6pxqQStqRQQj * fix(cli): only report a wmill.yaml mapping that sets an explicit workspaceId Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QaQ3UtkbHA6pxqQStqRQQj --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ee9e550a48 |
feat(git-sync): sync extra_perms for variables (#11004)
* feat(git-sync): sync extra_perms for variables Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hvv5B8VP5Di4dbcCiVyZyE * refactor: trim the variable ACL-sync comment to the 4-line limit Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hvv5B8VP5Di4dbcCiVyZyE * test: cover the revoke direction of variable extra_perms sync Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hvv5B8VP5Di4dbcCiVyZyE --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
fce635d3c4 |
feat: guest app execution mode, a role that takes no seat (#10929)
* feat: guest app execution mode, a fourth role that takes no seat Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: make the guest grant a server-minted label, not a declarable scope Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * chore: pin ee-repo-ref to the guest session companion branch Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: close the relabel hole, guest embed tokens, read-path switch, custom-path entry Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest tokens are not rescopable and guest embed tokens keep the sentinel Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest-derived tokens share one constraint set; gate sign-in on guest discovery Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: the label alone governs a guest; refuse guests with accounts; unserialize discovery Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest discovery fails closed; SAML aborts if the guest cookie write fails Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * refactor: enforce the guest switch once at the auth door; sign-in for a guest of another app Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest app-mode decided once at the on-behalf resolver; clear a stale guest session before offering another app's sign-in Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: a guest may use anonymous apps; await the stale-session logout; trim comments Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: a guest's path confinement waits for the app's mode, so anonymous apps stay open to it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest target survives http (Lax cookie), rides SAML RelayState; tell account holders on arrival * fix: a guest uses an anonymous app as itself; S3 uploads confined by app mode * fix: a guest upload needs an app policy; a missing app does not skip the confinement * fix: guests are gated on the Enterprise plan server-side; pin ee-repo-ref * fix: the guest plan gate fails closed on non-enterprise builds; settings report the effective switch * fix: guest controls read the plan, not the key; gate the guest tests on the features they need * docs: tighten the guest session invariant comments * feat: 100 free guests per 30 days, then a quarter seat each on Enterprise and a hard cap elsewhere; superadmin guest list; refusals reach the page Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: the cap is exact, an account ends a guest session at the door, popups close, and guest mode survives the CLI round trip Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * feat: a superadmin switch over guests for the whole instance; the pre-existing-user flag keeps its meaning Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: drop the dead guest-access helper, name the instance setting once, guests tab states, CE save order Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: a guest app path is refused at the mint if it could widen the scope; the instance toggle waits for its reload Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guests stop at the launched-by-me job grant; canonical app paths at the mint and discovery; the toggle ends on the stored value Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: only the scope grammar's own characters bar an app path from guests, refused at deploy as well as at the mint Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: the deploy-time guest path guard checks the destination of a rename and refuses a leading slash Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: a workspace rename keeps the guest switch; the rename guard reads the deployed mode under the row lock Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest_activity follows a workspace rename and goes with a workspace delete Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * chore: pin ee-repo-ref to the state-bound guest target Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * chore: pin ee-repo-ref; the guest cookie is never cleared by a callback Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * docs: the workspace-scoped guest_activity delete moves an instance-wide count; assert the mint records the guest Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * test: the seeded allowance is a day old, so only the mint can write today's guest_activity row Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * chore: update ee-repo-ref to 1a10132e4f3cb442c7d0c2cf6e5d92d150bf6e07 This commit updates the EE repository reference after PR #769 was merged in windmill-ee-private. Previous ee-repo-ref: 32841072aa396bff91d30bd91854fa348cb3c439 New ee-repo-ref: 1a10132e4f3cb442c7d0c2cf6e5d92d150bf6e07 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
e39dd7eb12 |
docs: teach agents to pass a resource as $res:<path> in run arguments (#10927)
* docs: teach agents to pass a resource as $res:<path> in run arguments Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk * docs: extend run-argument rule to in-editor chats, fix run-as wording Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk * docs: tighten resource run-argument rule after review - Drop the false rationale that "$var:" only works inside a resource value from the write_variable description and its runtime rejection message; keep the rule (a variable cannot reference itself). - MCP resource-argument description: the title fallback renders "No title", so say the title is only a label rather than that it can be empty. Guard the real-newline fix with asserts in the existing enrichment test. - Eval: assert the full "$res:f/evals/global/github_main" value as one prefix so a wrong path with a right prefix fails. - resources.md: narrow "a trigger's payload" to its configured static args. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk * docs: scope the run-argument rule to global chat, add an exact eval matcher The ai_evals A/B on the two in-editor modes showed no effect: script mode sonnet 5/5 both with and without the description, flow mode sonnet 5/5 and haiku 5/5 on the baseline alone. A flow's input schema already carries `format: resource-<type>`, so those modes have a signal global mode does not give. Revert both files to keep the tool schemas free of a description that buys nothing per iteration; global mode keeps it, where haiku goes 0/5 -> 5/5. Add `stringEqualsAnyOf` to toolCallArgs and use it for the resource reference: nothing in the eval resolves the value, so a prefix match accepted a near-miss path like `$res:f/evals/global/github_main_backup`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk * docs: address cubic review — CLI wording, mock resource getter - `-d --data` help on all four run/preview commands: give $res: and $var: their own clauses instead of a parenthetical that read as if a resource were a kind of variable. - Mock backend: `getBenchmarkResource` now resolves AI-provider seeds as well as plain ones, so it agrees with `existsResource` and `listResource` — both report either kind, and a case that listed a resource and then read it by path got a row it could not fetch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0f5a1db2ab |
fix(cli): make a sync push into a fork converge on schedules and inline names (#10951)
* fix(cli): make a sync push into a fork converge on schedules and inline names Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcofduXAs9FT948Aj78V8m * fix(cli): gate the fork schedule lookup, tolerate fork-conflict, keep rendered names unique Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcofduXAs9FT948Aj78V8m * test(cli): use the OS path separator in the push convergence fixtures Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcofduXAs9FT948Aj78V8m * fix(cli): report a set-aside fork schedule flag and keep checkout inline names inside the flow folder Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcofduXAs9FT948Aj78V8m * fix(cli): enable a fork-only schedule on create, and treat a fork with no parent as owning its schedules Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcofduXAs9FT948Aj78V8m --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
337154b830 |
fix: connect to dev server instead of localhost (#10912)
* fix: connect to dev server instead of localhost * fix: derive WebSocket scheme from location.protocol Mirror the protocol-aware pattern used by initSqlWebSocket in dev.ts so the WebSocket connects over wss:// when the dev server is reached through an HTTPS proxy/tunnel, avoiding mixed-content blocking. * refactor: drop now-unused port parameter of wmillTsDev Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HsfdN82yP88qyQ3h8Lwv2v --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
cfcfe298dd |
feat(ai-chat): make reusable skills ai_skill resources you select per workspace (#10914)
* feat(ai-chat): make reusable skills ai_skill resources you select per workspace * chore: pin the ee ref to the skill telemetry counters * fix: address review findings on skill authoring, import and migration * fix: enforce skill selection in read_skill and stop imports clobbering resources * feat: carry format_extension from the hub into synced resource types * fix: let an edit set or clear a resource type's format_extension * fix: regenerate the sqlx cache and close the review round findings * fix: close the round-2 findings on folder ACLs, cached sync and truncation * refactor: make the skills migration non-destructive and use design-system inputs * fix: close the round-4 findings on folder owners, startup sync and truncation * fix: clear obsolete extensions, guard folder owners, and report skipped skills * fix: honor explicit-null extensions and report same-type migration conflicts * fix: scope skill actions to the committed workspace and paginate the listing * fix: keep the drawer scoped to the live workspace and surface truncation * fix: discard a skills refresh for a workspace the chat has left * chore: update ee-repo-ref to 6efe7a73c745c2e1377a34498523c00d89010a3d This commit updates the EE repository reference after PR #764 was merged in windmill-ee-private. Previous ee-repo-ref: 55998c142bc72edd08532748af1974b16035658d New ee-repo-ref: 6efe7a73c745c2e1377a34498523c00d89010a3d Automated by sync-ee-ref workflow. --------- Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
4b5be386ce |
fix: keep a local dbt descriptor under sync pull --keep-deleted (#10911)
* fix: keep a local dbt descriptor under sync pull --keep-deleted Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0174o6mGTWoanipUgf5zNcVL * fix: keep an added-shaped dbt descriptor removal under --keep-deleted too A stateful pull compares `.wmill`, not the working tree, so a descriptor missing from that map still arrives as `added` while a real file with the project's warehouse and run arguments sits on disk. Counting only `edited` left that file deletable, and silently: the flag logged nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0174o6mGTWoanipUgf5zNcVL --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
66123f3a9b |
feat: add --keep-deleted flag to wmill sync pull and push (#10878)
* feat: add --keep-deleted flag to wmill sync pull and push Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMfhFSZQJJRLPrfkug6VoK * fix: address review findings on --keep-deleted Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMfhFSZQJJRLPrfkug6VoK --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
b8bf539c3f |
fix(cli): keep svelte component styles in the raw-app bundle (#10838)
* fix(cli): keep svelte component styles in the raw-app bundle Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test: fold svelte style guard into the plugin test file Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs: record the editor-parity constraint on the svelte css option Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(cli): pin esbuild's service cwd before any test file chdirs esbuild's node API captures process.cwd() when its module is first imported and spawns its service with that cwd on every (re)start. createBundle stops the service after each bundle, so the cwd is reused across the whole run. Several test files chdir into a temp dir and delete it afterwards. The first one to bundle therefore pinned the service to a directory that stopped existing, and the next test to reach esbuild died with The service was stopped: ENOENT: no such file or directory, posix_spawn '.../@esbuild/linux-x64/bin/esbuild' The binary is present; ENOENT is posix_spawn rejecting the missing cwd. Which file tripped it depended on bun's readdir order, so renaming an unrelated test file was enough to surface it. Importing esbuild from the preload pins the service to a cwd that outlives the run, independent of file ordering. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G88YF3sZFnJZUvTLVjqhZc --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
5b885ae311 |
fix: keep raw-app files within their app folder on sync pull (#10796)
* fix: keep raw-app files within their app folder on sync pull Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: validate raw-app file keys as stored, closing nul and duplicate-field bypasses Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: guard raw-app runnable ids too and fail closed on unparseable value Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: strip only a leading slash on raw-app file keys to match backend Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: strip only a leading slash on raw-app file keys to match backend Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
05abf6d5aa |
feat(cli): deduplicate identical script lockfiles (dedupeLockfiles) (#10769)
* feat(cli): deduplicate identical script lockfiles into one per language * test: pin shared lockfile path classification * fix(cli): never delete a lockfile the dedup plan also writes * fix(cli): plan lockfile dedup from the whole tree, not the sync scope * fix(cli): keep dedup out of dry runs and stop hiding scripts from its scan * test: pin which files the shared-lock scan counts as readers * fix(cli): validate shared-lock refs and let the majority keep its file * fix(cli): snapshot shared-lock ownership before regeneration moves it * fix(cli): address dedup review nits (dry-run push, json shape, scan scope) * refactor(cli): put shared lockfiles in a top-level locks/ directory * fix(cli): claim only the shared lock names windmill writes, and only when on * fix(cli): read the lock field itself, and count only scripts sync reads * fix(cli): parse metadata by its real format and lint from the sync root * fix(cli): never re-hash a script whose generation failed * fix(cli): share sync's walk exclusions and fail closed on unreadable dirs * fix(cli): keep a lockfile the metadata on disk still references * fix(cli): decide a lock is unread from the metadata field sync reads * refactor(cli): name shared lockfiles after the dependency file they resolve * fix(cli): carry shared lockfiles a narrowed sync cannot speak for * fix(cli): move a shared lockfile when its dependency file moved, not on a head count * fix(cli): let the many correct a shared lockfile a lone variant planted * fix(cli): read why a lock differs from the stamp the worker writes into it * fix(cli): let an agreeing majority speak whatever the stamps say * docs(cli): count the disjuncts the comment introduces * fix(cli): keep a private lock for any script the worker locks differently * fix(cli): match annotations by the worker's own names, not by shape * fix(cli): recognize the py: interpreter pin the macro does not cover * fix(cli): let the map speak for dependency-file deletions * perf(cli): group lock entries without rebuilding the group per insert * fix(cli): defer shared-lock deletions until the metadata has settled * fix(cli): decide shared-lock readers by the lock field, failing closed * fix(cli): read folded lock refs and keep locks read by unparseable metadata * refactor(cli): one shared-lock reader scan, shared by the pull and push paths * fix(cli): keep nested dependency set names out of shared lockfiles * fix(cli): drop a shared-lock scan gate that no real repo took |
||
|
|
ef4dc46d4b |
fix(cli): keep script settings on push and repair the up-to-date check (#10741)
* fix(cli): keep script retention, debounce and cache settings on push Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(cli): surface the create response when the fixture fails Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(cli): drop debounce settings the CI build refuses to accept Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * repair the script push up-to-date comparison (#10743) * test: settle the backlog before the capped audit-export drain (#10737) * test: settle the backlog before the capped audit-export drain * chore: update ee-repo-ref to bd4de74eb37b32a2b6c7c69f6dedac031ef8436b This commit updates the EE repository reference after PR #730 was merged in windmill-ee-private. Previous ee-repo-ref: b5a5f9114df26088cfe976d91f10e55ba8bfcaa6 New ee-repo-ref: bd4de74eb37b32a2b6c7c69f6dedac031ef8436b Automated by sync-ee-ref workflow. --------- Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> * fix(cli): repair the script push up-to-date comparison Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(cli): drain dependency jobs and pin a non-1 priority skip Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(cli): describe the priority fixture without the old comparison Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor(cli): read cache_ignore_s3_path off the typed response Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(cli): stop redeploying bunnative scripts on every push Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
1816b11474 | fix(cli): delete file resources at the right path on sync push (#10639) | ||
|
|
85134578b4 |
fix(cli): sync push crashed on edited fileset children; reject non-canonical fileset dirs (#10572)
* fix(cli): route fileset children to their parent resource on sync push Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): scope fileset pointer validation to sync pushes Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): error on script push of file/fileset resource content files Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): enforce server-canonical fileset pointers and fail fast before apply Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): resolve ws-specific fileset metadata and validate pointers before dry-run Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): prefer workspace-specific fileset metadata over base file Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(cli): make fileset metadata lookup assertions platform-separator safe Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): stop dropping fileset children whose names look like typed metadata Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(cli): exempt fileset children from the current-workspace classifier too Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2748d019f5 | fix(cli): load the app's ESM svelte compiler, not its CJS one (#10622) |