Commit Graph

14360 Commits

Author SHA1 Message Date
AlexRV12 afd8d723ef docs: correct the superadmin_secret arm and the global-route exceptions 2026-08-13 20:27:30 +02:00
AlexRV12 4a3d64b38a docs: scope the superadmin row and correct the handler tallies 2026-08-13 20:05:23 +02:00
AlexRV12 ffe49208f5 docs: cover the EE oauth denials and the global-route operator flag 2026-08-13 19:50:27 +02:00
AlexRV12 8ee606c4f5 docs: audit what an operator's token can reach via the API 2026-08-13 19:32:56 +02:00
Ruben Fiszel 2ac3e64fe2 chore(main): release 1.787.0 (#10657)
* chore(main): release 1.787.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.787.0
2026-08-12 13:27:21 +02:00
Guilhem eb238e3f0b fix: stop the AI chat destroying secret variables on edit (#10616)
* fix: stop the AI chat destroying secret variables on edit

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

* fix: clear stale staged secret values and state the draft-staging rule

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

* docs: condense the pending-secret invariant to its field

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

* fix: refuse empty and oauth-managed secret values, keep drawer-staged ones in the draft

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

* fix: resolve a variable deploy's secret from one draft snapshot

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

* refactor: make the variable draft the single source of a staged secret

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

* docs: drop stale in-memory secret invariants from comments and the eval

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

* fix: stop null account/expires_at leaking into variable drafts and diffs

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

* fix: report when a variable deploy leaves the secret value unchanged

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

* docs: scope the variable-value readability claims to the chat

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

* docs: correct the secret-draft invariant in the diff masking comment

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

* docs: record why a non-secret value is resent on a partial update

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

* fix: stop "Load secret value" discarding a staged secret

The audit-logged load writes the deployed secret into the draft row the
variable drawer shares with the AI chat, so offering it while that row
already stages a value silently replaces it — and the deploy that follows
carries the old value with no sign the staged one was lost.

The gate that hid the action already existed but keyed on
`isEncryptedDraftValue`, which only holds once a draft has round-tripped
through the server. A value staged in the same tab is still plaintext, so
it slipped through. Key on "anything staged" instead; clearing stays
explicit via Reset.

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

* fix: extend the variable draft's empty-value sentinel past secrets

Two gaps in the chat's variable write path, both from treating "the draft
cannot carry this value" as meaning only "the value is secret".

`variableToDraftState` drops the value of an OAuth-managed variable so a
refreshed live token is never pinned into a draft, leaving '' behind. The
deploy body resent that '' verbatim for a non-secret one, wiping the token
the refresh flow owns. The sentinel now covers every value the draft is not
allowed to hold, which also removes the divergence from
`VariableEditor.save` and the shared deployer.

Making a variable secret when it holds no value produced a secret draft
staging '', a deploy body with no `value`, and the backend's "cannot change
is_secret without updating value too" — the sibling create path already
answers that case with guidance, so answer it here too.

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

* fix: gate the Secret toggle's secret load on the staged value too

The toggle calls `onLoadSecret` on every change so an is_secret flip has a
value to send, but that load overwrites the shared draft row — the same
discard the button gate just closed, reached by a different control.

It now loads only when the row stages nothing, which is exactly when the
flip needs a value fetched. With a value already staged there is one to
send, and it is the one the user or the chat put there.

Blocking the load costs the side effect that used to mask a worse bug: for
a deployed variable, the load replaced an `$encrypted:` marker with real
plaintext before save. Without it, un-securing a marker would store the
marker string as the value, since the deploy endpoints only decrypt it while
is_secret stays true. So the toggle is disabled outright while a marker is
staged — Reset first. That closes the marker case for draft-only variables
as well, where no load could ever have masked it.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 13:13:41 +02:00
hugocasa f4a935bd1c fix(schedule): hoist non-RLS reads out of the create_schedule tx (#10658)
create_schedule opened the RLS transaction (user_db.begin) first, then ran
reads that deliberately use the non-RLS `db` pool — fork-ness and
permissioned_as/email resolution — while holding it. Acquiring a second pooled
connection while the tx holds one self-deadlocks on a single-connection pool
(embedded Postgres, PgBouncer statement mode, any max_connections=1 setup): the
read blocks on the sqlx acquire timeout, then errors.

Move those reads (and the ScheduleType::from_str validation) above
user_db.begin(). They don't depend on the tx and bypass RLS by design, so the
result is semantically identical; the RLS transaction is simply opened later and
held for less time. Same class of fix as #9970 (migration bootstrap on the
migrator's held connection).

Note: sibling paths keep the same latent pattern on branches this change does
not touch (push_scheduled_job reads the pool under the tx for flow schedules;
edit_schedule/set_enabled for cross-user permissioned_as) — a possible follow-up.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-12 13:11:18 +02:00
Ruben Fiszel edcf80efc4 test: fix repro_diffname CLI flake by draining the app dependency job (#10659)
* test: wait for the app dependency job before pulling in repro_diffname

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

* test: reuse waitForDeploymentJobs and assert pulled lock files

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

* test: condense the dependency-job wait comment

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 13:10:26 +02:00
Guilhem ce58b8495c feat: expose every runs filter on the open_page chat tool (#10612)
* feat: expose every runs filter on the open_page chat tool

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

* fix: reject runs filters the page would silently ignore

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

* fix: normalize runs list filters and refuse combinations the page drops

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

* fix: validate the full folder-name contract and pin evals to one call

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

* fix: refuse queue statuses the concurrency view cannot filter on

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 09:34:37 +00:00
Ruben Fiszel 20953a0c67 chore(main): release 1.786.1 (#10652)
* chore(main): release 1.786.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.786.1
2026-08-12 09:40:03 +02:00
Ruben Fiszel 2808150ae4 fix: avoid content shift on home page load and in the script editor logs pane (#10654)
* fix: avoid content shift on home page load and in the script editor logs pane

The tutorial banner rendered by default and was removed once an API round-trip
resolved that it should not show, jumping everything below it up by 58px on
every home page load. It now caches the last resolved state in localStorage and
paints that first, so the first frame already matches what the sync concludes; a
device with nothing cached stays hidden until the sync answers.

The logs header spinner was an unsized lucide icon (24px) where the settled
state renders a 12px Timer, so the row grew 7px while a job was queued and
shrank back when it started, shoving the log body down and up again.

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

* fix: keep the tutorial banner hidden when dismissed mid-sync

The banner is interactive while the initial tutorial-progress request is still
in flight, so a dismiss or a skip can land before the sync resolves. The
continuation then overwrote the user's choice and brought the banner back.

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

* fix: pin the result placeholder row height across the spinner swap

Sizing the spinner to the font size still left it 6px short of the text-sm line
box it replaces, so the row contracted instead of growing. Pin the height on the
container so it holds in both states and tracks the root font size.

Also assign state before persisting it, and collapse the duplicated rationale
above the banner cache.

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

* fix: stop the test panel splitpanes resting one header too tall

The panes carried `!max-h-[calc(100%-{...}px)]`, but the arbitrary value is
built by string interpolation so Tailwind never emitted a rule for it: the
class was inert and the computed max-height was `none`. The panes then took
their 100% height, ignoring the header row above them, and overflowed the
column by exactly the header. Flex only applied the shrink transiently, so a
reflow during a run snapped the whole logs & result region up ~12px and back.

min-h-0 lets flex size the panes to the space that is actually left, which is
what the clamp was reaching for and is correct for the debug and bottom layouts
too, without their hardcoded 83/43/0 pixel guesses.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 09:33:22 +02:00
Ruben Fiszel 201d7c4eb2 fix: bound postgres result collection so an oversized result cannot OOM the worker (#10644)
* fix: bound postgres result collection so it cannot OOM the worker

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

* fix: render the sql result limit exactly so the error can be set verbatim

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

* docs: point the fraction rationale at the renderer that still emits them

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

* perf: stop re-parsing every collected row to rebuild it as a RawValue

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

* style: drop a dangling doc line and an unrelated rustfmt reflow

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 09:11:56 +02:00
Ruben Fiszel 5f819cd344 fix(frontend): skip reserved ids when auto-assigning flow module ids (#10651)
* fix(frontend): skip reserved ids when auto-assigning flow module ids

* test: state the reserved-id invariant only beside the implementation
2026-08-12 08:41:30 +02:00
Ruben Fiszel 45a6e4932a chore(main): release 1.786.0 (#10649)
* chore(main): release 1.786.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.786.0
2026-08-12 02:22:18 +02:00
Ruben Fiszel 00822a7435 fix: bound duckdb result collection so an oversized result cannot OOM the worker (#10641)
* fix: bound duckdb result collection so an oversized result cannot OOM the worker

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

* fix: keep the duckdb cap a worker-survival limit rather than a cloud product one

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

* fix: refuse an oversized blob before it expands to one json value per byte

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

* fix: share one expansion budget across a row's values, nested ones included

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

* fix: bound the row's own serialization so escaping cannot outgrow the budget

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

* fix: charge a json column before parsing it into a value tree

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

* docs: trim the json budget rationale and name what the budget does not cover

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

* fix: gate the sql result size limit on the duckdb feature

Its only consumer is the duckdb executor, so the minimal build compiled it
as dead code and failed under -D warnings.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 02:17:07 +02:00
AlexRV12 66c0d1251d fix(copilot): read an artifact inside the transaction that revises it (#10647)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 02:13:29 +02:00
Ruben Fiszel a09df8a130 decycle the recursive TriggerFilter schema in the python client build (#10648) 2026-08-12 01:58:35 +02:00
Ruben Fiszel a6157ba104 feat: bound how much disk a single duckdb job can spill (#10645)
* feat: bound how much disk a single duckdb job can spill

* fix: name the env var and correct duckdb's unreachable spill-cap advice

* fix: do not blame an unset env var for duckdb's default spill cap

* style: keep the duckdb spill-cap invariant comments within four lines

* docs: size the duckdb spill cap against the disk cloud pods actually use
2026-08-12 01:55:45 +02:00
Ruben Fiszel a65a184a80 chore(main): release 1.785.0 (#10626)
* chore(main): release 1.785.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.785.0
2026-08-11 18:26:31 +00:00
hugocasa f23a5d78b2 fix: tell MCP clients which tool parameters may be omitted (#10642)
* fix: tell MCP clients which tool parameters may be omitted

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

* refactor: make the mcp property-key rename testable and shorten the hint

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

* fix: keep the mcp omission hint from calling flow inputs optional

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

* fix: skip the mcp omission hint on a parameterless tool

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 18:20:47 +00:00
Guilhem 442bbcc1fc align variable value font size with the rest of the table (#10643) 2026-08-11 18:19:57 +00:00
Ruben Fiszel 3394546657 feat(npm-proxy): keep package files on disk and in the object store (#10638)
* docs: design for where the npm proxy keeps cached registry content

* feat(npm-proxy): keep package files on disk and in the object store

* fix(npm-proxy): degrade when the cache is unwritable, stream and bound it

* fix(npm-proxy): keep the happy path off the heap and isolate pull scratch

* fix(npm-proxy): bound the upload, verify pulled trees, keep oversized manifests

* fix(npm-proxy): protect live scratch, bound uploads by parts, refuse traversals

* fix: let the blocking unpack own the scratch it writes into

* fix: replace a cache directory that is not a package instead of deferring to it

* fix: evict by moving a package off the live path, not by deleting it in place

* fix: leave a package the sweep cannot move rather than deleting it in place

* fix: take one registry snapshot through a cache miss

* fix: stamp a pulled package as used so the sweep does not evict it first
2026-08-11 16:40:53 +00:00
Ruben Fiszel 9c055bf40d lock the duckdb temp directory so no script can move it (#10587) 2026-08-11 13:54:16 +00:00
Ruben Fiszel 18ae0bdfbf feat: keep duckdb spilling behind the local-filesystem fence (#10607)
* fix: explain duckdb failures caused by job isolation

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

* fix: apply the isolation policy to the schema-sync pre-pass

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

* chore: bump ee ref for the out-of-memory hint wording

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

* fix: bump the bundled DuckDB engine to 1.5.5

The 1.5.5 duckdb crate no longer hands back a 96-bit `rust_decimal`, so a
DECIMAL wider than that renders instead of panicking inside an `extern "C"`
frame — which, being unable to unwind, aborted the whole worker process and
left the job running as a zombie. `SELECT
'1234567890123456789012345678.9012345678'::DECIMAL(38, 10)` was enough.

Adapting to the crate's API: `Value` is now `#[non_exhaustive]` and gained
`UHugeInt` and `Geometry`, and `rust_decimal` became an optional feature that
the `decimal`/`numeric` argument path still needs.

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

* fix: address review findings on the duckdb bump

Run the FFI crate's own tests in CI: it is excluded from the workspace, so the
`cargo test --all` in backend-test never reached them and the new guard against
the worker-aborting DECIMAL would not have run. build_dev.sh now honors a
caller-pinned CARGO_TARGET_DIR so the test build reuses that compile instead of
building the bundled engine a second time.

Also pin UHUGEINT rendering, and correct the rust_decimal rationale —
`Decimal::new` is public without the feature, so the reason is that the feature
reproduces the exact binding the crate used to derive, not that nothing else can.

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

* fix: address review nits on the duckdb bump

Name the unsupported DuckDB type rather than dumping the value, which may be
arbitrarily large or hold data that does not belong in an error message, and
say which column it came from.

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

* chore: pin the ee ref to the narrowed duckdb extension allowlist

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

* feat: keep duckdb spilling behind the local-filesystem fence

* chore: repin the duckdb fork after adding the reset-test exclusion

* docs: stop claiming the duckdb patch has been filed upstream

* docs: point the backend duckdb bullet at the fork's rationale

* fix: place lock_temp_directory so no existing struct member moves

* fix: skip the extension-load guard when the repo is unreachable

* refactor: trim the fork comments and fail the extension guard in CI

* chore: repin the duckdb fork onto upstream duckdb-rs main

* fix: keep the engine patch applying on a CRLF checkout

* docs: link the upstream issue tracking the underlying problem

* chore: repin the duckdb fork onto the patch as filed upstream

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

* chore: update ee-repo-ref to 88568d11162ffa11723e7955e613224bab4f0568

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

Previous ee-repo-ref: 22f075c1164d9dd5a3ba92d682905aabd071d273

New ee-repo-ref: 88568d11162ffa11723e7955e613224bab4f0568

Automated by sync-ee-ref workflow.

* chore: repin the duckdb fork onto the cmake/fmt build fix

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

* test: pin the immutability half of lock_temp_directory

The spill test proves the exemption works; nothing proved the lock that makes
it sound. A rebase could drop the refusals and leave every other tripwire green.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-08-11 13:38:09 +00:00
hugocasa 1816b11474 fix(cli): delete file resources at the right path on sync push (#10639) 2026-08-11 13:17:31 +00:00
hugocasa 85134578b4 fix(cli): sync push crashed on edited fileset children; reject non-canonical fileset dirs (#10572)
* fix(cli): route fileset children to their parent resource on sync push

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

* fix(cli): scope fileset pointer validation to sync pushes

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

* fix(cli): error on script push of file/fileset resource content files

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

* fix(cli): enforce server-canonical fileset pointers and fail fast before apply

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

* fix(cli): resolve ws-specific fileset metadata and validate pointers before dry-run

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

* fix(cli): prefer workspace-specific fileset metadata over base file

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

* test(cli): make fileset metadata lookup assertions platform-separator safe

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

* fix(cli): stop dropping fileset children whose names look like typed metadata

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

* fix(cli): exempt fileset children from the current-workspace classifier too

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 13:16:45 +00:00
Guilhem 583649bb23 feat(frontend): show prod and dev as sibling choices in the workspace picker (#10590)
* fix(frontend): declutter the workspace picker and workspace creation

* fix(frontend): fail open when the auto-invite domain check errors

* fix(frontend): fail closed when the auto-invite domain check errors

* feat(frontend): present prod and dev as sibling choices on the workspace card

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 13:01:24 +00:00
Ruben Fiszel 6967804f5a chore(npm-proxy): count file paths and retained entries separately (#10637) 2026-08-11 12:38:39 +00:00
Ruben Fiszel a8816b896d feat(ata): prefer the npm proxy when the instance configures a registry (#10632)
* feat(ata): prefer the npm proxy when the instance configures a registry

* fix(npm-proxy): cap tarball extraction and stop pinning a failed config probe

* fix(npm-proxy): keep large packages cacheable by using a single shard

* fix(npm-proxy): cache the archive so a large package is served, not refused

* fix(npm-proxy): read archives off the runtime, keeping only what types need

* fix(npm-proxy): charge a retained entry for what it allocates, not its bytes

* fix(npm-proxy): size retention for real packages and read the manifest back

* fix(npm-proxy): charge path bytes and pin the manifest read-back

* fix(npm-proxy): stop retaining past the budget instead of refusing the package
2026-08-11 12:31:04 +00:00
hugocasa a02a97ce3b fix(parser-py): keep first param when def main( line has trailing comment (#10586)
* fix(parser-py): keep first param when def main( line has trailing comment

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

* chore: bump windmill-parser-wasm-py to 1.782.0

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 12:15:21 +00:00
Ruben Fiszel e54b6a914c fix(ata): fall back to the npm proxy when the CDN request fails outright (#10630)
* fix(ata): fall back to the npm proxy when the CDN request fails outright

* fix(ata): surface proxy failures and guard the body read too

* docs(ata): state the proxy catch's constraint, not its history

* fix(ata): log a failed proxy d.ts fetch, which callers discard
2026-08-11 11:26:52 +00:00
hugocasa 46eca13282 fix: pin MCP OAuth token requests to the validated address (#10593)
* fix: carry the validated token endpoint with MCP OAuth credentials

get_or_refresh_mcp_client already resolved and checked the token endpoint on
both its cached and freshly-registered paths, then dropped the result. Keeping
it on McpClientCredentials lets the callers that post the client_secret there
connect to the address that was checked, and removes a second lookup they were
each doing on their own.

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

* refactor: hand out the token URL with the client pinned to it

Makes the pin unrepresentable-if-wrong rather than documented: the validated
target is private and reachable only through token_request, which returns the
URL together with the client pinned to the address it was checked against, so
a caller cannot pin one host and post to another.

Adds the test that was missing under the whole guard: that the pinned client
really does connect to the pinned address instead of resolving the host. The
accept loop is bounded, so a pin that stops working fails in seconds.

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

* fix: keep the token endpoint private behind token_request

Leaving the URL public still allowed posting the client_secret to it on an
unpinned client, so the invariant was only documented. Both the URL and its
validated target are now private and reachable together, and the pinning test
resets the accepted socket to blocking so it does not read empty on macOS.

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

* test: drop the non-blocking reset from the pinning test

Linux hands back a blocking socket from accept regardless of the listener's
flag, and no runner here builds this crate for a platform that does otherwise.

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

* chore: update ee-repo-ref to f8d523195e40fd1d740595dcab6ce5cdc1bdbf09

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

Previous ee-repo-ref: 729df45314c6f2168b44eddb6edea401b0495d6d

New ee-repo-ref: f8d523195e40fd1d740595dcab6ce5cdc1bdbf09

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-08-11 12:41:28 +02:00
Ruben Fiszel ceacc17014 fix(raw-apps): respect the instance .npmrc in the raw app editor (#10629)
* feat(raw-apps): route in-browser npm installs through the npm proxy

* fix(npm-proxy): follow npm range semantics and cache packuments

* fix(npm-proxy): bound the packument cache by bytes and stream tarballs

* fix(npm-proxy): keep a v-prefixed pin exact and read the tarball once

* chore(raw-apps): bump the ui_builder pin to the npm-proxy installer
2026-08-11 12:30:40 +02:00
Ruben Fiszel ec99108cf6 feat(triggers): nested filter groups and dotted paths (#10625)
* feat(triggers): nested any_of / all_of filter groups

A trigger filter entry can now be a group — `{"any_of": [...]}` or
`{"all_of": [...]}` — nesting further entries, so criteria like
`A AND B AND (C OR D)` are expressible. Existing flat `{key, value}` lists keep
their meaning, combined by the trigger's `filter_logic` as before.

Filters are compiled once per connection: the set of top-level keys the whole
tree references is collected up front, so a message is parsed in a single
streaming pass that captures only those keys, instead of one full pass per leaf
filter as before. Filters that fail to parse are now logged rather than dropped
silently, since a nested group is easier to mistype than a flat entry.

The editor gains "Add group", rendering groups recursively with their own
AND/OR selector; Kafka and WebSocket triggers share it.

Fixes WIN-2345

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

* fix(triggers): drop empty filter groups instead of evaluating them

A group with no criterion cannot evaluate to a constant: true makes an `or`
filter list accept every message, false mutes an `and` list. Two clicks in the
editor ("Add group", save) produced one. Drop it when compiling so its siblings
stay in force, and reject at save time the filters the listener would otherwise
drop silently.

Also restore the item shape of `$ref`-typed arrays in the generated agent
schemas: the extractor only resolved refs at the property level, so moving
`filters.items` to a shared schema flattened it to a bare object. Resolving them
inside `items` too also recovers the shapes `initial_messages` and the MQTT
`topics` had already lost.

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

* fix(triggers): name the offending entry when a nested filter is invalid

Serde's untagged error only reports that the outermost entry matched no
variant, whatever depth is actually wrong, which defeats the point of
validating a group at save time. Walk the tree instead and report the path.

Normalize the WebSocket editor's filters to [] on load, as the Kafka editor
does, so the list component can rely on an array.

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

* fix(triggers): key filter rows by node so deletion keeps values aligned

The value editor seeds itself from `code` once, so an index-keyed row reused
for a different filter kept showing the deleted row's value.

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

* chore: bump ee-repo-ref after merging main

The merge pulled OSS code that needs EE symbols newer than the companion
branch's base, so the companion was merged with EE main too.

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

* perf(triggers): keep filter short-circuiting from materializing unread fields

The single-pass scan deserialized every referenced key before the boolean tree
ran, so an AND whose first leaf rejects the message still allocated the large
objects the later leaves name — the shape this feature exists for. Borrow the
wanted keys as raw slices during the scan and parse a field only when
evaluation actually reaches it.

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

* feat(triggers): none_of filter group

Negation of a nested group, so a trigger can exclude what it must not react to
without inverting every other criterion. A key the message does not carry
satisfies it: there is nothing there to match.

Only groups can negate — the root's operator is the trigger's filter_logic
column, which has no value for it.

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

* feat(triggers): address a nested field with a dotted path

`{path: "a.b.c", value: v}` alongside the existing `{key, value}`, so the common
case reads the way people write it instead of nesting the shape into the value.
A separate field rather than dots in `key`, which already means the top-level
field spelled that way — overloading it would resettle what existing triggers
over flattened payloads match.

Paths address objects only for now: a path through an array does not match
rather than guessing an element, and array containment stays on the value side.

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

* docs(triggers): mention none_of in the filter_logic description

Plus a test for the empty-path-segment rejection, which had none.

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

* chore: update ee-repo-ref to 78859aab0c6e78283ec8d2b37e8c410963afdc83

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

Previous ee-repo-ref: 0e42ba72ccc38a6b0a380f58afe0db36d284f4c9

New ee-repo-ref: 78859aab0c6e78283ec8d2b37e8c410963afdc83

Automated by sync-ee-ref workflow.

* fix(triggers): reject a criterion naming both key and path

The untagged enum takes such an entry as a `key` criterion and drops the
`path`, which is the silent-ignore the save-time validation exists to prevent.

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

* refactor(triggers): drop the label next to the key/path toggle

The toggle already shows which one is selected.

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

* fix(triggers): reject an entry that combines a criterion with a group

Generalizes the key+path fix: the untagged enum settles a half-and-half entry
on the first variant that fits and ignores the rest, so a criterion carrying a
group key lost the whole subtree without a word.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-08-11 11:07:12 +02:00
hugocasa 5125467de4 fix: accept a bodyless request that advertises a JSON content type (#10628)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 10:28:43 +02:00
Ruben Fiszel 4fafe59371 fix: bump the bundled DuckDB engine to 1.5.5 (#10588)
* fix: bump the bundled DuckDB engine to 1.5.5

The 1.5.5 duckdb crate no longer hands back a 96-bit `rust_decimal`, so a
DECIMAL wider than that renders instead of panicking inside an `extern "C"`
frame — which, being unable to unwind, aborted the whole worker process and
left the job running as a zombie. `SELECT
'1234567890123456789012345678.9012345678'::DECIMAL(38, 10)` was enough.

Adapting to the crate's API: `Value` is now `#[non_exhaustive]` and gained
`UHugeInt` and `Geometry`, and `rust_decimal` became an optional feature that
the `decimal`/`numeric` argument path still needs.

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

* fix: address review findings on the duckdb bump

Run the FFI crate's own tests in CI: it is excluded from the workspace, so the
`cargo test --all` in backend-test never reached them and the new guard against
the worker-aborting DECIMAL would not have run. build_dev.sh now honors a
caller-pinned CARGO_TARGET_DIR so the test build reuses that compile instead of
building the bundled engine a second time.

Also pin UHUGEINT rendering, and correct the rust_decimal rationale —
`Decimal::new` is public without the feature, so the reason is that the feature
reproduces the exact binding the crate used to derive, not that nothing else can.

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

* fix: address review nits on the duckdb bump

Name the unsupported DuckDB type rather than dumping the value, which may be
arbitrarily large or hold data that does not belong in an error message, and
say which column it came from.

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

* chore: pin the ee ref to the narrowed duckdb extension allowlist

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

* chore: pin the ee ref to the verified duckdb extension allowlist

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

* chore: pin the ee ref to the allowlist regression test

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

* chore: update ee-repo-ref to 04dd9c5c352f04995cd0470400a877261f956561

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

Previous ee-repo-ref: fe7eb440a5bbae37774d3a96b69ab5c46c0b8936

New ee-repo-ref: 04dd9c5c352f04995cd0470400a877261f956561

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-08-11 09:34:27 +02:00
Ruben Fiszel ede4e7781d unbreak the JSR publish of the typescript client (#10627)
* fix(sdk): unbreak the JSR publish of the typescript client

`Sql` is `export type Sql = string`, but build.jsr.sh re-exported it as a
value, so `deno publish` fails type-checking with TS1205 under
isolatedModules. Every `v*` tag since has published nothing to JSR.

The npm build never noticed because it lists the same symbol as `type Sql`;
the two scripts keep separate copies of the export list.

Record both JSR-only constraints next to the list, since neither shows up
until a release tag runs publish.jsr.sh.

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

* fix(sdk): scope the slow-types note to what deno actually rejects

Deno's fast check only rejects a return type it cannot trivially infer;
setClient, appendToResultStream and streamResult are all exported without
one and publish fine. The previous wording read as if the current list were
already non-compliant.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 09:24:47 +02:00
Ruben Fiszel d9b9137e17 feat(sdk): add cancelJob to the TypeScript client (#10624)
* feat(sdk): add cancelJob to the TypeScript client

The Python client has had cancel_job since forever; the TypeScript one had no
way to cancel a job at all. Wire the same jobs_u/queue/cancel endpoint, with a
default reason when none is given, and export it from both the named and
default exports of the npm package as well as the JSR one.

* chore: regenerate system prompts for cancelJob

check-system-prompts triggers on typescript-client/**, so the agent-facing SDK
reference has to carry the new function.

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

---------

Co-authored-by: Tushar <tusharanshu18@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 08:45:48 +02:00
Ruben Fiszel 13b521651b fix(python-client): return at most size bytes from S3BufferedReader.read (#10623)
* feat: add unit tests for S3BufferedReader.read and improve read method implementation

* feat: refactor S3BufferedReader.read method and add unit tests for its functionality

* feat: implement peek() on S3BufferedReader with buffered reads

* fix(python-client): keep the read(size) contract and trim the test surface

Drop the duplicated `TestS3BufferedReaderRead` class from
`python-client/tests/wmill_client_test.py`: CI runs `pytest tests/` from
`python-client/wmill`, so that legacy manual harness never executes, and the
same assertions already live in `python-client/wmill/tests/test_s3_reader.py`.

Narrow that file to the four behaviours a future change could break, and make
the `bytes_generator` guard actually call `bytes_generator`.

Align `peek()` with `io.BufferedReader.peek`, which does at most one read on
the underlying stream, rather than looping until `size` bytes are buffered.

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

* fix(python-client): hold read1 to one underlying read

read1 forwarded to read, so read1(-1) drained the whole object — the same
unbounded buffering this branch removes from read. Now that a buffer exists,
read1 can honour its own contract: fill only when the buffer is empty, then
serve from it.

Also treat read(None) as read(-1), per the BufferedReader contract, and pin
that read(0) does not pull from the stream: that holds only because the
drain sentinel is a negative size, and widening it to any falsy size would
reintroduce whole-file buffering.

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

* fix(python-client): return from read1(0) without touching the stream

A zero-length read has nothing to serve, so pulling a chunk to satisfy it
both wastes a round trip and advances the stream. Guard it ahead of the
fill, and pin it with a chunk source that counts pulls.

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

---------

Co-authored-by: Tushar <tusharanshu18@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 23:04:27 +02:00
hugocasa 06c6b8780c fix: scope a fork's cloned app policy and custom path to its creator (#10595)
* fix: scope a fork's cloned app policy and custom path to its creator

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

* fix: gate a cloned anonymous app on the parent's own deployment rule

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

* docs: state why a cloned anonymous app is gated more strictly than create_app

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

* style: wrap an over-long comment line in clone_apps

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

* fix: clone an app's execution_mode unchanged

Forcing `publisher` on a cloned app was a speed bump rather than a boundary:
protection rules are workspace-scoped and are not cloned, so the fork's creator
can publish an anonymous app there with no rule in the way. It was also the one
policy field a deploy back to the parent carries verbatim, since `update_app`
recomputes the identity but writes the policy wholesale, so a fork's copy could
silently close the parent's public endpoint.

The identity rewrite is what closes the hole this addresses: the fork's endpoint
no longer runs as whoever the parent published it as.

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

* fix: ignore an app's run-as identity when comparing workspaces

`compare_two_apps` hashed the whole policy, so a fork whose apps were re-pointed
at their creator reported every one of them as changed. Nothing could clear those
entries: the deploy offers the target's current identity, the deployer's, or a
typed-in one, never the source's, so the difference survives however many times
the item is deployed. `script` and `flow` already compare no identity.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 22:59:21 +02:00
Ruben Fiszel cf3ddaa3cc chore(main): release 1.784.0 (#10603)
* chore(main): release 1.784.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.784.0
2026-08-10 22:56:55 +02:00
hugocasa 5ed846abd2 chore: internal accounting update (#10602)
* chore: bump ee ref and refresh query cache

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

* chore: bump ee ref

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

* chore: bump ee ref

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

* chore: bump ee ref

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

* chore: bump ee ref

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

* chore: update ee-repo-ref to 236115e11f074d86675aa5acdf5061dd3e64f43c

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

Previous ee-repo-ref: 62bc50118d09374b8a45756504520cfb6e5f0210

New ee-repo-ref: 236115e11f074d86675aa5acdf5061dd3e64f43c

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-08-10 21:55:09 +02:00
Ruben Fiszel 2748d019f5 fix(cli): load the app's ESM svelte compiler, not its CJS one (#10622) 2026-08-10 21:50:03 +02:00
hugocasa c09de594b6 feat: version resource values with history, diff and restore (#10596)
* feat: version resource values with history, diff and restore

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

* fix: record resource versions in a trigger so direct writes are covered

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

* fix: show the selected version's value and tighten history write access

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

* perf: gate resource version recording in trigger WHEN clauses

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

* feat: clear a resource's past versions, and address review nits

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

* fix: restore the displayed version and keep author attribution on pooled writes

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

* fix: scope history to the selected workspace and gate clearing on ownership

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

* fix: gate restore on write access and clearing on the signed-in workspace

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

* refactor(frontend): share the version-history row between script and resource drawers

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

* perf: trim resource version history in the monitor sweep, not on write

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

* fix(frontend): match the script versions drawer shell for resource history

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

* perf(frontend): highlight version values instead of mounting monaco

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

* fix(frontend): match the script drawer's code preview presentation

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

* fix: rank version trim in one windowed pass instead of a correlated delete

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

* refactor(frontend): treat the newest version as current by position

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

* perf: gate the resource version trim to an hourly sweep

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

* fix: unnest the version row action and correct the trim cadence docs

* perf: cap the history listing and use sets for reference lookup

* feat: warn when a resource is written more than 60 times a minute

* fix: lower the resource write advisory to 20 per minute

* fix: discard stale history loads and never diff against an unread value

* fix: correct the write advisory boundary and document the eviction lock

* fix: read history and the live value from one snapshot

* refactor: read the drawer's diff baseline from versions, not the live resource

* fix: open the history drawer with no version selected

* fix: disarm the clear confirmation and clear the pane when the selection moves

* fix: explain the missing diff and drop a guard that can no longer fire

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 21:32:18 +02:00
Ruben Fiszel 5b0a159a01 fix(smtp): explain why a test email failed instead of 'deadline has elapsed' (#10620)
* fix(smtp): explain why a test email failed instead of 'deadline has elapsed'

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

* fix(smtp): keep non-SMTP error codes and retire a stale test alert

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

* chore: update ee-repo-ref to f0df8b82c4c089d384423ed64b8504506084820d

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

Previous ee-repo-ref: 1ffaf3dea81e007c6c11146c1e12e97e83f5b938

New ee-repo-ref: f0df8b82c4c089d384423ed64b8504506084820d

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-08-10 21:21:14 +02:00
Vladislav Kuzmin bf1b2cdcf9 fix(duckdb): cast list columns in quicksearch so tables containing them can be previewed (#10614)
* fix(duckdb): cast columns in quicksearch so nested types can be previewed

DuckDB's `CONCAT` implicitly casts scalars but rejects nested types:

    D SELECT CONCAT(' ', ['a','b']);
    Binder Error: Cannot concatenate types VARCHAR and VARCHAR[] - an explicit
    cast is required

Quicksearch concatenates every visible column, so one LIST, STRUCT or MAP column
makes a table impossible to preview — both the grid and its row count fail:

    Binder Error: Cannot concatenate types VARCHAR, VARCHAR, BIGINT, ...,
    VARCHAR[], ... and TIMESTAMP WITH TIME ZONE - an explicit cast is required
    LINE 1: ... FROM "raw"."accounts" WHERE ($1 = '' OR CONCAT(' ', "id", ...

Every scalar in that list concatenates fine on its own — VARCHAR, BIGINT,
DOUBLE, BOOLEAN, DATE and TIMESTAMPTZ were each checked individually — so the
array column is the entire cause.

Cast each column in the predicate. The comparison is textual either way, so no
result changes, and the projection is untouched: casting there would change the
types the caller reads back. This follows the shape already used for MSSQL in
`mssql_needs_cast_for_eq`.

Both DuckDB quicksearch sites are covered, SELECT and COUNT. Fixing one leaves
the grid rendering while the row count still errors.

Tests include the live path: the Database Manager sends a
`-- WM_INTERNAL_DB_SELECT {...}` marker and the backend expands it, so the new
test drives that expansion with the real 27-column definition captured from a
failing job, `sync_id VARCHAR[]` included. It fails without the fix and passes
with it.

* fix(frontend): cast columns in the DuckDB quicksearch

Same defect as the Rust query builders, in the implementation that actually
runs. `make_select_query` / `make_count_query` in windmill-common have no callers
anywhere in the repo; the query the browser sends is built here.

DuckDB's CONCAT implicitly casts scalars but rejects nested types, and
quicksearch concatenates every visible column, so one LIST column makes a table
impossible to preview — both the page and its row count fail with

    Binder Error: Cannot concatenate types VARCHAR, ..., VARCHAR[], ... and
    TIMESTAMP WITH TIME ZONE - an explicit cast is required

The helper lives in select.ts and is imported by count.ts so the two cannot
drift, and both call sites are fixed: fixing only SELECT leaves the grid
rendering while the row count still errors.

* fix(duckdb): cast only list columns in quicksearch, leaving other SQL byte-identical

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

* test(frontend): pin the DuckDB quicksearch column list byte-for-byte

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

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 20:48:19 +02:00
Ruben Fiszel 8c65511e81 fix: raw app new-app modal ignores instance-level AI settings (#10619)
* fix: stop the new raw app modal claiming AI is unconfigured before it knows

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

* fix: require a resolved workspace before trusting the loaded AI config

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

* fix: drop the unreachable token guard and point superadmins at instance settings

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

* fix: show the instance settings link to superadmins who are not workspace admins

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 20:39:38 +02:00
Ruben Fiszel b7d2052b03 block the whole 0.0.0.0/8 range in the SSRF filters (#10597) 2026-08-10 19:57:29 +02:00
AlexRV12 77adf85ccd feat: version history for session artifacts (#10574)
* fix: never replace an in-flight indexeddb open, only a settled one

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

* feat: keep a version history for session artifacts

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

* feat: let the assistant browse an artifact's earlier versions

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

* feat: pick an older artifact version from the preview panel

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

* test(ai_evals): cover the change note the assistant writes on each edit

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

* fix: bound every indexeddb open, not only one told it is blocked

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 19:51:29 +02:00
Ruben Fiszel 4a69cd616e keep the logins state declaration from narrowing to undefined (#10618) 2026-08-10 19:45:27 +02:00