Commit Graph
13603 Commits
Author SHA1 Message Date
Diego Imbert cdc7750248 Merge remote-tracking branch 'origin/main' into change-68b704f7
# Conflicts:
#	backend/ee-repo-ref.txt
#	cli/src/commands/datatable/datatable.ts
#	cli/src/guidance/skills.gen.ts
#	system_prompts/auto-generated/cli/cli-commands.md
#	system_prompts/auto-generated/prompts.ts
#	system_prompts/auto-generated/skills/cli-commands/SKILL.md
2026-06-20 18:24:10 +02:00
Diego Imbert 8484c58559 chore: point ee-repo-ref at datatable_migration git-sync companion 2026-06-20 18:20:52 +02:00
Diego Imbert 9e6c4c88e7 feat: add datatable_migration kind to workspace diff pipeline 2026-06-20 18:16:27 +02:00
Diego Imbert 3680972816 compare paeg 2026-06-20 17:20:06 +02:00
Diego Imbert e6f6e55f6b feat: explain migrations purpose with a tooltip in the migrations modal 2026-06-20 16:55:53 +02:00
Diego Imbert ab9071ad39 fix: correct down migration for db manager alters (no double-wrap, serial) 2026-06-20 16:55:24 +02:00
Diego Imbert ad074bd405 feat: generate down migrations for db manager DDL (postgres) 2026-06-20 16:46:23 +02:00
Diego Imbert 40cc718feb fix: don't re-prompt DDL guard when creating a migration without running 2026-06-20 16:40:02 +02:00
Ruben Fiszelandrubenfiszel 346cc30e2d chore(main): release 1.734.0 (#9691)
* chore(main): release 1.734.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.734.0
2026-06-20 16:32:16 +02:00
Diego ImbertandClaude Opus 4.8 b0973c3023 hide primary storage row until added in workspace storage settings (#9692)
* feat(frontend): hide primary storage row until added in workspace storage settings

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

* feat(frontend): red border on empty storage resource picker

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

* feat(frontend): allow deleting primary storage when no secondary storages exist

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

* feat(frontend): disable storage save when a row is missing its resource

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-06-20 16:18:00 +02:00
Diego Imbert ee65da8d83 fix: make migration view editor read-only so its code can scroll 2026-06-20 16:14:53 +02:00
Diego Imbert 32732e599b feat: make datatable migrations opt-in per data table 2026-06-20 15:44:18 +02:00
Ruben Fiszel 3ebf24359d feat: ducklake materialization for data pipelines (#9689) 2026-06-20 15:42:03 +02:00
Diego Imbert 56202da8b9 feat: record db manager DDL on data tables as migrations 2026-06-20 15:33:52 +02:00
Diego Imbert 4ead9cfb04 feat: refresh datatable schema after running a migration from the SQL REPL 2026-06-20 15:30:11 +02:00
Diego Imbert f066eac61d fix: re-prompt instead of stripping DDL when new-migration modal is cancelled 2026-06-20 15:10:01 +02:00
Diego Imbert cc0415b191 fix: ensure detected DDL ends with semicolon when wrapped in transaction 2026-06-20 14:54:00 +02:00
Diego Imbert d19d58ebc4 fix: validate datatable migration name and datatable at the API boundary 2026-06-20 14:51:23 +02:00
Diego Imbert f97a0b2f60 feat: default new datatable migration to a BEGIN/END transaction template 2026-06-20 14:45:00 +02:00
Diego Imbert 68d82dbe54 chore: regenerate CLI docs for datatable migrate commands 2026-06-20 14:41:44 +02:00
Diego ImbertandClaude Opus 4.8 09a80040ca fix(frontend): clear branch step state when switching outer loop iterations (#9650)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 12:22:15 +02:00
Ruben Fiszelandrubenfiszel d5388da953 chore(main): release 1.733.1 (#9685)
* chore(main): release 1.733.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.733.1
2026-06-19 17:37:27 +02:00
Ruben FiszelandClaude Opus 4.8 119d94601d feat(jobs): auto-grant approvers a run-detail view link on the approval page (#9686)
* feat(jobs): auto-grant approvers a run-detail view link on the approval page

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

* feat(approval): show a clear run-details button for logged-in workspace members

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

* fix(approval): build run-details link from route params, not undefined job

getJob is fire-and-forget on the new approval page and is denied for an approver who lacks direct run read access — the exact case this link serves — leaving job undefined and producing /run/undefined. page.params.job is the flow id the view_token is minted for.

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-06-19 17:29:19 +02:00
Ruben FiszelandClaude Opus 4.8 6aa9e515f7 de-flake asset-dispatch debounce test by reading settings from DB (#9687)
The debounce assertion resolved the dispatched job's debounce window through
`prefetch_cached_from_handle`, which goes through the process-global
runnable-settings cache (shared by every test running concurrently in the
binary) and its tempdir-backed file I/O. Read the persisted rows directly from
the test's isolated DB instead, removing that cross-test coupling and extra I/O
from the assertion path. Still validates the full wiring
(handle -> runnable_settings -> debouncing_settings).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 17:16:18 +02:00
960c55e1f3 preserve URL filter state on page refresh (#9680)
* fix(home): preserve URL filter state on page refresh

ListFilters.loadFilterFromUrl() runs synchronously at script init and
sets ownerFilter via binding. When $workspaceStore resolves asynchronously
after mount it triggered the $effect that resets ownerFilter, wiping the
URL-loaded filter before the user saw any results.

Skip the first $workspaceStore resolution using the same firstRun guard
pattern already used in this file (firstWorkspaceRun). Workspace switches
still correctly clear the filter.

Fixes #9624

* refactor(home): reset filters on workspace change instead of first-run guard

Track the previous workspace value and clear filters only when it actually
changes, rather than skipping the first $workspaceStore resolution. Encodes
the real invariant (reset on change) without depending on child/parent init
ordering, and preserves URL-loaded filters on initial mount by construction.

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

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 17:12:34 +02:00
hugocasaandClaude Opus 4.8 c1f31c0e47 fix(backend): validate ansible vault_id entries before config generation (#9681)
* fix(backend): validate ansible vault_id entries before config generation

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

* test(backend): cover ansible.cfg write-boundary vault_id validation

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-06-19 16:54:25 +02:00
hugocasaandClaude Opus 4.8 c39ee07c0b fix: validate websocket trigger urls and gate trigger test route (#9682)
* fix: validate websocket trigger urls and gate trigger test route

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

* docs: clarify validate_websocket_url_for_ssrf call sites

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-06-19 16:54:04 +02:00
hugocasaandClaude Opus 4.8 fb44fe7af2 fix: require super admin for object storage config test endpoint (#9683)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 16:53:49 +02:00
Ruben FiszelandClaude Opus 4.8 1be4df9acb fix(frontend): group live pipeline runs in the activity panel (#9684)
* fix(frontend): refetch pipeline dispatch edges on live runs so cascades group

The activity panel groups runs into cascades by connected components of the
dispatch-edge graph, but edges came only from the one-shot history preload
(refetched on workspace/folder/days change). dispatch_event rows are written
server-side when a producer completes, so a run launched live had its producer
and freshly-dispatched children appear as live poll events with no connecting
edge — they rendered as separate ungrouped rows instead of one cascade.

Add an edges-only refetch and trigger it whenever the live poll's event id-set
changes, so live cascades converge to grouped like historic/scheduled ones.

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

* fix(frontend): address review nits on live dispatch-edge refetch

- Sequence same-scope edges-only refetches with a monotonic edgeSeq so a
  slower earlier response can't overwrite a newer one mid-cascade (the gen
  counter only guards scope changes).
- Condense the duplicated edge-refetch rationale: keep the canonical "why"
  in loadEdges, trim the page effect comment to its trigger/loop invariant.

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-06-19 16:43:23 +02:00
Ruben Fiszelandrubenfiszel b2ce475fc3 chore(main): release 1.733.0 (#9677)
* chore(main): release 1.733.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.733.0
2026-06-19 13:50:47 +00:00
Ruben FiszelandClaude Opus 4.8 5970510cf6 perf(backend): gate asset producer-change event on write-set changes (#9672)
* perf(backend): only emit asset producer-change event on write-set changes

Data Pipelines (#9193) made every script deploy emit a
`notify_asset_producer_change` event: `clear_static_asset_usage` inserted
into `notify_event` unconditionally on every clear, and the per-asset
insert path emitted nothing. So a plain script with no assets — the
overwhelming majority of deploys — wrote a `notify_event` row that made
every worker drop its `ASSET_PRODUCER_WRITES_CACHE` entry instance-wide,
needlessly thrashing the cache the feature added.

That cache only tracks script rows with write access (`usage_access_type
IN ('w','rw')`), so a deploy changes it only when the script gains or
loses a write producer. Gate the event on exactly that:

- `clear_static_asset_usage` / `clear_static_asset_usage_by_script_hash`
  emit only when the delete removed a 'w'/'rw' row (via `RETURNING`).
- `insert_static_asset_usage` emits only when it actually inserts a
  'w'/'rw' script row (no-op `ON CONFLICT`, read-only, and flow usage
  stay silent).

Plain, read-only, and flow deploys now emit nothing; producer-changing
deploys still invalidate, atomically and visible-only-on-commit as
before. Adds a test asserting the emit/no-emit matrix.

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

* perf(backend): dedup producer-change notify on write-asset redeploys

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

* fix(backend): derive replace write-set from persisted rows; document auth contract

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

* docs(backend): correct replace_static_asset_usage call-site comment

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-06-19 13:49:32 +00:00
6833a554ae fix: allow users to always discard their own drafts without write permission (#9659)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-06-19 13:34:38 +00:00
centdixandClaude Opus 4.8 4296a6ae1f feat(ai-chat): cap read_app_file + search_app grep tool to bound context in large raw apps (#9653)
* docs: add global AI chat context-optimization plan for raw apps

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

* test(ai-evals): add global raw-app debugging cases on a large fixture

Adds a ~20-file analytics_dashboard raw-app fixture (incl. a 5k-line data module
and a planted wrong-totals bug), two global cases (read-heavy debug + small-edit
baseline), app-seed support in the mock backend, directory-fixture loading, and a
decorateHelpers seam so read-dedupe is measurable. Records tokenUsage for before/
after comparison of the read-tool optimization.

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

* feat(ai-chat): cap and dedupe read_app_file to bound context in large apps

read_app_file now defaults to a head slice (1500 lines / 50k chars) with offset/
limit to page further, and skips resending a file whose earlier read is still in
context (per-conversation ledger keyed off the originating tool-call id, so it
self-heals after compaction). Bounds the file-content portion of global-chat
context when working in large raw apps.

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

* test(ai-evals): add read-heavy raw-app debug case (large data module)

global-test31 induces the model to inspect the 5k-line seedData module, exercising
the read_app_file cap/offset path. Baseline ~262k tokens vs ~200k with the cap+dedupe
change (-24%).

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

* docs: record A+B benchmark results and fixed-overhead finding

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

* fix(ai-chat): clearer read_app_file past-EOF message + unit tests for cap/dedupe

Addresses local-review nits: out-of-range offset now reports 'offset N is past the
end of the file' instead of a backwards 'lines 11-10' label; adds unit coverage for
the slicing (line cap, offset/limit window, char budget, past-EOF) and re-read dedupe
(hit + miss-when-not-retained).

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

* feat(ai-chat): char-level paging + per-range dedupe for read_app_file

Adds char_offset/char_limit so minified/long-line files can be paged within a line
window, keys the re-read ledger by range (so reading different ranges no longer
collides), and dedupes on the full-file hash (a cached range stub is invalidated
when any byte of the file changes, not just the returned range). Tests updated for
the char-slice behavior plus single-line capping, char paging, and out-of-window
change detection.

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

* test(ai-chat): add read_app_file context micro-benchmark + re-read eval case

Adds a deterministic micro-benchmark (no LLM) that drives read_app_file through a
realistic big-project read pattern (large file, re-read, minified bundle, paging)
and asserts the cap+dedupe cut returned context >50% vs the old whole-file behavior
— isolating the feature's effect from model nondeterminism and guarding against
silent weakening. Adds global-test32, a cross-file consistency investigation that
revisits overlapping files so re-read dedupe is exercised in a real run.

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

* test(ai-evals): clarify test32 measures the read cap, not dedupe

Verified: sonnet and haiku both read each file once per conversation and retain
it, so test32 never triggers read_app_file re-read dedupe. Dedupe is measured
deterministically by the micro-benchmark instead. Comment corrected to match.

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

* refactor(ai-chat): drop read_app_file re-read dedupe, ship the cap only

Benchmarking showed the per-conversation re-read dedupe never fires in practice:
across sonnet/opus/gpt-5.5/haiku, every model reads each file once per conversation
and keeps it in context (0 within-conversation re-reads). It was a correct but unused
guard, so this removes the ledger, full-file hash, retention predicate, the
AIChatManager wiring, and the eval decorateHelpers seam — keeping the read cap +
offset/limit/char paging (A), which is the lever that actually bounds context. The
micro-benchmark is now cap-only; test32 is kept as a multi-file read-load case.

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

* feat(ai-chat): add search_app grep tool for global raw-app chat (experimental)

Client-side grep over a raw app's frontend files and inline runnables (literal,
case-insensitive, optional file_glob/context_lines/max_matches, head-capped).
Completes the list -> search -> ranged-read triad. Includes the eval A/B gate
(WMILL_AI_EVAL_DISABLE_SEARCH_APP), unit tests + micro-benchmark, and a
find-all-usages eval case (global-test33).

Experimental: A/B benchmarking shows it is not an unconditional win — it helps
on find-all-usages but adds agentic iterations on navigable apps.

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

* test(ai-evals): accept search_app as a valid file-inspection tool in raw-app cases

Add requiredToolsAnyOf alternatives-group to ToolValidationSpec and switch
global-test29..32 to it so a model that locates files via search_app instead
of read_app_file no longer false-fails the tool assertion.

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

* docs: remove stale ai-chat context-optimization planning doc

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

* refactor(ai-chat): drop read_app_file char paging for a hard char cap

The char_offset/char_limit params guarded minified files (a single line over
the char budget) but were effectively unused in benchmarks. Remove them and the
in-window char paging; keep the hard 50k-char budget and, when a read hits it,
tell the model to narrow the line limit (or treat the file as unreadable if a
single line exceeds the budget). Proper long-line handling is left as a TODO.

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

* refactor(ai-chat): bake search_app context to 1 line, clarify query is literal

Drop the context_lines param (models varied it to little effect) for a fixed
SEARCH_APP_CONTEXT_LINES=1, and cap on matching lines instead of pushed rows so
max_matches stays accurate with context always on. Sharpen the query description
to state it is a literal (non-regex) substring and to suggest the call form
(e.g. formatCurrency() to hit call sites and skip formatCurrencyPrecise.

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

* refactor(ai-chat): widen baked search_app context to 2 lines

Models that set the old context_lines param leaned to 2; match the lean.

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

* fix(ai-chat): count every file with a match in search_app header

Move fileHadMatch ahead of the render cap so files whose matches fall past max_matches are still counted (with a regression test). Also swap the raw NUL globstar sentinel for a printable escape (the NUL bytes made core.ts read as binary to grep) and reword two comments to describe current constraints instead of drafting history.

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

* fix(ai-chat): drop redundant input echoes from app tool results

read_app_file and search_app no longer prefix results with the tool name or echo back the caller's own inputs (file path, query, file_glob) — the model already has them from the call args, and the unbounded query echo could push the search result past its output budget. Keeps the useful signals (line range, match/file counts, truncation) and the actionable advice. Also reword max_matches to 'matching lines' since it caps lines (each expands to context rows). Unit tests updated to the new format.

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-06-19 13:33:54 +00:00
Ruben FiszelandClaude Opus 4.8 924f9c7e8d fix(backend): strip NUL bytes from draft values on write (#9673)
draft.value is a json column (not jsonb), so a client could store a U+0000
escape in it. Any later text extraction (`->>` / `to_jsonb`) on such a value
raises 22P05 "unsupported Unicode escape sequence" — one poisoned draft 500'd
the whole GET /drafts/list, silently hiding the home-page "This workspace has N
drafts" banner (and breaking the global drafts page).

Prevent it at the source: sanitize the value in update_draft (the only path that
writes client-supplied draft content) so a NUL never reaches the column.
strip_json_nul does a single backslash-parity-aware byte pass that removes real
NUL escapes (values and keys alike) while leaving a legitimate escaped backslash
intact — O(n) with no serde_json::Value tree to allocate, important because the
slow path is also hit by any value legitimately containing the text after a
backslash (e.g. script source). The clean path is a single substring check.

A SQL migration scrubs rows written before this, gated to genuinely-poisoned
rows (a real NUL makes value::jsonb raise, distinguishing it from a legitimately
escaped backslash). With the data clean, no read-side query needs to change.

Tests: unit tests for the strip helper (escaped-backslash no-op, real+literal
collision, odd-backslash-run parity, nested keys/values) and an integration test
that POSTs a NUL-bearing draft and asserts it is stored and listed NUL-free
(fails without the strip).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 13:33:36 +00:00
PyraandClaude Opus 4.7 ab3bc97cd9 feat(python, windows): enable S3 to cache wheels (#5199)
* add .minio-data to .gitignore

* feat(python): make S3 cache arch specific

Current schema:

S3-Bucket
├── python_311
│   ├── wheel==1.0
│   └── wheel2==1.0
└── python_312
    ├── wheel==1.0
    └── wheel2==1.0

New schema:

S3-Bucket
├── linux_aarch64
│   └── ...
└── linux_x86_64
    ├── python_311
    │   ├── wheel==1.0
    │   └── wheel2==1.0
    └── python_312
        ├── wheel==1.0
        └── wheel2==1.0

* remove .minio-data from .gitignore

* remove unneeded tracing::error

* feat(python, windows): enable S3 to cache wheels

* fix(python, windows): drop residual unix cfg gates on S3 cache items

Post-merge, PIPTAR_UPLOAD_CHANNEL and its call sites were already
cross-platform, but the types/functions they reference (PiptarUploadTask,
handle_piptar_uploads, pull_from_tar, OBJECT_STORE_SETTINGS) remained
unix-gated, breaking the Windows build.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-19 13:11:35 +00:00
Ruben Fiszel 496e770264 Revert "fix(backend): clean up unique_ext_jwt_token on workspace deletion (#9…" (#9678)
This reverts commit 9add719d93.
2026-06-19 13:01:15 +00:00
Ruben FiszelandClaude Opus 4.8 cafb473494 fix(python): split PIP_TRUSTED_HOST by whitespace to support multiple hosts (#9675)
* fix(python): split PIP_TRUSTED_HOST by whitespace for multiple hosts

When PIP_TRUSTED_HOST contains multiple space-separated hostnames, the
whole string was passed as a single --trusted-host argument
(--trusted-host "host1 host2") rather than one flag per host. This
matches pip's documented PIP_TRUSTED_HOST convention by emitting a
separate --trusted-host for each host, mirroring the existing
pip_extra_index_url handling.

Fixes WIN-2077

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

* fix(python): use shell word-splitting for nsjail trusted-host args

Address review feedback: the previous tr/sed pipeline only split on
single spaces, diverging from the Rust split_whitespace() paths. Repeated
or leading/trailing spaces produced empty --trusted-host flags and
tab-separated hosts were not split. Use an unquoted for-loop over
$TRUSTED_HOST so the shell's own IFS word-splitting handles arbitrary
whitespace and skips empty fields, matching the non-nsjail paths.

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-06-19 12:59:08 +00:00
Ruben FiszelandClaude Opus 4.8 9add719d93 fix(backend): clean up unique_ext_jwt_token on workspace deletion (#9676)
The workspace_id column on unique_ext_jwt_token (migration 20260409145556)
has no FK constraint on the workspace table, and delete_workspace did not
remove its rows. Deleted workspaces left orphaned external JWT token records
that kept appearing in the superadmin External JWTs listing.

Add a DELETE FROM unique_ext_jwt_token WHERE workspace_id = $1 alongside the
other per-table cleanup statements in delete_workspace.

Fixes WIN-2078

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 12:48:48 +00:00
Ruben Fiszelandrubenfiszel b24616dc44 chore(main): release 1.732.0 (#9670)
* chore(main): release 1.732.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.732.0
2026-06-19 11:34:59 +00:00
Ruben FiszelandClaude Opus 4.8 33617367d0 fix(backend): grant script_trigger access to windmill roles (#9674)
The script_trigger table (migration 20260423050000_script_trigger)
relied on ALTER DEFAULT PRIVILEGES to grant access to windmill_user and
windmill_admin. Those default privileges only apply to objects created
by the role that set them (migration 20250205131523), so deployments
whose migration runner is a different role leave script_trigger
ungranted.

Direct application writes run as the invoking role and fail with
"permission denied for table script_trigger" — notably
clear_script_triggers and insert_script_trigger in
windmill-common/src/assets.rs during every script save.

Add an explicit GRANT on script_trigger and its sequence, matching the
notify_event fix (#9665) and the asset table precedent.

Fixes WIN-2076

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:30:21 +00:00
Ruben FiszelandClaude Opus 4.8 3371265382 fix(frontend): ignore hash/assets in script diffs and drafts (WIN-2071) (#9664)
* fix(frontend): ignore hash/assets in script diffs and drafts

The script editor's draft value is seeded from the full `getScriptByPath`
DB row (since #9351), so it carries `hash` (the deployed version's
identity) and `assets` (re-derived from the script content by the
editor). Neither is editable draft content, yet both were persisted into
the draft row and surfaced as spurious changes in the workspace/fork
compare diff view.

- Add `hash`, `assets`, and the read-time-computed `inherited_labels` to
  `CLEANED_VALUE_KEYS` so the shared diff/unsaved-change strip ignores
  them everywhere (DiffDrawer + WorkspaceItemDiffViewer).
- Strip `hash` and `assets` from script drafts at the single persistence
  chokepoint (`UserDraftDbSyncer.save`) so every path — reactive
  autosave, Ctrl/Cmd+S flush, the pagehide keepalive — sends the same
  trimmed payload. On reload the deployed row re-supplies them.

Fixes WIN-2071

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

* docs(frontend): clarify draft sanitizer vs diff-strip relationship

The two field lists are intentionally not equal — only the hash/assets
overlap must stay consistent. Reword the comment so a future maintainer
doesn't add keys to one expecting parity with the other.

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-06-19 11:21:24 +00:00
Ruben FiszelandClaude Opus 4.8 017c3d3343 feat(ansible): add AI chat and editor bar buttons for ansible (#9671)
Ansible scripts previously lacked the AI assistant and the contextual
variable helper that other scripting languages expose in the script editor.

- Add 'ansible' to SUPPORTED_CHAT_SCRIPT_LANGUAGES so the AI chat button
  shows in the editor toolbar and the AI chat opens in SCRIPT mode without
  the "language not supported" warning.
- Add an Ansible system prompt (system_prompts/languages/ansible.md) plus a
  LANGUAGE_METADATA entry, and regenerate the auto-generated prompts/skills
  so the AI has tailored Ansible context.
- Show the contextual variable picker for ansible and insert references as
  `{{ lookup('env', 'NAME') }}`, matching how Windmill exposes reserved
  variables as environment variables to the ansible-playbook process.

Fixes WIN-2072

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:12:33 +00:00
centdixandClaude Opus 4.8 0cc2257596 fix(ai): emit token usage in gemini proxy streaming translation (#9669)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:57:52 +00:00
Ruben Fiszelandrubenfiszel 887a3076b2 chore(main): release 1.731.0 (#9668)
* chore(main): release 1.731.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.731.0
2026-06-19 10:16:35 +00:00
centdixandClaude Opus 4.8 c30bdecea7 fix(mcp): repair invalid type keywords in tool JSON schemas (#9667)
Drop empty/unknown `type` values (Windmill emits `type: ""` for untyped fields) and infer `type: array` for nodes carrying `items`, so generated MCP tool schemas validate against JSON Schema draft 2020-12. Anthropic's tool registration rejected the whole tool list otherwise.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:04:42 +00:00
Ruben FiszelandClaude Opus 4.8 7e4df02bd6 fix: trigger flow error handler on unrecoverable (OOM/zombie) step failures (#9662)
* fix: trigger flow error handler on unrecoverable (OOM/zombie) step failures

When a worker is OOM-killed mid-step, the zombie job handler fails the step
via handle_job_error with unrecoverable=true. update_flow_status_after_job_completion
had `false if unrecoverable => false`, which silently completed the flow with the
error and skipped the flow's failure module (error handler). It would also have
pinned the failure module to the dead worker via same_worker.

Unrecoverable failures now route to the failure module instead of being retried or
silently dropped, and the error-handler step is pushed as a regular queued job that
any live worker can pick up.

Fixes WIN-2070

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

* fix: skip retry on unrecoverable flow failures, add retry-skip regression test

Address review: the failure-module-on-unrecoverable change must also bypass the per-step retry policy in push_next_flow_job, otherwise an OOM/zombie-killed step with a retry config would be retried instead of routing to the error handler. Gate the retry evaluation on !unrecoverable and add a regression test.

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

* chore: add sqlx offline cache for new flow-step zombie test query

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

* fix: route unrecoverable continue_on_error step failures to the error handler

Addresses Codex/Pi review (P1): with continue_on_error on the failed step, the
step counter was advanced before the unrecoverable decision branch, so
push_next_flow_job pushed the next normal step instead of the failure module —
hiding the worker death and letting the flow complete successfully.

- Do not advance the step counter (inc) for an unrecoverable continue_on_error failure.
- Let the Failure arm in push_next_flow_job route to the failure step even on a
  continue_on_error module when unrecoverable.
- Add a regression test (a[continue_on_error] -> b + failure_module): asserts the
  failure module runs and step b does not.

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-06-19 09:57:05 +00:00
hugocasaandClaude Opus 4.8 a425431e90 feat(backend): auto-reconnect postgres trigger listener with backoff (WIN-2073) (#9666)
* feat(backend): auto-reconnect postgres trigger listener with backoff

The Postgres trigger listener permanently disabled itself on any
connection error (stream close, receive error), so a transient network
interruption (e.g. a cloud provider maintenance window) permanently
killed the trigger.

Restructure the listener to match the Kafka trigger: the replication
connection is now established inside an outer reconnect loop in
`consume`. On a dropped stream or receive error it backs off 30s and
reconnects instead of disabling, reporting a critical error every 10
failed attempts and a recovery once it reconnects. Disabling is kept
only for unrecoverable misconfiguration (missing publication or
replication slot, unparsable replication message).

Fixes WIN-2073

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

* fix(backend): count postgres reconnects on stream drop and alert from first

Adopt the SQS listener's reconnection accounting in the Postgres trigger
listener. A stream close or receive error now counts toward the retry
counter and raises a throttled critical error (on the first occurrence,
then every 10 attempts), and the retry counter is reset / recovery is
reported only once the reconnected stream actually delivers a message.

Previously the inner-loop disconnect branches reset `tries` to 0 on every
successful (re)connect and never alerted, so a stream that connected and
then immediately dropped could ping-pong every 30s indefinitely without
ever raising an alert. Resetting on real progress rather than on a bare
connect closes that blind spot and matches the SQS pattern.

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-06-19 09:56:36 +00:00
Ruben FiszelandClaude Opus 4.8 a682d02311 fix(backend): grant notify_event access to windmill roles (#9665)
The notify_event table (migration 20260203172950_polling_based_events)
relied on ALTER DEFAULT PRIVILEGES to grant access to windmill_user and
windmill_admin. Those default privileges only apply to objects created
by the role that set them (migration 20250205131523), so deployments
whose migration runner is a different role leave notify_event ungranted.

Trigger inserts were already worked around with SECURITY DEFINER
(migration 20260206060555), but direct application inserts that run as
the invoking role still failed with "permission denied for table
notify_event" — notably clear_static_asset_usage in assets.rs during
script save, and restart_worker_group in settings.

Add an explicit GRANT on notify_event and its sequence, matching the
existing explicit-grant pattern used for the asset table.

Fixes WIN-2074

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 09:55:18 +00:00
Ruben Fiszelandrubenfiszel 8c78fa0a55 chore(main): release 1.730.0 (#9654)
* chore(main): release 1.730.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.730.0
2026-06-18 23:49:35 +02:00
Diego Imbert e98dcd3579 fix: surface postgres error detail when datatable migrations fail to run 2026-06-18 23:34:55 +02:00