Commit Graph

6833 Commits

Author SHA1 Message Date
Ruben Fiszel 68b1fcc5cd fix: prevent u16 underflow in suspend count causing permanent flow deadlock (#10256)
When extra resume_messages arrive concurrently and resume_messages.len()
exceeds required_events, the u16 subtraction wraps to ~65535, which is
written as the suspend counter and permanently deadlocks the flow waiting
for events that never arrive. Use saturating_sub so it clamps to 0 instead.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 12:14:10 +02:00
Ruben Fiszel d2c5d6f4b4 feat: make content search a full CE feature (#10252)
Content search (the `#` mode of the home-page Ctrl+K search, which
searches scripts/flows/apps/resources by content) was capped on CE to 10
scripts and 3 each of flows/apps/resources, with an "EE feature" warning
in the UI. It is now a full CE feature: the CE result caps are lifted to
match the previous EE limits (10000 scripts, 1000 each of the rest) and
the EE warning is removed.

Fixes WIN-2218

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 11:30:23 +02:00
hugocasa b948efd3c8 fix: accept ssh/scheme-less git repo urls and $var: refs in app repo resolution (#10246)
* fix(git-sync): accept ssh/scheme-less repo urls and $var: refs in app repo resolution

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(git-sync): interpolate repo urls at github-call sites only, not in persisted markers

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore: update ee-repo-ref to 183f78b3ee193d6b5e55fd453c570f94a12c8b13

This commit updates the EE repository reference after PR #681 was merged in windmill-ee-private.

Previous ee-repo-ref: 9bc5018f68edf3a9f256ef6315ad6ddf4fba3a45

New ee-repo-ref: 183f78b3ee193d6b5e55fd453c570f94a12c8b13

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-07-22 00:26:15 +02:00
Ruben Fiszel 50f1375f18 chore(main): release 1.765.0 (#10223)
* chore(main): release 1.765.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-07-21 20:15:14 +02:00
Diego Imbert ec6324409d fix(s3): support instance-policy credentials in object storage tests (#10238)
* fix(s3): cache ambient aws credentials and surface credential chain errors

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SCczeVBDhDnLXWqxPWw6od

* fix(frontend): clarify that object storage connection tests run on the server

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SCczeVBDhDnLXWqxPWw6od

* fix: render test connection tooltip in popup and harden cache test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SCczeVBDhDnLXWqxPWw6od

* better doc

* fix(frontend): correct tooltip wording, tests run from the executing worker

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SCczeVBDhDnLXWqxPWw6od

* fix(s3): single-flight ambient credential provider creation

* fix(frontend): clarify object storage tests run on the server process

* fix(frontend): make instance object storage test tooltip provider-neutral

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-07-21 20:02:34 +02:00
hugocasa 2ce21c9ef8 feat(git-sync): enable per-item promotion mode on dev workspaces (#10205)
* feat(git-sync): enable per-item promotion mode on dev workspaces

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style: keep unrelated git-sync Alert copy at its original wrapping

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): fall back to parent_path on empty deploy path + bump ee ref

computeGitSyncDeployBranch used ?? so a backend-serialized empty path (rename out of the repo filter) skipped the deploy branch and could commit to the tracked base; use || to fall back to parent_path like the backend. Bumps ee-repo-ref for the single-object promotion_open_prs fix (windmill-ee-private#679).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): route dev-promotion non-branchable objects off the tracked base

user/group objects (and any unresolvable ref) returned null in promotion mode, so a dev-workspace deploy pushed them straight to the parent's tracked branch. Fall back to the dev's env-label branch instead; the backend opens no PR for them (isolated, not promoted).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(git-sync): dev-workspace promotion via a toggle on the inherited repo

A dev workspace reuses the single repo it inherited from prod: a 'Promote to prod via Git' toggle flips it between sync mode (deploys to the dev branch) and promotion mode (per-item wm_deploy/** PRs to prod), with a per-item/per-folder sub-toggle. Removes the redundant separate-promotion-repo setup for dev workspaces.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(git-sync): dev-promotion regression test + widen git_sync_e2e path filter

Adds a CLI integration case covering dev-workspace promotion (script -> wm_deploy branch; user/group -> env-label branch, main never touched). Widens the git-sync-test.yml relevance filter to the deploy-branch derivation, git-sync guard, and CLI git-deploy files so the e2e suite runs on PRs like this one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): gate dev promotion toggle on EE, fix card mode + workflow path filters

Codex review: (1) show the dev promotion toggle only under an active EE license and revert the optimistic save if the backend rejects it; (2) derive the dev card's display mode from use_individual_branch so promotion copy shows in promotion mode; (3) mirror the new relevance paths into the workflow's top-level push/pull_request filters so it actually triggers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): only use the single-card dev promotion UX when the dev has one repo

Codex review: an attached dev workspace keeps its own repositories rather than inheriting prod's. Gating the single-card + toggle + hidden-secondaries UX on repositories.length <= 1 makes a multi-repo attached dev fall back to the normal layout, so no active repo is hidden and an unrelated repo isn't presented as prod's promotion target.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): runtime EE-plan gate for promotion mode, consistent with auto-pull/PR

Codex review: promotion mode only had the CE compile rejection, while auto-pull and PR creation runtime-gate on the active plan (check_git_sync_ee_license). Add check_promotion_license and call it from both edit_git_sync_config and edit_git_sync_repository, plus the matching CE rejection on edit_git_sync_config so the two endpoints are symmetric. Promotion is now gated like every other git-sync EE setting.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): dev promotion must reuse the parent workspace's repository

Codex review: repository count doesn't prove a dev inherited prod's repo — an attached dev keeps its own. check_dev_promotion_targets_parent_repo resolves the promotion repo's URL and rejects enabling promotion unless it matches one the parent (prod) tracks, so branches/PRs can't target an unrelated repository. Called from both git-sync edit endpoints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): dev promotion save-time check uses shared parent-repo matcher (url+branch)

Delegates to windmill_common::git_sync_ee::dev_promotion_target_matches_parent so the settings gate and the deploy-time safety net share one url+branch identity check. Bumps ee-repo-ref for the EE deploy-time enforcement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump ee-repo-ref for private resolve_repo_url_and_branch

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump ee-repo-ref for promotion-target matcher authz doc

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(git-sync): bump hub scripts to gitsync-cli versions, fix promotion tooltips

Point LATEST_GIT_SYNC_SCRIPT_PATH (28790 -> 28796) and
GIT_SYNC_PULL_SCRIPT_PATH / gitInitRepo (28789 -> 28795) at the hub
versions pinning windmill-cli@1.763.1-gitsync.0, which carries the
dev-workspace promotion routing. Slugs unchanged, so the GitHub-App
token check and hub script cache are unaffected.

Tooltips: enabling promotion pushes a PR-ready wm_deploy/** branch;
Windmill only opens the pull request itself when automatic pull
requests are enabled. Reword both toggles to stop promising a PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): dev promotion mirrors to the env-label branch, PR toggles exclusive by branch type

Bump ee-repo-ref for the dispatcher changes: a promotion dev's deploys
now also push to its env-label branch (one extra mirror job per batch,
users/groups mirror-only), and `fork_open_prs` no longer applies to a
dev in promotion mode where `promotion_open_prs` governs.

Frontend: the fork-PR toggle tooltip states its actual coverage
(wm-fork/** and the dev branch of a dev workspace) and that a promotion
dev's own pull request toggle takes over for wm_deploy/** branches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): reject dev promotion on pre-28796 pinned sync scripts

An older pinned sync script bundles a CLI that force-disables per-item
branches on every fork, so enabling promotion on a dev workspace with
such a pin would silently keep deploying to the env-label branch. Both
git-sync edit endpoints now reject the combination with an actionable
error; the EE dispatchers (via ee-repo-ref bump) demote inherited
configs to promotion-off semantics so markers, branch keys and the
mirror match the branch the CLI actually pushes. Roots and auto-managed
repositories are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): serialize dev promotion toggle saves

The promotion and per-folder toggles persist immediately via whole-repo
saves; leaving them interactive while one is pending lets rapid flips
race, and the earlier save (enabling runs extra backend checks) can
commit last, silently reversing the state the UI shows. Both toggles now
disable while a save is in flight.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(git-sync): lock auto-PR toggle during promotion save, rename-out branch routing

Frontend: the automatic-PR toggle is revealed by the promotion toggle's
in-flight save; an edit made mid-save was absorbed into the saved
baseline without reaching the backend. It now disables during that save.

EE (ee-repo-ref bump): dispatcher debounce/concurrency keys and PR
markers follow the CLI's parent_path fallback for rename-out items, so
their wm_deploy/** branches debounce per-branch and open their PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(git-sync): condense comments to durable constraints

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref to 8bf73f803158bcbf7b8d55a36f4a1ebfcc1bbcd9

This commit updates the EE repository reference after PR #679 was merged in windmill-ee-private.

Previous ee-repo-ref: c2cd718cb53d234f909f485bd7cd43ed9605ffd1

New ee-repo-ref: 8bf73f803158bcbf7b8d55a36f4a1ebfcc1bbcd9

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-07-21 17:07:52 +00:00
Ruben Fiszel 4a898247a2 fix(apps): let entitled viewers read pre-existing S3 files from deployed apps (#10245)
* fix(apps): let entitled viewers read pre-existing S3 files from deployed apps

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(apps): confine S3 viewer fallback to full unscoped sessions

A scope-restricted token (e.g. apps:read:<app>, or an app-embed token) is
allowed on apps_u/* but rejected by the route-scope middleware on job_helpers/*,
so granting it the viewer fallback would be a new capability it cannot obtain
directly. Gate the fallback on scopes.is_none() so only full sessions (which can
already read via job_helpers) delegate; scoped and anonymous callers stay gated.
Add a scoped-token isolation assertion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(apps): treat filter-tags-only tokens as unscoped for S3 viewer fallback

The scopes.is_none() guard wrongly denied the viewer fallback to tokens that are
effectively unscoped (empty scope arrays and if_jobs:filter_tags:-only tokens),
which the route-scope middleware treats as unrestricted and which can therefore
read the same file via job_helpers directly. Reuse that semantics via a shared
is_effectively_unscoped helper so the relaxation covers exactly the tokens that
gain no new capability, while genuinely scoped tokens stay gated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 17:04:01 +00:00
Diego Imbert 555c751016 fix(db): repair s3 asset paths missing default-storage leading slash (#10243)
* fix(db): repair s3 asset paths missing default-storage leading slash

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01An2pTqSmqJd2XwnagvX4kM

* fix(db): also repair script_trigger refs + exclude _default_ storage alias

Extend the s3 leading-slash repair beyond the asset table:

- script_trigger.trigger_ref (pipeline cascade edges, stored as s3://<path>)
  suffered the identical corruption: a window-era default-storage edge was
  recorded as s3://exports/x instead of s3:///exports/x, so it no longer
  matches the producer's post-fix write ref at dispatch (asset_dispatch does
  an exact trigger_ref = match with no DISTINCT), silently breaking the edge.
  Repaired with the same storage-name heuristic, with a dedup DELETE to avoid
  double-dispatch.

- Exclude the reserved _default_ alias from the storage-name set. The runtime
  treats s3://_default_/key as the primary storage (fork_storage_ref), so
  _default_/key is a valid explicit-default ref; prepending a slash would
  corrupt it. Applies to both asset and script_trigger via the shared cache.

join_pending_inputs (transient AND-join state) and materialized_asset_schema
(ducklake-only) are intentionally left alone; documented inline.

Verified end-to-end on a fresh DB: seed prior-state rows as the pre-fix parser
would have persisted them for data pipelines and scripts, run the full
migration suite, assert every row matches the fixed-parser identity (default
repair, hive/root/nested keys, named-storage + _default_ untouched, pre-cutoff
untouched, non-s3 untouched, duplicate collapse) across both tables.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-07-21 17:03:42 +00:00
Diego Imbert 7fb8a2e390 fix(parsers): keep s3 asset path suffix verbatim to preserve storage distinction (#10241)
* fix(parsers): keep s3 asset path suffix verbatim to preserve storage distinction

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01An2pTqSmqJd2XwnagvX4kM

* package json

* fix(pipelines): preserve named storage in generated TS/Python S3 URIs

The TS/Python templates emitted `s3:///${s3Key(path)}`, stripping the
leading slash and pinning the URI to default storage. For a named-storage
asset path (`secondary/key`) that produced `s3:///secondary/key`, which
resolves to the default storage with key `secondary/key`, dropping the
named-storage dependency and reading/writing the wrong object.

Emit the path verbatim after `s3://` (matching the DuckDB template) so a
named-storage input/output keeps its storage; identical to the previous
output for default-storage paths. Removes the now-unused `s3Key` helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(cli): align bun.lock parser versions with frontend

The PR bumped windmill-parser-wasm-asset (1.749.0→1.753.0) and
windmill-parser-wasm-regex (1.692.0→1.764.0) in package.json and the npm
package-lock.json for both cli and frontend, but cli/bun.lock was left
pinned to the old versions. Sync it so the CLI's wasm asset parser (used
by localGraph inference) matches the frontend and deploy-time parser.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-07-21 16:25:06 +00:00
Ruben Fiszel 2caee41fdf fix(worker): mount /dev/shm as tmpfs in the Docker v2 nsjail sandbox (#10240)
The Docker v2 nsjail profile provided /dev/null, /dev/zero, /dev/random,
and /dev/urandom but omitted /dev/shm, since generate_rootfs_mounts()
skips the image's own /dev in favor of the profile's device nodes. Any
program needing POSIX shared memory (Ansible/Python multiprocessing,
Chromium) failed with "No such file or directory: /dev/shm".

Add a /dev/shm tmpfs mount, matching run.ansible.config.proto and
run.python3.config.proto.

Fixes WIN-2216

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 15:49:29 +00:00
Ruben Fiszel 68debab877 feat(triggers): add AMQP (RabbitMQ) trigger via lapin (#10230)
* feat(triggers): add AMQP (RabbitMQ) trigger using the lapin library

Fixes WIN-2214

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(triggers): defer AMQP cross-workspace deploy pending utils-internal publish

Revert the amqp_trigger additions to the shared windmill-utils-internal
TriggerDeployKind and the frontend cross-workspace deploy adapter: the
frontend installs the published npm package, which lacks the new kind
until a release is cut. AMQP create/edit/delete/list/sync/capture are
unaffected (they use local types); only cross-workspace deploy/merge of
AMQP triggers waits on the package bump. Also document the at-most-once
ack in the consumer loop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(triggers): address AMQP review — at-least-once ack, workspace cascade, contracts

- ack AMQP deliveries only after successful dispatch; nack+requeue on failure
- add ON DELETE CASCADE workspace FK so amqp_trigger rows are cleaned on
  workspace deletion (and the listener stops)
- fix the /amqp_triggers/test OpenAPI body and add amqp_trigger to
  WorkspaceDiffRow.kind
- register AMQP in the generated workspace trigger tool (create_trigger)
- drop banned $bindable defaults on optional props in the config section
- add build_uri unit tests (encoding, ports, vhost)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(triggers): stop AMQP poison-message loop and reconnect on transient drops

Chaos testing against a live RabbitMQ broker showed the previous
nack(requeue) + immediate re-poll spun a tight redelivery loop (~1000
critical-error reports/sec) on a poison message, and any connection blip
permanently disabled the trigger (lapin has no built-in reconnect).

- on dispatch failure: nack+requeue then stop consuming; the listener
  framework re-lists the trigger after its ping goes stale (~15s), backing
  redelivery off to that cadence instead of a tight loop (verified: rate
  dropped from ~1000/s to ~1 per ~26s, message preserved)
- on connection/stream error: stop and let the framework reconnect instead
  of disabling; persistent failures are still disabled via get_consumer
  (verified: a forced connection close now auto-reconnects and resumes)
- finish the AI create-trigger action wiring for AMQP: add amqp to
  CreatedResourceTriggerKind, the action-card registry, and the drawer
  registry so the result card renders and its "Open" action works

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(triggers): complete AMQP frontend registries and defer merge rows

- add amqp to capturableTriggerTypes (so AmqpCapture mounts), the Runs
  jobTriggerKinds filter, and CLOUD_DISABLED_TRIGGER_TYPES
- wire AMQP into global AI chat mode: TRIGGER_KINDS, the request union,
  writeTriggerSchema, triggerServices, and the draft adapter
- stop emitting actionable AMQP fork-comparison rows (revert amqp_trigger
  from TRIGGER_OR_SCHEDULE_TABLES) since cross-workspace deploy is deferred
  until windmill-utils-internal is published — avoids a deploy that fails
  with "Unknown kind: amqp_trigger"
- use design-system TextInput instead of raw <input> in the config section

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(triggers): complete AMQP session/draft registries and constrain prefetch

- add amqp to the session-deploy, draft-compare, preview-router, and
  copilot workspace-item registries so AMQP drafts/deploys/nav/path
  resolution work
- include amqp_count in the MoveDrawer attached-trigger rename warning
- replace the raw prefetch <input> with a design-system TextInput bounded
  to an integer 1-65535 (backend u16) and block save on invalid values

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(triggers): make AMQP disconnect/reconnect consistent with the Kafka trigger

lapin, like rdkafka, has no transparent reconnect, so the AMQP listener now
mirrors the Kafka trigger's explicit reconnect loop instead of relying on the
framework re-list (which disabled the trigger once get_consumer failed on a
sustained outage):

- get_consumer returns cheaply; consume owns a (re)connect loop that retries
  with a 30s backoff, reports a critical error every 10 failed attempts, and
  reports a recovered critical error once it reconnects — never disabling the
  trigger on a connectivity failure
- a consumer/stream error breaks out to reconnect rather than disabling
- dispatch failure still nacks+requeues (at-least-once) with a short backoff
  to avoid a tight poison-message loop, keeping the connection alive

Verified against a live RabbitMQ broker: killing the broker keeps the trigger
enabled and retrying (attempt N), and restarting it auto-reconnects (logs
"reconnected after N attempts") and resumes dispatch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(triggers): complete AMQP capture registries and constrain prefetch contract

- add the 'amqp' case to triggerKindToTriggerType so opening the AMQP editor
  from a capture button no longer throws "Unknown TriggerKind: amqp"
- register AmqpIcon in CaptureTable's icon map and add an AMQP entry to the
  script/flow CaptureButton menu
- bound the OpenAPI prefetch_count to an integer 1-65535 (matches the Rust
  u16) and regenerate clients/prompts
- require a non-empty exchange name when the exchange binding is enabled
- build_uri: fall back to "/" on a blank vhost and bracket IPv6 hosts (+ tests)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(triggers): wire AMQP into pipeline graph, git-sync, and preprocessor types

- asset_graph: discover attached amqp_trigger rows and emit an AMQP TriggerEdge
  so AMQP triggers render (and can be opened/deleted) on the data-pipeline canvas
- frontend pipeline graph: add amqp to NativeTriggerKind, the add-trigger menu,
  node presentation, event-trigger set, annotation keywords, and the
  editor/service registrations
- git-sync: add the amqp_trigger include pattern (+ test) so an AMQP git-sync
  deployment stages only its .amqp_trigger.* file, not an unrelated same-path object
- preprocessor starters: add the AMQP event to the generated TS/Python/PHP
  trigger event types (kind/payload/exchange/routing_key/queue_name/redelivered/
  delivery_tag)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(triggers): finish AMQP pipeline/parser wiring, prefetch validation, source lists

- fix a stray edit that corrupted the pre-existing MqttTriggerEditor import
  ($lib/... path) in PipelineTriggerEditors.svelte
- reject prefetch_count = 0 server-side in validate_config (RabbitMQ treats 0
  as unlimited) and defensively skip basic_qos(0) in build_consumer (covers
  the capture path that bypasses CRUD validation)
- recognize `// on amqp` in the canonical parser (TriggerSpec::Amqp) and add
  amqp to the CLI non-autorun/event-trigger sets so a pipeline cascade never
  runs an AMQP-only node as a manual root without an event
- add amqp to the preprocessor intro lists and both pipeline AI instructions

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(triggers): reject zero AMQP prefetch in all paths and finish guidance lists

- extract a shared validate_amqp_options used by both CRUD validate_config
  and build_consumer, so capture configs (which bypass CRUD validation) also
  reject prefetch 0 instead of silently connecting with an unlimited buffer
  (+ unit tests for 0/1/65535/None)
- add AMQP to the main script-writing preprocessor-sources prompt and the CLI
  triggers-skill guidance list

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(triggers): de-duplicate AMQP prefetch comment and fix GET response text

- keep the zero-prefetch rationale only on the shared validate_amqp_options
  doc; drop the redundant call-site comments
- correct the getAmqpTrigger OpenAPI 200 description ("deleted" -> "retrieved")

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref to aaa6cb89b05b76139252c64f057e53b94d12ac60

This commit updates the EE repository reference after PR #680 was merged in windmill-ee-private.

Previous ee-repo-ref: 5da5fd65aca9594b2611837a52e4677b544b0380

New ee-repo-ref: aaa6cb89b05b76139252c64f057e53b94d12ac60

Automated by sync-ee-ref workflow.

* chore(migrations): consolidate the four AMQP migrations into one

The table and the three enum ADD VALUE statements (trigger_kind, job_trigger_kind,
draft_kind) are one atomic feature. ALTER TYPE ... ADD VALUE runs inside the
migration transaction on PG >= 14 (Windmill's minimum) since the amqp_trigger
table doesn't reference those enum types, so they can share a single migration
instead of four. Verified applying cleanly in a single transaction on a fresh DB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-07-21 15:10:29 +00:00
hugocasa c7ee192680 update ee ref to git sync cli prompt fix (#10224) 2026-07-21 14:37:38 +00:00
Diego Imbert d24e176816 fix(parser): spurious pg arg inferred from placeholders in comments (#10226)
* fix(parser): ignore pg placeholders in comments, strings and dollar quotes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NXWRDKzswMeDBP5THXpb9Q

* package json + lock

* chore: remove stray root npm lockfiles

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013kuUhCPD9ph4ZuFd13SCWJ

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:36:44 +00:00
Ruben Fiszel 6e42633643 fix(pg): actionable error when s3object input exceeds jsonb 256MB cap (#10228)
Native SQL PostgreSQL scripts with an `(s3object)` input materialize the
whole referenced file into a single jsonb parameter. PostgreSQL hard-caps a
jsonb value's element payload at 256MB, so a large file fails with an opaque
`total size of jsonb array elements exceeds the maximum of 268435455 bytes`.

`materialize_s3object_args` now reports the largest materialized payload, and
that specific server error is rewritten into guidance explaining the input is
materialized (not streamed) and pointing large-file users at DuckDB, which
reads S3 natively and streams.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 10:21:34 +00:00
Ruben Fiszel 39058c0a01 fix(postgres-triggers): enforce resource-path scopes on ancillary routes (#10222)
* fix(postgres-triggers): enforce resource-path scopes on slot/publication routes

The Postgres trigger ancillary routes (slot management, publication
management, version/logical-level checks, template script creation) relied
only on the route-level middleware, which validates the scope domain+action
but delegates resource-path enforcement to each handler. These handlers made
no check_scopes call, so a token scoped to one postgres resource path (e.g.
postgres_triggers:write:u/alice/*) could drive these endpoints against any
postgres resource in the workspace, including the destructive drop_slot_name
(pg_terminate_backend + pg_drop_replication_slot).

Add a check_scopes call at the top of each affected handler, before any
connection is opened, mirroring the generic trigger CRUD handlers. Read
endpoints require postgres_triggers:read:{path}; write endpoints require
postgres_triggers:write:{path}.

Fixes WIN-2213

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: condense postgres_trigger_scope test module comment

Address Codex nit: state the durable constraint (mismatched scope must fail
before DB access) instead of narrating pre-fix behavior and change history.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 09:21:07 +00:00
Ruben Fiszel fd51d40f12 feat(pipelines): catalog declared measures and dimensions (#10190) 2026-07-21 07:34:44 +02:00
hugocasa adc555d172 fix(triggers): apply scope-path filtering to list and fix update scope check (#10220)
The shared `list_triggers<T>` handler returned every trigger row of its
type in the workspace regardless of the token's declared scope. A token
limited to e.g. `http_triggers:read:<prefix>/*` could enumerate all
trigger paths (and their configs) through the `/list` endpoint, while
`get_trigger`, `create_trigger`, `delete_trigger` and `exists_trigger`
correctly rejected them. This affected all 10 TriggerCrud kinds (HTTP,
WebSocket, Kafka, NATS, MQTT, SQS, GCP, Azure, Postgres, Email).

Apply `build_scope_path_predicate(&authed, T::scope_domain_name(),
"read")` to the returned rows after the draft-only append, mirroring
scripts, flows, apps, resources, variables and schedules. A `HasPath`
supertrait on `Self::Trigger` exposes the row path to the shared handler
without each impl restating it (`Trigger<T>` returns `&base.path`, the
`()` OSS stub returns "").

Also fix `update_trigger`: it only checked scope against the new path in
the request body, letting a scoped token move a trigger it can't touch
into its scope. Now check both the existing path (URL) and the new path.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 07:09:31 +02:00
Ruben Fiszel 7ec56ef619 fix: require auth on GET /concurrency_groups/{job_id}/key (#10221)
The /concurrency_groups global service is registered after the router's
.route_layer(from_extractor::<ApiAuthed>()), and Axum's route_layer only
wraps routes present at the call site, so this handler was left with no
router-level auth. Unlike its siblings list_concurrency_groups and
prune_concurrency_group, get_concurrency_key declared no ApiAuthed
parameter, so GET /api/concurrency_groups/{job_id}/key was reachable
unauthenticated and would return concurrency keys (which can embed
workspace ids, script/flow paths, and $args-templated argument values)
for arbitrary jobs instance-wide.

Add _authed: ApiAuthed so the extractor independently enforces
authentication regardless of layer placement, matching the
defense-in-depth pattern of the sibling handlers.

Fixes WIN-2212

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 07:08:16 +02:00
Ruben Fiszel 858d9a5527 chore(main): release 1.764.0 (#10196)
* chore(main): release 1.764.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-07-20 22:56:04 +02:00
Ruben Fiszel ddec2abbb3 feat(jobs): cap total queued jobs per workspace on cloud (#10218)
* feat(jobs): cap total queued jobs per workspace on cloud

A workspace could flood the queue with an unbounded number of jobs across
many concurrency keys and scripts (or keyless jobs), which the per-key
cap from #10197 does not bound. Add a companion instance-wide ceiling on
a workspace's total queued jobs.

check_workspace_queue_cap rejects a push once the workspace has
WORKSPACE_MAX_QUEUED_JOBS (default 20000, superadmin-configurable, 0 to
disable) jobs queued, cloud-only and runtime-gated on CLOUD_HOSTED like
the per-key cap. It runs on every push, so it applies even to premium
workspaces and catches parallel for-loop floods. Jobs already queued
still drain; only new pushes past the ceiling are rejected, so an
in-flight flow only fails to push further work while at the ceiling.

The setting loader self-gates on CLOUD_HOSTED so it is never loaded off
cloud, from initial load or a settings-change reload. The depth count is
bounded by the cap via LIMIT so a runaway backlog never costs an
unbounded scan on the push path.

* docs(jobs): note the workspace cap is a soft ceiling and the depth helper is count-only

Records the two review points as constraints: the cap does not serialize
admission (a soft ceiling by design, like the per-key cap), and
workspace_queue_depth is pub only for the test, returns a count not job
data, and leaves authorization to the caller.
2026-07-20 22:09:59 +02:00
hugocasa b070f56c5e feat: detect server-handled git-sync so CLI picks git push vs wmill sync push (#10201)
* feat: detect server-handled git-sync so CLI picks git push vs wmill sync push

Add a non-admin GET /w/{w}/workspaces/git_sync_deploy_mode endpoint returning
{configured, deploy_on_push}, so any workspace member (not just admins, who
alone can read get_settings) can tell whether pushing to the git remote deploys
via server-side auto-pull. Surface it through `wmill gitsync-settings status`
and align the deploy guidance/skills to prefer git push when the repo deploys on
push, falling back to `wmill sync push` otherwise.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: address review — clean JSON output, warn on git_sync parse failure

- gitsync-settings status --json-output now uses console.log so the JSON pipes
  cleanly to jq (log.info wraps it in ANSI color codes)
- get_git_sync_deploy_mode logs a warning on git_sync deserialize failure instead
  of silently reporting configured=false, and documents why it is not EE-gated

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: address codex review — license-gate and branch-match deploy-on-push

- get_git_sync_deploy_mode now reports deploy_on_push only on Enterprise-licensed
  instances (auto-pull can't run on CE/downgrade) and returns auto_pull_branches
  so the client knows which tracked branches actually deploy on push
- gitsync-settings status matches the local git branch against auto_pull_branches
  before recommending git push, so an untracked branch falls back to wmill sync push
- add an integration assertion for the endpoint's default (no git-sync) shape

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: point per-topic skills at the canonical Deploying section

The git-push-vs-wmill-sync-push decision lives in core.ts (AGENTS.wmill.md),
which is already in context. Have the per-topic skills reference the Deploying
section instead of re-encoding the detection, so there is one source of truth
and no drift (the compressed version also wrongly implied `gitsync-settings
status` detects the CI-workflow path, which only core.ts's filesystem check does).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: match remote+branch server-side for deploy-on-push detection

Codex flagged that a workspace-level auto-pull signal recommends `git push` even
when the local checkout is a different repo/branch than the one that auto-deploys.
Match precisely instead, without exposing anything sensitive:

- git_sync_deploy_mode takes optional remote+branch query params. The backend
  normalizes each auto-pull repo's URL to host/path (dropping embedded
  user:token credentials by rebuilding from parsed components, never scrubbing
  the string) and compares to the caller's remote; deploy_on_push is true only on
  a licensed instance where an auto-pull repo matches that remote and tracked
  branch. The response is two booleans — no repo URLs or branches leave the server.
- Branchless (default-branch) and fork/sync_forks repos stay a safe fallback to
  `wmill sync push` rather than a wrong git-push recommendation.
- CLI status sends `git remote get-url` + current branch (new getGitRemoteUrl
  helper, --remote flag) and reports the matched result.
- Unit-test the URL normalization/credential-stripping directly, since a
  regression there would be a token-handling bug.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: address codex security findings in deploy-mode detection

- Strip credentials from the local remote client-side before sending, so a
  token embedded in the URL never reaches the server's request-URI logs
- Fetch the remote via spawnSync arg array (not an interpolated shell string),
  removing a command-injection path from a caller-supplied --remote value
- Use the remote's push URL (`git remote get-url --push`) and recommend the
  qualified `git push <remote> <branch>`, so the pushed target matches the one
  the server checked
- Keep the port in remote normalization so different services on the same host
  don't collide into a false match
- Unit-test credential stripping (CLI) and port distinctness (backend)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: resolve $var repos and fork sync_forks in deploy-mode detection

- Interpolate $var:/$res: references in the repo url/branch the same way the
  auto-pull poller does (system context, cached, only when a field is a
  reference), so variable-backed git URLs match instead of falling through
- For a fork workspace, evaluate the root ancestor's git-sync settings and treat
  its wm-fork/<base>/<id> branch as deploying when the root repo has
  auto_pull.enabled && sync_forks and its base matches the tracked branch
- Read settings/resources on the plain pool (a fork member may not belong to the
  root workspace); only booleans are returned
- Unit-test the fork/branch matching (base + sync_forks + workspace-id suffix)

A blank tracked branch (repo default) still needs a network ls-remote to resolve,
so it stays a safe fallback to `wmill sync push` rather than a wrong git push.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: share one git-repo resolver between poller and deploy-mode

The auto-pull poller and the deploy-mode endpoint both resolved a git-sync repo
resource (system context, $var:/$res: interpolation) with duplicated boilerplate.
Extract windmill_store::resources::resolve_git_repository_resource and have both
call it, so the interpolation lives in one place. Drops the endpoint's local
resolve_repo_url_branch helper and its raw SQL query (and cache entry).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: address codex review — fork false-positives, shell-safety, auth contract

- Fork deploy detection now mirrors reconcile_fork_branch_pull: the wm-fork branch
  must route to this workspace (first existing of the id candidates) and the repo
  must be in the fork's own inherited settings, so a multi-repo root or an
  ambiguous id can't produce a false deploy_on_push
- Recommended deploy command is shell-quoted (branch/remote names may contain
  metacharacters and the output is agent-executed)
- Remote normalization folds only the host; repo paths stay case-sensitive
- Document the system/RLS-bypassing contract on the shared resolve helper and
  restore the head-fetch doc; fix the overclaiming integration-test comment
- Dev-workspace label and default-branch cases remain documented safe fallbacks

Also restores 5 sqlx cache entries an earlier cleanup dropped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: require a runnable auto-pull delivery path for deploy_on_push

enabled auto-pull alone doesn't mean a push deploys: a webhook-only repo with no
active hook (failed registration), or a repo that only polling could serve on an
SSH URL (the poller rejects SSH), delivers nothing. Gate deploy_on_push on an
actual delivery path — active webhook, or a pollable non-app HTTPS repo — per the
repo's auto-pull mode. Unit-tested across modes/webhook/URL-scheme/app.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: read fresh repo config for on-demand deploy-mode detection

resolve_git_repository_resource took an implicit allow_cache=true (right for the
poller loop). An on-demand status could then match against a stale url/branch
cached by an earlier poll. Make allow_cache a parameter: poller keeps true, the
deploy-mode endpoint passes false so it reflects the current git-sync config.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: defer the deploy fallback instead of assuming wmill sync push

When backend auto-pull doesn't match the checkout, `status` no longer flatly
recommends `wmill sync push` — a CI workflow may still deploy on push. It now
reports the backend signal and points at the Deploying guidance (check CI → git
push, else wmill sync push; record the choice as a `Deploy mode:` line in
AGENTS.md). deploy_command is null in JSON when undetermined. This resolves the
CI-backed false recommendation without the CLI re-implementing CI detection.

Also fix two review nits: restore the deploys_on_push_branch doc comment (it had
drifted onto has_runnable_delivery) and correct the app-repo comment (their
exclusion from the poll path is a conservative safe under-report, not "can't be
polled").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: drop the ambiguous-fork-id disambiguation from deploy-mode

The existence-query resolution guarded a very narrow case (a suffix owned by both
a coexisting wm-fork-<suffix> and <suffix> workspace, queried from the wrong one).
Not worth the per-fork query; keep the cheap candidate-family check plus the
inherited-repo membership test, which already close the real fork false-positive.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: drop remote-URL matching; disambiguate deploy-mode by repo count

Matching the caller's git remote URL against each repo dragged in the whole
remote-URL surface (sending the URL, credential stripping, shell-safe remote
handling, fetch/push URL, port/case normalization) — and the risk that came with
it. Replace it with a simpler rule that fits the actual question:

- deploy_on_push is true only when exactly ONE licensed, deliverable auto-pull
  repo tracks the pushed branch. With a single synced repo the local checkout is
  unambiguously it; with several we can't tell which is the caller's, so we
  return false and the CLI asks the user.
- The endpoint takes only `branch` (no `remote`); status no longer reads or
  sends the git remote.
- On the fallback, status now tells the agent to ASK the user how the repo
  deploys (CI git-push vs wmill sync push) and record it in AGENTS.md, instead of
  assuming wmill sync push. Guidance updated to match.

Removes normalize_git_remote (+url dep), getGitRemoteUrl, stripGitRemoteCredentials,
shellQuote, the --remote flag, and their tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: share fork-branch routing between reconciler and deploy-mode

Deploy-mode detection was re-deriving fork/dev routing (root walk, wm-fork/dev
branch parsing, descendant resolution, inherited-repo check) that the auto-pull
reconciler already owns — the source of repeated edge-case bugs. Extract it into
windmill_common::workspaces::resolve_fork_branch_target and have both the endpoint
and reconcile_fork_branch_pull (EE) call it, so they can't drift and dev
workspaces are handled by construction.

Endpoint now resolves the root via the canonical cached fork_ancestor_chain
(dropping a duplicate CTE) and routes forks/dev workspaces through the shared
resolver. The .sqlx cache is unchanged (the moved queries already existed).

Bumps ee-repo-ref for windmill-labs/windmill-ee-private companion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: exclude archived roots and frame deploy_on_push:false as unconfirmed

- deploy_on_push now requires the root workspace to be live; polling and webhook
  delivery both exclude deleted roots, so an archived root (or anything beneath
  one) with retained git-sync no longer reports deployable
- status and the OpenAPI now describe false as "not confirmed" (it also covers
  ambiguity and conservative false-negatives), not a definite no — the CLI asks
  the user rather than asserting the push won't deploy

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump ee-repo-ref for EE branch merge of main

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 21:44:24 +02:00
hugocasa 11fda89b52 feat(telemetry): generic feature-usage telemetry with AI session metrics (#10200)
* feat(telemetry): add generic feature_usage table and batched logging endpoint

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(telemetry): log AI session usage events and document them in telemetry settings

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): use escape sequence instead of literal NUL bytes in buffer key

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): validate dimensions, decouple retention, keepalive flush

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): allowlist feature-usage dimensions and index retention scans

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): pin tool-name allowlist and deploy session attribution

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(telemetry): route AI chat usage through feature_usage and drop ai_chat_usage

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(telemetry): slim dimension validation to registered kinds plus key shape

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): backfill ai_chat_usage into feature_usage before dropping it

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): disclose provider and model identifiers in telemetry settings text

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(telemetry): issue all flush chunks before awaiting so pagehide keeps them

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore: update ee-repo-ref to 6306c072a50937ea9af44a5bcf42345543207486

This commit updates the EE repository reference after PR #672 was merged in windmill-ee-private.

Previous ee-repo-ref: 964f242a0eb44db7f7d26636cc8d76aeabea2b73

New ee-repo-ref: 6306c072a50937ea9af44a5bcf42345543207486

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Fable 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>
2026-07-20 20:56:57 +02:00
windmill-internal-app[bot] f635bd5ae7 chore: refresh vendored docs snapshot (#10068)
Co-authored-by: hugocasa <15649739+hugocasa@users.noreply.github.com>
2026-07-20 20:43:03 +02:00
hugocasa 87be041c09 fix(git-sync): avoid percent-encoded colon in git-sync hub script path (#10213)
* fix(git-sync): avoid percent-encoded colon in git-sync hub script path

The git-sync init/detection hub script slug contained a colon stored as
`%3A` in the run-by-path URL. The generated API client re-encodes path
params with encodeURI, turning `%3A` into `%253A` (double-encoding). Some
hardened reverse proxies / WAFs reject double URL-encoding and return a
bare 400 before the request reaches Windmill, breaking git-sync repository
detection on those instances.

The hub resolves scripts by numeric id and ignores the slug, so dropping
the colon from the slug is behavior-neutral (same script, same id-keyed
worker cache) while producing a colon-free run URL.

Also force-cache GIT_SYNC_PULL_SCRIPT_PATH at build alongside
LATEST_GIT_SYNC_SCRIPT_PATH so the backend-driven pull script is always
baked into the image for airgapped workers, instead of relying on an
incidental hubPaths.json overlap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump ee-repo-ref for git-init slug match fix

Pulls in windmill-ee-private#676 so the EE is_git_init_script check matches
the colon-free git-init hub slug (GitHub App token grant for git-sync jobs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump ee-repo-ref for git-init slug helper + test

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref to a3adea1ffb406e709cc480871df58fab6c51aca1

This commit updates the EE repository reference after PR #676 was merged in windmill-ee-private.

Previous ee-repo-ref: cef4e008ef62dec434aa9bb3ec783db8aff6a1c1

New ee-repo-ref: a3adea1ffb406e709cc480871df58fab6c51aca1

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-07-20 20:36:34 +02:00
hugocasa 2b58df57fc feat(ai): extract prompt cache token usage from OpenAI and Azure providers (#10214)
* feat(ai): extract prompt cache token usage from OpenAI and Azure providers

Parse the nested cache token details OpenAI returns and thread them into
TokenUsage, matching the Anthropic and Bedrock providers.

- sse.rs: add OpenAIPromptTokensDetails / OpenAIInputTokensDetails and the
  optional prompt_tokens_details / input_tokens_details fields.
- other.rs (Chat Completions) and openai.rs (Responses): populate
  cache_read via .with_cache(cached_tokens, None).

OpenAI's prompt_tokens/input_tokens already include cached tokens (cached is
a subset), so total/prompt are unchanged; cache_read is recorded separately
for reporting. For the same reason the frontend token-usage conversions are
left as-is (adding cached would double-count); optional cache fields and a
clarifying comment are added to prevent a future incorrect Anthropic-style fix.

Fixes WIN-2207

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(ai): pin OpenAI/Azure cache-token deserialization paths

Add regression tests deserializing the real Chat Completions and Responses
usage payloads, guarding the prompt_tokens_details.cached_tokens /
input_tokens_details.cached_tokens paths against a silent rename.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(ai): extract to_token_usage() and test the cache mapping

Address review nit: move the usage->TokenUsage conversion into
OpenAIChatUsage::to_token_usage / OpenAIResponsesUsage::to_token_usage so
the providers call one method and the tests exercise the real mapping.
Tests now assert cache_read is populated while input/total are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 18:47:25 +02:00
Ruben Fiszel 38ceae1a09 fix(db): grant schema usage and re-run windmill role grants (#10212)
* fix(db): grant schema usage and re-run windmill role grants

Migration 20250205131523 grants the windmill_user and windmill_admin
roles access to the schema and its tables, but its first statement is
LOCK TABLE pg_catalog.pg_roles, which requires superuser. On managed
Postgres (RDS, Cloud SQL) the migration user is not one, the lock
raises, and the block's EXCEPTION WHEN OTHERS handler downgrades the
failure to a NOTICE, so every GRANT after it is skipped. Core tables end
up ungranted and queries on a user_db transaction (SET LOCAL ROLE
windmill_user/windmill_admin) fail with "permission denied for table"
or, when schema USAGE was never granted, "relation does not exist".

Add a migration that re-runs those grants without the lock and without a
catch-all handler, and add the missing GRANT USAGE ON SCHEMA public to
init-db-as-superuser.sql, which PostgreSQL 15+ no longer implies for
PUBLIC. The init script also now creates windmill_admin before the table
grants so role membership is in place when they run.

Fixes WIN-2208

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(db): correct schema-privilege rationale in grant migration

PostgreSQL 15 revoked CREATE, not USAGE, from PUBLIC on the public
schema, so USAGE is still granted by default there. The explicit grant
is what a hardened database that revoked it needs, not a PG15 default.
Also correct the description of what 20250205131523's failure actually
loses: 20221105003256 grants the tables outside any locked block, so the
gap is the ALTER DEFAULT PRIVILEGES covering later-created tables.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(db): grant only runner-owned objects to avoid aborting upgrade

GRANT ALL ON ALL TABLES IN SCHEMA raises a hard "permission denied for
table X" the moment the schema holds an object the migration runner does
not own (a superuser-installed extension such as PostGIS spatial_ref_sys,
or a co-located application table). With no catch-all handler that would
abort the whole upgrade -- a regression against 20250205131523, which
tolerated it only by swallowing every error.

Grant per-object over just the tables and sequences the runner owns,
which is exactly the set the GRANT can succeed on. Windmill's own tables
are all runner-owned, so coverage is unchanged; foreign objects are
skipped rather than aborted on. ALTER DEFAULT PRIVILEGES stays (it only
governs the runner's future objects, so it cannot conflict).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(db): guard each grant so the migration can never abort an upgrade

Wrap every grant in its own BEGIN/EXCEPTION/WARNING so no single failure
can abort the migration -- the opposite of 20250205131523's one
block-wide WHEN OTHERS, whose flaw was granularity: a single early
failure there silently skipped every remaining grant. Here each grant
that cannot be applied is isolated, re-raised as a named WARNING, and the
rest still run.

This closes the last abort paths: a grant on an object dropped by another
session between the catalog scan and the GRANT, USAGE on a schema the
runner cannot grant, or a missing role, now warn and continue instead of
failing the upgrade. On a clean owned schema the guards never fire (zero
warnings, verified). The owner filter stays so foreign objects are
skipped without even a warning; the guard is the backstop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(db): also grant runner-owned views and materialized views

pg_tables returns only ordinary and partitioned tables, so the previous
loop left owned views (flow_workspace_runnables and any materialized
views) ungranted -- a coverage regression against the GRANT ... ON ALL
TABLES form, which grants views too. Those views are read through
user_db transactions, so windmill_user/windmill_admin need access.

Enumerate pg_class over the relkinds ALL TABLES covers (r, p, v, m, f),
keeping the ownership filter so foreign objects are still skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(db): grant by effective authority, not owner-name equality

Filtering relations by pg_get_userbyid(relowner) = current_user skips
objects the runner can legally grant but does not own by name: after a
migration-credential rotation, tables and sequences stay owned by the
previous runner while the new runner grants through inherited membership
(or as a superuser). Owner-name equality would leave those ungranted and
their user_db access broken.

Filter by pg_has_role(current_user, owner, 'USAGE') instead -- objects
the runner owns directly, inherits ownership of, or reaches as superuser.
Genuinely foreign objects (owner the runner is not a member of) are still
skipped, so the per-object guards remain the backstop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(db): scope grants by explicit membership, not superuser authority

pg_has_role treats a superuser as a member of every role, so a superuser
migration runner would grant windmill_user/windmill_admin access to every
co-located relation in the schema -- another application's tables, an
extension's tables -- not just Windmill's.

Compute the runner's role set from pg_auth_members (recursive explicit
membership) and grant only relations owned by it. This still covers the
credential-rotation case owner-name equality missed (the new runner is a
real member of the previous owner) without inheriting the superuser's
implicit authority over unrelated roles.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 18:32:47 +02:00
Ruben Fiszel 71f2d47cb4 feat: cap queued jobs per concurrency key on cloud (#10197)
* feat: cap queued jobs per concurrency key on cloud

* fix: close preprocessed-flow bypass and bound concurrency cap scan

* fix: only cap concurrency keys with an active concurrent_limit

* chore: only load concurrency key cap setting when cloud hosted

* fix: reject queued-job import on cloud
2026-07-20 12:33:40 +02:00
Ruben Fiszel b5e69ffba6 fix(security): enforce token scope filtering on folder list endpoints (#10193)
* fix(security): enforce token scope filtering on folder list endpoints

* fix: apply folder scope filtering before pagination

* fix: keep SQL pagination for unrestricted tokens on folder lists

* fix: bound scoped folder-list scan with chunked pagination

* fix: use keyset pagination for scoped folder-list scan

* refactor: reduce folder scope fix to the minimal predicate filter

* chore: drop folder list scope test
2026-07-20 07:50:50 +02:00
Ruben Fiszel 70359e3a76 fix(schedules): apply scope-path filtering to schedule list endpoints (#10192)
`list_schedule` and `list_schedule_with_jobs` returned every schedule in
the workspace regardless of the token's declared scope. A token limited
to `schedules:read:<prefix>/*` could enumerate all schedule paths (and
their script paths, cron expressions and recent job outcomes) through
these two endpoints, while `get_schedule` correctly rejected them.

Apply `build_scope_path_predicate(&authed, "schedules", "read")` to the
returned rows, mirroring scripts, flows, apps, resources and variables.
In `list_schedule` the filter runs after the draft-only append so both
deployed and draft rows are covered.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 07:32:52 +02:00
Ruben Fiszel f32d7702bc fix(inputs): add ownership check to saved-input args read endpoint (#10194)
`get_args_from_history_or_saved_input` looked up saved-input rows by
`id + workspace_id` only, without checking ownership or `is_public`. The
`input` table has no RLS policy, so any authenticated workspace member
could read another member's private saved-input args (which may hold
credentials) just by knowing the UUID, even though `inputs/list` already
scopes to `is_public OR created_by = caller`.

Add `AND (is_public IS true OR created_by = $4)` to both `input`-table
queries in the handler (the `?input=true` single-query branch and the
default `v2_job UNION ALL input` branch), matching the predicate already
used by `list_saved_inputs`.

The `v2_job` branches are already covered by the table's RLS policies
enforced via `SET LOCAL ROLE windmill_user` in `UserDB::begin()`, so they
are left unchanged.

Fixes WIN-2202

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 07:31:02 +02:00
Ruben Fiszel 60a7a23a04 chore(main): release 1.763.0 (#10186)
* chore(main): release 1.763.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-07-19 10:45:40 +02:00
Ruben Fiszel 89948bb441 chore(git-sync): bump hub scripts to windmill-cli@1.762.3 (#10189) 2026-07-19 10:40:29 +02:00
Ruben Fiszel d5b0a1b5c7 chore(main): release 1.762.2 (#10184)
* chore(main): release 1.762.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-07-18 08:49:56 +02:00
Ruben Fiszel f6e36f862e chore(schedules): lower reconciler re-arm back-off cap to 8 passes (#10182)
Follow-up to #10179. The exponential back-off between reconciler re-arm
retries of a persistently-failing schedule capped at 32 passes (~2.7h at
the default 5-min reconcile cadence). Lower the cap to 8 (~40min) so a
schedule fixed out of band (a lapsed license renewed, a bad cron corrected
directly in the DB) auto-recovers within a few passes, while still cutting
the retry rate sharply versus retrying every pass. Fixes via the UI/API
re-arm immediately and are unaffected.

Fixes WIN-2198

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 08:49:41 +02:00
Ruben Fiszel cba5f0d8a8 fix(scripts): populate auto_kind from draft JSON for draft-only scripts (#10183)
The scripts list endpoint (include_draft_only=true) only populated
auto_kind for the pipeline case, leaving library draft-only scripts
(no `main` function) with auto_kind: null even though the frontend
saves auto_kind: "lib" into the draft JSON. This made it impossible
to distinguish library draft-only scripts from regular ones without a
separate per-script API call.

Fall back to the auto_kind saved in the draft value after the
content-derived pipeline check, which keeps priority since it mirrors
the deploy-time computation.

Fixes WIN-2199

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 08:39:22 +02:00
Ruben Fiszel 252ffd0401 chore(main): release 1.762.1 (#10181)
* chore(main): release 1.762.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-07-17 22:52:46 +02:00
Ruben Fiszel c82056cfde fix(schedules): stop disabling schedules on transient push errors (#10179)
* fix(schedules): stop disabling schedules on transient push errors

A scheduled flow whose next-occurrence push failed after retry exhaustion
used to be disabled, killing a healthy schedule over a transient DB blip
(pool contention, statement timeout). Now that the unarmed-schedule
reconciler exists (#10174), transient failures no longer disable: the
current occurrence runs to completion and the reconciler re-arms the next
occurrence once this run leaves the queue.

In the flow schedule-push path after retry exhaustion we now branch on the
error: QuotaExceeded/NotFound still disable (the schedule's own fault, and
rearm_schedule would otherwise leave them enabled-yet-unarmed forever),
while transient errors are only reported and the flow continues.

The previous iteration returned a SchedulePushZombieError to force a zombie
restart; that is removed, because zombie detection cancels (does not
restart) same-worker flows, so it would have lost the current run of a
same-worker scheduled flow. The now-obsolete SchedulePushZombieError type
and its catch in worker.rs are deleted.

Fixes WIN-2198

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(schedules): back off and surface repeated reconciler re-arm failures

The unarmed-schedule reconciler retried a schedule that could not be
re-armed on every pass, forever, logging only to the server. With the flow
schedule-push path no longer disabling on non-transient errors, a
persistently-broken push (bad stored cron/timezone/args, lapsed license
key) now stays enabled and would spin in that loop silently.

The reconciler now tracks consecutive re-arm failures per schedule:
exponential back-off (2, 4, 8, … passes, capped) between retries so a
broken schedule is not hammered, and after 3 consecutive failures it
surfaces the cause once (records schedule.error + raises a critical alert)
without disabling. Both reset the moment the schedule re-arms, which also
clears the recorded error.

Verified end-to-end on a running server: a flow schedule with a corrupted
cron stays enabled, retries back off, the error is surfaced after the
third failure, and it re-arms and clears the error once the cron is fixed.

Fixes WIN-2198

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 22:48:15 +02:00
Ruben Fiszel 203f6c69dd fix(worker): gate ansible socket-dir name check to unix (#10180)
is_persistent_control_path_dir_name is only referenced from
prepare_socket_root, which is #[cfg(unix)]. On Windows nothing used it,
so -D dead-code failed the build. Gate the function and its unit test to
unix, matching the reaping code they support.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 21:26:40 +02:00
Ruben Fiszel 3ffce7e2cc chore(main): release 1.762.0 (#10175)
* chore(main): release 1.762.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-07-17 20:15:13 +02:00
Ruben Fiszel 0b6bd376db ci: drop stale path_field_renames from mcp runner test constructor
#10176 removed `path_field_renames` from `EndpointTool`, while #10162 added a
new `ep()` test constructor in runner.rs that still set it. Each passed CI
against its own base, but together on main the test build fails with E0560.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 18:11:49 +00:00
hugocasa ae3d9ce2c0 fix(mcp): apply token scopes consistently across mcp endpoint tools (#10162)
* fix(mcp): apply token scopes consistently across mcp endpoint tools

Endpoint-tool authorization is now shared between single- and
multi-workspace modes, honors the token's script/flow path patterns for
every path-taking tool, and the JWT minted for proxied endpoint calls
carries scopes derived from the caller's own.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(mcp): review nits: restore create_http_request doc, reword comments

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:34:17 +02:00
hugocasa d0aa7dca13 fix: parse all names in grouped go param declarations (#10165)
* fix: parse all names in grouped go param declarations

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore: bump windmill-parser-wasm-go to 1.761.0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:24:07 +02:00
Ruben Fiszel 7d2c5ceb0f fix(flows): make updateFlow body path optional so AI can update flows (#10176)
* fix(mcp): default a body field to its same-named path param so updateFlow works

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: trim mcp path-param fallback helper comment

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(mcp): keep path params un-mangled so update tools take plain `path`

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(flows): default update_flow body path from URL via EditFlow

Harmonizes updateFlow with the EditVariable/EditResource/EditApp convention: the
flow to update is identified by the URL, so the body path is optional and only
needed to rename. Fixes the 422 at the API layer for every client (MCP, the
in-app AI chat, raw HTTP), not just the MCP tool schema.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(mcp): drop redundant body-path fallback now that the server defaults it

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: fix stale generator comment after removing mcp body-path fallback

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(flows): mark updateFlow body path optional in the openapi contract

Adds an `EditFlow` schema (path optional) for the update route so the public
contract matches the server; createFlow keeps `OpenFlowWPath` (path required).
Also trims two test comments to record constraints rather than history.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:22:31 +02:00
Ruben Fiszel 2ff5a918d5 feat(worker-tags): add * fork marker to workspace-scoped custom tags (#10177)
* feat(worker-tags): add `*` fork marker to workspace-scoped custom tags

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(worker-tags): pin fork-marker tag admission through real lineage

Also render WorkspaceMatcher in its authored form in the operator-facing
"not in the allowed CUSTOM_TAGS" error, and correct the authorization note
on workspace_with_fork_ancestors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(worker-tags): gate fork-lineage tag lookup on workspace membership

exists_workers_with_tags is a global route whose workspace is a query
param. Resolving its fork lineage for a caller who is not a member
disclosed whether an arbitrary workspace descends from one named by a
tag(parent*) rule. Require membership before the lineage lookup, and
sharpen the workspace_with_fork_ancestors contract accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(sqlx): add offline cache for fork-marker test INSERT query

The new test_fork_marker_tag_admission_through_lineage integration test
inserts a fork workspace with a bind-parameterized query that had no
cached entry, failing the SQLX_OFFLINE=true CI build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 18:18:54 +02:00
Ruben Fiszel 9762089fcb fix(schedules): re-arm enabled schedules left with no queued occurrence (#10174)
* fix(schedules): re-arm enabled schedules left with no queued occurrence

* fix(schedules): lock schedule row while re-arming and report outcome

* fix(schedules): make reconcile lock cancellation-safe, re-check armed under lock

Address review feedback on the schedule reconciler:

- Use a transaction-scoped advisory lock (pg_try_advisory_xact_lock) instead of
  a session-scoped one. monitor_db runs under a 600s timeout; on cancellation a
  session lock on a pooled connection would be stranded, wedging reconciliation
  on every replica. An xact lock releases when its transaction is dropped.
- rearm_schedule re-checks for a queued occurrence under the row lock and
  returns NoOp if already armed, closing the scan→lock window that could
  double-push across a cron boundary. Add a regression test.
- Make reconcile_unarmed_schedules private (its only caller is in monitor.rs)
  and document its system-only contract.
- Log the disable only after the guarded UPDATE actually disables the schedule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(schedules): never disable from reconciliation and cap re-arms per pass

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 18:08:10 +02:00
Alexander Petric 396fb1c475 feat(otel-tracing-proxy): trust internal endpoints with untrusted CAs (#10139)
* [ee] feat(otel-tracing-proxy): trust internal endpoints with untrusted CAs

Add `insecure_upstream_hosts` and `upstream_ca_certs` to the HTTP Request Tracing
settings so the OTEL tracing proxy can reach internal endpoints with untrusted or
private-CA certificates while keeping them traced. Wires the two settings through
the worker config and live reload, adds the inputs to the instance settings UI,
and pulls in the rustls upstream-client deps (hyper-rustls/tokio-rustls/rustls/
rustls-native-certs/rustls-pemfile; hyper-http-proxy switched to its rustls
feature).

The proxy-side implementation lives in the companion EE PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump ee-repo-ref to otel_ca companion commit

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(otel-tracing-proxy): expose new fields in declarative config; bump ee-ref

Addresses code-review findings:
- Add `insecure_upstream_hosts` and `upstream_ca_certs` to the declarative
  `OtelTracingProxySettings` in instance_config.rs so operator/GitOps-managed
  installs can set them and reconciliation no longer drops values saved via the UI.
- Restore the trailing newline on ee-repo-ref.txt and bump it to the companion
  EE commit carrying the strict host-matching / port-ordering fixes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref to 51e50629f48dbc4f5520a787b4bdfb76f4cd38d3

This commit updates the EE repository reference after PR #665 was merged in windmill-ee-private.

Previous ee-repo-ref: 49f458e4446395e98915c220baa757ab3b2ed2d8

New ee-repo-ref: 51e50629f48dbc4f5520a787b4bdfb76f4cd38d3

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-07-17 15:57:00 +02:00
Ruben Fiszel 97f4477069 feat(forks): let a fork's creator manage developers on it without being an admin (#10166)
* feat(forks): let a fork's creator manage developers on it without being an admin

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(forks): bind the fork-creator grant to the member's parent username and lock the delete

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 15:13:36 +02:00
Ruben Fiszel be57dd91e4 fix(ansible): keep persistent-connection socket path under the AF_UNIX limit (#10167)
* fix(ansible): keep persistent-connection socket path under the AF_UNIX limit

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ansible): root socket dir at WINDMILL_DIR and verify we own it

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ansible): fail closed on an untrusted socket root and honor commented section headers

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ansible): validate the socket root after creating it, not before

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ansible): root socket dir at sticky /tmp so the image's 0777 windmill dir cannot disable it

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ansible): only sweep socket dirs the worker could have created

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ansible): drop the configurable socket root, fixing its ancestor and sweep hazards

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ansible): require the socket root be usable, not just safe

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ansible): do not override a control_path_dir the job set itself

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(ansible): drop the dead parent-creation step for the fixed /tmp root

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 15:09:24 +02:00
Ruben Fiszel 6131f7d2ae chore(main): release 1.761.0 (#10148)
* chore(main): release 1.761.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-07-17 00:22:56 +02:00
Alexander Petric 91d6606868 fix(mcp): push granular scope patterns into SQL so scoped scripts/flows aren't truncated (#10140)
* fix(mcp): push granular scope patterns into SQL so scoped scripts/flows aren't truncated

MCP `list_tools` fetched scripts/flows capped at the 100 newest by
`created_at` and only *then* filtered by the token's granular
folder/custom scope in Rust. In a workspace with more than 100
scripts/flows, in-scope items outside that newest-100 window were
truncated before the scope filter ran, so a folder- or custom-scoped
token could see zero tools even though matching items existed.

Push the scope patterns into the query via a new `PathFilter::Patterns`
(mirroring `is_resource_allowed`: `*` disables filtering, exact paths
match by equality, `x/*` matches the folder or its subtree, empty grants
nothing) so the filter applies before the `ITEMS_FETCH_MAX_LIMIT` cap.
The existing hashed-name resolution path keeps its prefix behavior via
`PathFilter::Prefix`, and the Rust post-filter stays as defense in depth.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(mcp): warn in scope selector when a scope exceeds the MCP tool cap

The server exposes at most ITEMS_FETCH_MAX_LIMIT (100) scripts and 100
flows per token; a scope matching more silently drops the overflow, which
bloats the assistant's context with a partial, arbitrary tool set.

McpScopeSelector now computes how many scripts/flows the current scope
would expose (per type, mirroring the backend's is_resource_allowed) and
shows a warning Alert when either exceeds the cap, so the user can narrow
the scope before generating the URL/token. An async sequence guard keeps
rapid scope changes from applying stale counts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(mcp): address review — dedup count fetches, boundary-aware folder counting, fix copy

Follow-up to the MCP scope-selector truncation warning:

- Reuse a single per-type (scripts/flows) cache for both the preview list and
  the exposed count, instead of a second concurrent fetch of the same rows.
- Count a folder scope against the `f/{folder}/*` subtree (via the same
  boundary-aware matcher), so a folder like `team` no longer over-counts a
  sibling like `team2` and falsely warns.
- Custom-mode counts are derived synchronously from the already-loaded
  scripts/flows — no fetch.
- Reword the warning to "most recent" (flows are ordered by edited_at, not
  created_at).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(mcp): anchor folder count fetch at the folder boundary

Follow-up to review: the folder count fetched the unbounded prefix
`f/{folder}` (backend `path LIKE 'f/{folder}%'`), so a prefix-sharing
sibling like `f/team2` shared the page. With a page limit, enough newer
sibling rows could fill the first page ahead of the target folder's older
rows; the client-side boundary filter then dropped them all, wrongly
suppressing the warning and emptying the preview.

Fetch `f/{folder}/` instead so the backend prefix (`LIKE 'f/{folder}/%'`)
is anchored at the folder boundary and never returns siblings. The
client-side matcher stays as a backstop for folder names whose LIKE
wildcards (`_`, `%`) can still let the backend prefix over-match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-07-17 00:15:34 +02:00