mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-04 00:02:17 +00:00
64f0e87d577e1a502e4d4114429660e1ffecf485
14994
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
64f0e87d57 |
oauth: add github scope_options (gist, read:org) (#11471)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
153b02a5de |
fix: offer user scopes in the slack scope editor and drop the generated description on type change (#11464)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
f74113c75a |
post ai eval results to the workspace-prefixed cloud route (#11473)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
26be1d7da8 |
feat: add test key button to AI resource drawers (#11466)
* feat: add test key button to AI resource drawers * fix: scope-check inline AI resource values and keep test model editable * fix: keep test model editable for unsaved resources, own-key provider check |
||
|
|
88d0cd00e5 |
fix: restore the save to workspace button on inline flow steps (#11469)
* fix: restore the save to workspace button on inline flow steps Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: make the inline step save to workspace button icon only Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
7f1beadf79 |
feat: add wmill datatable migrate status (#11465)
* feat: add wmill datatable migrate status Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: show unpushed local migrations in datatable migrate status Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: move pushLocalMigrations doc comment back onto its function Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c72ae8f7d4 |
oauth: offer granular gcal read scopes (calendar list, metadata, free/busy) (#11459)
Keeps the calendar.events default. Adds calendarlist.readonly, calendars.readonly and freebusy as labelled scope_options so the hub's get_calendar_list, get_calendar_metadata and free/busy scripts can be granted least-privilege. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
ab2de838d7 |
feat: offer slack write scopes as bot and user scope options (#11472)
* fix: offer user scopes in the slack scope editor and drop the generated description on type change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: offer slack write scopes as bot and user scope options Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8c92e63ffc |
chore(docker): bump bundled crane to v0.22.1 (#11470)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
1c6758a656 |
fix(npm-proxy): support _auth and username/_password basic auth from npmrc (#11467)
* fix: send npmrc basic auth (_auth, username/_password) from the npm proxy Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: resolve npmrc credentials from parent paths like npm Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: honor empty npmrc overrides and keep registry credentials to its origin Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
b10f83c763 |
feat(sessions): show an item's deployed page in the preview panel (#11458)
* feat(sessions): show an item's deployed page in the preview panel The preview panel showed an item's editor and nothing else. It now shows the deployed page too, as a tab of its own. **Two sides, two tabs.** The editor and the deployed page are different things to look at, so `isItemTabFor` keys on the side rather than the item: asking for a side already open focuses it, asking for the other opens it alongside. Two editors for one item still cannot coexist — they would race its single (kind, path) cell — but an editor beside a viewer is safe, since the viewer reads the deployed version over the API and holds no cell. The tab breadcrumb keeps re-pointing in place; `Exit & see details` and the detail page's `Edit` open the other side instead of consuming the one you are on. A tab's label carries `(edit)` when it is the editor side. **The detail pages moved out of their routes.** `/scripts/get` and `/flows/get` are now thin wrappers over `ScriptDetail` and `FlowDetail`, which the panel renders too. Everything they reach — drawers, triggers, saved inputs — is scoped to the viewer's workspace through `setOperatingWorkspace`, and every navigation they attempt is caught by `interceptNav` and turned into a move inside the panel, so nothing takes the browser out of the session. A plain click is intercepted; ⌘-click and middle-click still open a real tab, which is why the pages keep their `href`s. **The picker opens what exists.** A row opens the deployed page, or the editor when nothing is deployed there, and carries a Draft / Draft only badge in the review dock's words. `WorkspaceItem` gained `draftOnly` and `hasDraft` from the listers, which already returned both; deploys now invalidate the picker cache through `itemDeployed`, so a just-deployed item stops reading as a draft. Rows also carry a hover Edit action, reachable from the keyboard with the pick modifier. `open_preview` gained a `mode`, narrowed out of the advertised schema for a session that cannot write drafts and re-checked per path in the handler, where a refusal reports "couldn't check" apart from "denied". The mode is resolved before those checks, so a call that omits it is gated as the editor it will become. Alongside, the workspace a detail page acts on is now the one it is showing rather than the one the browser is navigated to: `MoveDrawer`, `toggleWorkspaceErrorHandler` and the pages' own permission gates read the operating workspace and its acting user, and `RunForm` mints a password argument's ephemeral variable there too — in a fork session all of these previously answered for the parent. `InWorkspaceAppViewer` hands the app's `ctx` user down as a prop instead of writing the global `userStore`, which from a session tab was re-pointing every permission check on the page. Fixes found on the way: `DetailPageLayout` claimed `h-screen` inside a panel that is not the viewport; Edit on a historical script version dropped the version from the intercepted click; the Run button stayed spinning after a run that left the page mounted; and the window-level run shortcut fired from a collapsed panel and from keys another handler had already claimed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(sessions): historical edits, stale not-found, shared edit rights, tab labels Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): keep deployed-page links and workspace reads in the session Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): scope detail hrefs to the session, re-point the viewer's own tab Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): keep a previewed raw app's route out of the session URL Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): resolve edit-in-fork against the session workspace Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): read advanced run tags from the session workspace Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): fork from the session workspace, star only navigation items Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): mount only the side a preview tab shows Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): address CI review round 1 findings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): route links in a deployed page's drawers through the panel Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): tell the chat which deployed page the panel shows Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): only a 404 reads as an undeployed raw app Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): scope the unparseable-JSON run gate to the form Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): a flow deleted from the panel stays in its tab Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): the picker's edit shortcut works on the current row Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): load-error toasts say what failed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sessions): keep an oversized invalid JSON editor in its form's run gate Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * revert: keep main's draft_only description in openapi.yaml Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d518aa5557 |
feat: let slack connects issue a user token via user_scope (#11452)
* feat: let slack connects issue a user token via user_scope Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: keep trailing newline in ee-repo-ref Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: bump ee-repo-ref Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: name the provider in slack token descriptions and refresh them on reconnect Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: drop the generated slack description when connecting another provider Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: drop the slack scope pin migration, slack ignores scope on refresh Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: clear the generated slack description on client-credentials connects too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: update ee-repo-ref to ff4d04f17721d84fb9a1f655af50ff7e4e7dcbc7 This commit updates the EE repository reference after PR #837 was merged in windmill-ee-private. Previous ee-repo-ref: 83298dcf23574d5ed05e6c767bf1d9b067ab7a95 New ee-repo-ref: ff4d04f17721d84fb9a1f655af50ff7e4e7dcbc7 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
227e934210 |
feat: harden job OIDC tokens with version claims, jti and a lifetime cap (#11457)
* feat: harden job OIDC tokens with version claims, jti and a lifetime cap Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: count restarted flow nodes as latest only if the current version uses them Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: follow stored loop and branch bodies when resolving current flow nodes Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: bind current flow nodes to their step id and skip non-numeric node keys Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: derive flow step currency from the flow above it and restarts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: treat every restarted job but a version-checked flow as not latest Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: count a restarted body as latest when the run it came from was current Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to b469efc9ceddfaaa1040e4cb2c18993822f92c78 This commit updates the EE repository reference after PR #838 was merged in windmill-ee-private. Previous ee-repo-ref: 25e0b9ae1c6c60419a479fa38d5dc5928832790a New ee-repo-ref: b469efc9ceddfaaa1040e4cb2c18993822f92c78 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
d2830cb4a0 |
fix: stop running deleted script versions from worker caches (#11456)
* fix: stop running deleted script versions from worker caches Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: reuse script cache invalidate and test the deletion notify payload Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep a deleted copy from shadowing the same hash in another workspace Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: drop deletions missed while down and fills racing the eviction Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: batch deletion events, evict path caches and cover version pruning Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: evict the raw-import cache on both passes and split large deletion events Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
840567fbe5 |
feat: labelled scope checkboxes in the oauth connect dialog (#11460)
* feat: show human labels for oauth scope options in the connect dialog Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: always show scope checkboxes, label gdocs and gchat scopes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: offer default scopes as checkboxes for every oauth provider Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
ddde41bc1d |
fix: block runs while a JSON input does not parse (#11463)
* fix: block runs while a JSON input does not parse Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: clear json editor error on unmount and flush editors before run Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: restore validity when a nullable arg input is cleared Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: let field editors parse before the run check and reset the message on view switch Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: clear the run refusal message when form validity changes Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
5bd2c2c254 |
drop unused mut that breaks the backend integration test build (#11462)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
f1d970bd1a |
ci: move CI AI models to opus 5.5, gpt-6.1 sol and deepseek v4.1 (#11461)
* ci: move CI AI models to opus 5.5, gpt-6 and deepseek v4.1 flash * test: point the deepseek eval alias at v4.1 flash * ci: run the codex review on gpt-6.1-sol with codex cli 0.159.3 |
||
|
|
94924d4644 |
chore(deps): bump docker/build-push-action from 5 to 7 (#11421)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 7. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v5...v7) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
c25bb1ed90 |
feat: add //no_network annotation for native scripts (#11445)
* feat: add //no_network annotation to deny all network access in native scripts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: close no_network bypasses (quic dns, header parsing, token, non-native) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: refuse //no_network on deno regardless of //native, derive disabled ops from deno_net Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: scope //no_network to native scripts only, drop bun/deno refusal Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
bba58c4167 |
oauth: add gdocs and gchat providers (#11447)
* oauth: add gdocs and gchat providers, gchat icon Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * oauth: Google sign-in button for every accounts.google.com provider, least-privilege gchat default - AppConnectInner: derive isGoogleSignin from the registry auth_url instead of a hardcoded list, so gdocs/gchat/gforms/gcloud/gworkspace get Google's button. - gchat default scopes: chat.messages is a restricted scope; default to chat.spaces.readonly + chat.messages.create (both sensitive). chat.messages / chat.messages.readonly stay selectable. - BRAND_COLORS.md: GchatIcon row in sort order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
a8e65ab1e6 |
fix: lost suspend decrement when concurrent approvals resume a flow (#11450)
* fix: make RunForm schedule props optional and expect 403 for operator drafts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: serialize concurrent approval resumes on the flow's queue row Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: read flow status after taking the resume lock Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: route every approval decrement through one helper Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
c0fb2db244 |
fix: keep flow graph rendered between deploy and navigation (#11454)
* fix: keep flow graph rendered between deploy and navigation Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: rename flow snapshot to avoid shadowing in loadFlow Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
851f6d74c9 |
fix: ignore edited_at and edited_by in flow and item diffs (#11455)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
6fe992aebe |
make RunForm schedule props optional and expect 403 for operator drafts (#11449)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
8953ca670a |
feat: make hub integrations usable as examples in global AI chat (#10599)
* feat: make hub integrations usable as examples in global chat Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: keep web search guidance in sync with provider capability Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: resync web search guidance before the request is built Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: carry loop web search availability into every prompt rebuild Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: drop web search guidance on the completions api fallback Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: correct onBeforeIteration contract for the fallback re-entry Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: give the ai chat hub script descriptions and integration metadata Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: treat authored hub metadata as evidence the scripts were curated Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: treat hub curated as three-state and speak only for a stated true Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test: let the benchmark hub serve integration metadata Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test: benchmark the hub tool against a real integration's scripts and metadata Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test: cover two more real integrations where the scripts already answer Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test: report metadata_source from whether the fixture has authored meta Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: parse the hub resource type schema instead of relaying it as a string Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: match integration suggestions on slug words instead of substrings Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: search the integration a query names outright instead of ranking past it Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: reject hub integration slugs that would re-target the proxied request Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: add a mentioned integration's hits instead of filtering the search to it Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: keep named-integration hits under the content cap and unmangle fixture placeholders Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: cut the middle of a capped hub result instead of repeating its tail Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: cap hub results by keeping the best of the ranked and named hits Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: keep a named integration that ranking placed below the content cap Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: let plan mode use the hub integration lookup Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat: mark which hub integrations carry authored provider knowledge The hub flags the integrations whose document holds hand-written provider knowledge, so a caller can tell before spending a call on the metadata endpoint: 18 of ~216 qualify, and for the rest the endpoint returns what was inferred from the same scripts a search already hands back. Carry the flag onto search results, where the model first meets a slug, so get_hub_integration is aimed at the few instead of guessed at. A hub that predates the flag omits it and nothing is marked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: stop the documented mark reading as a reason not to call The flag says the hub additionally holds provider knowledge checked against the live API. It is not a signal to skip the lookup elsewhere: that call still returns the resource type and the usage-ranked examples, neither of which a search result carries, and neither guessable. The prompt said to read a script instead when the mark is absent, which traded those for a guess on the ~198 undocumented integrations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: keep the benchmark's documented flag true to what it serves The eval hub reported Baremetrics and Holded as undocumented while its metadata endpoint handed back their authored notes, so a case could teach the model the flag means nothing. Derive it from both fixture sources, and pin the agreement. Also trims the documentedIntegrations comment to the four lines AGENTS.md allows, keeping the case-folding constraint. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: keep the benchmark hub mostly undocumented, like the real one Adding holded and baremetrics to the documented set resolved the fixture's contradiction the wrong way: it left five of six integrations marked, against the live hub's 18 of ~216, and claimed authored notes for two the hub reports as having none. Drop the notes instead. Their auth and endpoints are in their shipped scripts, which is what the cases that use them are about. Also drops the last two places still describing the flag as a reason to spend or skip the metadata call. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor: let the model name the integration instead of guessing it from the query Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor: word web search guidance conditionally instead of tracking provider capability Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: open the hub metadata route to job tokens and share one integrations fetch Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: record a copied hub script's source where write_script keeps it Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test: pin that a query narrows to the integration it was given Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: match integration suggestions on the name the hub curates Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: name an integration the hub leaves unnamed from the local word table Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
8c7dcbbda5 |
feat: agents as a standalone kind with home listing, detail and editor pages (#11332)
* feat: list agents on the home page and create them from the new menu Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep runnables out of the agents view and anchor a new agent once saved Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: autosave a new agent's first edit and list agents past one page Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: add agent detail and editor pages Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: explain when an agent cannot be run and drop the broken agent move Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep query params and a unique path when creating an agent Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: lead the home list with agents and keep rows while the agent view loads Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: treat a loading agent as undeployed when leaving the editor page Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: agent detail page config panel, run page on form runs, chat badge Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: agent configuration modal and draft paths like other new items Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep a new agent draft-free until the first input, land agents with runnables Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: place AI agent after apps in the new menu and describe chat and flow use Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: new agents start with managed memory, editor form says how to turn it off Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: clearer managed memory hint in the agent editor form Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: share the agent editor's pane notice as a PaneNotice component Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: name a new agent after a path no resource holds Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: tell repeated tool names apart and hide permissions on draft-only agents Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: agent configuration beside the model in the chat composer and above the form Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: center the agent run form, configuration beside its Run button Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: icon-only agent configuration button beside Run Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: agents run on behalf of their deployer through a run-by-path endpoint Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: agents keep their run-as identity in their value, preserved by the CLI The identity an agent runs as lives in `value.on_behalf_of` instead of a column. Every write of an agent resolves it server-side as a flow's is: the writer's own, unless an admin or wm_deployers member asks to keep it, and a folder default on create. Retyping a resource into an agent resolves its value the same way. Export leaves it out; the run endpoint reads it and drops it from the step's inputs. The CLI follows the app model: a pushed agent never takes its identity from the tracked file, an unchanged agent compares equal to the deployed one, and an admin or deployer push claims the deployed identity back. The owner-change pre-check lists agents. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: deploying an agent draft from review keeps its deployed identity As for an app: an agent draft carries no identity, so the review page claims the deployed one back, which the backend honours for an admin or wm_deployers member. The draft diff leaves the deployed identity out, since a draft never holds one. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: deploying an agent to another workspace offers the run-as choice An agent deployed to prod/staging, merged from a fork or promoted with `wmill workspace merge` gets the same identity choice as a flow or an app: the target's current one, the deployer, or a picked user, sent as a principal the way a trigger's is. The source workspace's principal is never copied, and a difference in identity alone is not a change in the workspace compare or its diff. The frontend consumes the published windmill-utils-internal, so its deploy provider carries the same rewrite until that version ships. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: agent identity on fork, agent-scoped job reads, and the run license gate A fork re-points an agent's identity at its creator when they may not preserve someone else's, and at the creator when it names nobody in the fork, as it does an app's. A token scoped to `jobs:run:agents:<path>` reads back the runs it starts, chat turns included. The agent run endpoint checks the enterprise license like every other run entrypoint. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: a CLI push decides agent identity handling by the tracked file's type An agent retyped into another resource by a push kept neither its value's `on_behalf_of` as the file stated it nor clear of the old agent's identity. The file's type now decides, and only a deployed agent's identity is claimed back. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: agents run as the caller, with a note on what a shared one needs Drops the agent run-as identity: its storage in the agent value, the backfill, the resolution on every write, and its handling in export, the CLI, draft and cross-workspace deploys, forks and the workspace compare. The run endpoint runs as the caller, so an operator or reader runs an agent with their own access. The editor tells the author of a folder agent that anyone running it needs access to its AI resource and to what its tools use. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: agent editor comments describe runs as the caller Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: agent editor pane notes use Alert Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: agent editor pane notes render as Alert Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: agent editor notes as regular Alerts, not banners Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: agent path as its own editor level, and evals on the agent page The path leaves the agent form: the editor dialog opens it as a level, as it does evals, and the editor page in a drawer. The agent page gains Evals, in a dialog. The page supplies the run form, keeping it out of the editor the flow editor reaches. The draft edit gate no longer throws when a focused, changed field is removed: the `change` that removal fires lands mid-teardown, so the gate opens just after instead. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: agent settings as the resource editor's header fields, behind a cog The agent's own settings (path, labels, workspace specific, description) open from a cog as the flow and script editors' do, laid out as the top of the resource editor. The folder note is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: agent settings fields and cog, completing the rename Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: evals open as a dialog over the agent editor page The editor page opens an agent's evals over itself, as the agent page does, with the unsaved edits offered to a run; the editor dialog keeps evals as a level of its own. The two pages share the dialog. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: the unreachable model provider note reads like the unreachable agent one Same warning level and wording as the note above it, with the path inline rather than in parentheses that lost their spaces. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: the unreachable model provider note offers editing the agent too Editing the agent to use a provider the reader can access is often the simpler way out; offered when the reader can write the agent, with Unlink and asking for access. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: provider note lists asking for access as its own option Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: shorter provider note, without the header's buttons repeated Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: evals only for those who can edit the agent Evaluating builds datasets and runs against the agent, which is authoring: the agent page and the editor offer it only with write access to the agent. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: agent page actions ordered as the script and flow pages The menu leads and Edit comes last, as DetailPageHeader lays them out. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: the agent editor dialog's levels slide in built on the first visit Warmed, as the evals pane's levels are, so settings and evals are mounted before the first navigation rather than inside its transition. Evals are only in the strip where they can be opened. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: the agent's settings report path errors, and hold nothing a reader can edit The path field reads its error back, so it shows it and keeps deploy blocked on it. Labels are shown rather than editable without write access. Evals wait for the load to know they can be opened, and the page layout builds no levels it never shows. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: one builder for an agent's run flow, and the agent page on the shared header The run endpoint and evals build the agent's one-step flow through the same function. The agent page uses DetailPageHeader, whose error handler, tag and trigger context are now optional, and whose menu items keep their disabled state. The home row and the page share the agent's menu and delete. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: the agent page's menu is built from its current path Deploy settings are the workspace's, so they load once and the menu is derived from them rather than fetched per path, where a superseded fetch could land after a navigation. The shared run-flow builder lives with agent runs rather than evals. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: the scoped-read comment names the run-flow builder as it is Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
ca44043e12 |
feat: let operators compose flows when the workspace grants the right (#11228)
* feat: let a workspace withdraw operator schedule and trigger writes Operators can create, edit and delete schedules and triggers today through the API, CLI and MCP, while the operator_settings flags beside them only hide those pages. An admin who wants operators to see what is scheduled without letting them change it cannot express that. Add manage_schedules and manage_triggers as enforced settings, gated at the schedule handlers and at the generic TriggerCrud routes so every trigger kind is covered by one check. They name capabilities operators already hold, so they are granted unless withdrawn, and absence has to mean "never configured" rather than a value. The read coalesces to true; the update endpoint merges into the stored jsonb with the two fields as Option<bool>, so an omitted key keeps what is stored. operator_settings is git-synced as a whole object, so a settings file written before these keys existed reaches the endpoint on every pull, and a serde or SQL default of either polarity would turn that pull into a silent withdrawal or restoration. The rights are read through a per-process cache, so withdrawing one publishes a notify_event that drops the entry on every replica. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dsf6VC4MVLisiEoeQkgbr4 * feat: let operators compose flows when the workspace grants the right Adds operator_settings.builder_flows: a workspace setting that lets every operator compose flows out of runnables that already exist. It does not make them authors. The boundary the operator role draws is authoring code and running arbitrary code, and this does not move it: check_flow_is_composition_only walks the value and refuses anything carrying code, including the shapes an obvious walk misses (code hoisted into a flow_node, an AI agent step's tools, and a linked ai_agent resource whose tool list is resolved at run time). What the walk cannot settle it returns for the caller to authorize under RLS: the worker tags the steps pin, every runnable they reference, and the (path, hash) of every version-pinned step. Composing a path is enough to run it and to run it as whoever it runs as, since the worker resolves a step's path with the root DB handle and adopts that runnable's on_behalf_of. A pinned hash needs its own check because dispatch ignores the path beside it. The gate runs on every write and on both request-supplied-value paths, flow preview and flow dependencies, or either becomes the way to run what the write path refuses. Operators of a builder workspace consume a full author seat; the EE companion carries the counting. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dsf6VC4MVLisiEoeQkgbr4 * feat: enforce operator write rights on the router and in the UI Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: close the capture gap and gate the trigger editors' write actions Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: gate acl writes and the native trigger drawer behind manage rights Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: refuse operator writes with 403 and gate sharing at the drawer Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * perf: resolve identity in the operator write gate only for writes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: gate the suspended-jobs actions and stop the route check refusing reads Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: explain the empty-state create button when operator writes are withdrawn Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: audit operator settings changes and fold path writes into native rows Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: open locked editors read-only and group the operator settings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: skip email and azure lookups on editor open while triggers are locked Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: state each operator-rights rationale once in comments Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: address CI review findings on operator write rights Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep capture move gated and skip it in the builders while locked Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: refuse builder-rights violations with 403 so operators stay logged in Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: trim duplication in the operator builder gates Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: hide build app from builder operators on the flow page Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: point at the companion EE PR merged with EE main Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep a builder's drafts list loading past drafts they cannot write Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: hide saved agents from builder operators in the step picker Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: note the inlined seat rule and drop orphaned sqlx entries Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: stop a builder's step test from logging them out Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: refuse a builder's dependency job on a path it cannot write Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep builders from adding dynamic dropdown code to a flow A flow's dropdown code runs as whoever loads its form, so a builder may keep or drop the code stored on the flow it updates, never add or change it. The builder's editor hides the dropdown types and code, and previews options through the deployed flow; the inline dropdown refusal is a 403 so it no longer logs operators out. Also trims rationale comments repeated across sites. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: show why saving operator settings failed The seat-cap refusal on granting builder rights explains what to do; the toast now carries the server's message instead of a generic failure. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: check builder flow drafts like deploys and treat dropdown code as code A developer who loads a builder's flow draft in the editor runs its dynamic dropdown code as themselves, so a builder's draft now passes the same checks as a deploy. Dropdown code is refused like step code rather than kept or dropped, which also removes the exact-match comparison that refused builders over whitespace. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: bill a builder workspace's operators as developers on cloud The cloud seat count behind the Premium page, the sidebar usage and the fork cap still weighed every operator at half a seat, while the builder right makes them authors. The out-of-repo invoicing job must follow the same rule. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: check a builder's flow draft as it will be stored Draft storage strips NUL escapes after the builder check, so a key ending in one (value\u0000, x-windmill-dyn-select-code\u0000) passed the check as an unknown field and was stored under its plain name. The check now reads the sanitized text. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: list a builder's flow drafts and hide hub imports from builders A builder's undeployed flows now appear in the home list, the flow list and the folder counts. Hub project imports and templates bring scripts and apps along, so builders are no longer offered them. The docs record builders' JavaScript expressions as an accepted risk. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep the stored builder right when a settings payload omits it A git-synced settings file written before the key existed withdrew the right on every push. builder_flows now follows the manage_* rights: an omitted key leaves the stored value, and the CLI does not count it as a difference. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: word builder refusals by what the flow contains, test the tag refusal A builder refused on a developer's flow never changed its code, so the refusals now describe the flow ("has inline code, so only a developer can edit this flow") rather than an authoring attempt. The grant confirmation uses the neutral dialog: granting changes billing but destroys nothing. The integration test pins the refusal of a worker tag the workspace cannot use. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: read builder rights from the operating workspace, gate the flow page's audit logs entry Builder rights now come from useOperatorBuilderFlows(), next to the schedule and trigger locks, so an editor embedded for another workspace answers about that workspace; the legacy AI chat, one instance for the whole app, reads the navigation workspace. The flow page's Audit logs entry follows the operator audit_logs setting now that builders open that menu. Operator settings reset every value on load, null settings included, so nothing carries over from the previous workspace. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: pick a dynamic dropdown's code source by the operating user's role The flow input editor, the flow test panel and the flow chat send the dropdown request to the operating workspace, so they now also choose inline versus deployed code by the role held there, through useOperatingUser(), instead of the navigation workspace's. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 40ac1c5f8cbce3843b582d9b392d3f3cc7eca3e6 This commit updates the EE repository reference after PR #815 was merged in windmill-ee-private. Previous ee-repo-ref: 31c9e66884b8ca805b20bbfad41fc428fbedbc0e New ee-repo-ref: 40ac1c5f8cbce3843b582d9b392d3f3cc7eca3e6 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
9613549abc |
feat: group consecutive tool calls in the AI chat (#11329)
* feat: group consecutive flow edits into one collapsible chat row Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: group lookups, name flow steps and fade tool label changes Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: count rejected draft saves as failed in tool groups Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: address review nits on chat tool grouping Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: hold a tool group's live step line like its header Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: hold a tool group's live line in the same value as its header Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep main's new tool cards and held calls out of tool groups Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: group app edits and mark single-server MCP groups with the server icon Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: tell MCP servers apart by full path in tool group headers Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep a streaming edit in its group and stop rekeying unsettled labels Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: word a queued tool group as settled until a call starts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: give queued tool groups their own wording and leave unnamed calls ungrouped Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep a tool group in progress between two of its calls Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: treat an edit without a path as unknown unless it is a flow-mode tool Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: let flow mode's pathless edits group again, keep unnamed app edits apart Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: only flow mode's pathless tools default to the open flow Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: key tool rows by their call so a loaded chat never shows a held label Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
083db5e388 |
feat: open chat path pill actions from a hover menu (#11441)
* feat: open chat path pill actions from a hover menu Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: build the path pill menu rows from Button Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: resolve chat path pills by a draft's chosen name Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: alias a draft name only to an item of the same kind Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
52c31881fc |
feat: add alert actions and reduce alert padding (#11439)
* style: reduce alert padding * feat: add alert actions rendered as buttons in the alert's colors * fix: address review nits on alert actions and button tone * fix: color split-button outline and divider by tone * fix: apply tone hover and disabled states to the split-button chevron * refactor: ignore button tone on split buttons |
||
|
|
077709b914 |
feat: rename agent memory options to On and Legacy, explain each (#11442)
* feat: rename agent memory options to On and Legacy, explain each Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: default the chat agent example to On memory and align the schema copy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: offer Legacy memory only to steps that hold it, explain under the toggle Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep the off memory hint true on the saved-agent editor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: state the 128k fallback in the context window description Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
e117871bec |
weekly ai evals on current models, and claude 5.5/gpt-6 support (#11409)
* feat: run ai evals weekly on current models and post results to a dashboard Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: add current flagship models, a reasoning flag and claude 5.5 defaults Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: never send a reasoning disable claude 5.5 or gpt-6-astra reject, and treat gpt-6 as a reasoning model Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: address review on gpt-6 support, chat completions tools and model metadata Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: leave tiered gpt-6 unpriced and drop the off sentinel on gpt-5 and o-series Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: point the ai_evals readme at the model registry instead of copying it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: encode the reasoning rules as per-family maps with a shared parity fixture Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep the chat completions tools rule open-ended past gpt-5.6 and scope the parity fixture Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
94ac34a489 |
fix: await async def main in python scripts (#11437)
* fix: await async main and preprocessor in python scripts * fix: reuse one event loop per python process for async main * fix: reuse the event loop a python script sets at import * docs: clarify python await helper comment |
||
|
|
7664001b36 |
fix: bump git sync hub scripts to cli 1.820.1 (#11438)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
1d8d4a16b4 |
fix(cli): resolve fork specific items from the parent workspace entry (#11436)
* test(cli): stop CLI tests resolving a just-published windmill-client Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test: quote the Windows cert path in the pg attach assertion Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(cli): note when the windmill-client pin must move Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cli): resolve fork specific items from the parent workspace entry Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(cli): keep fork resolution to the id-guarded inference Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
ab2a973357 |
fix: collapse run card in ai chat when the run is declined (#11435)
* fix: collapse run card in ai chat when the run is declined Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: simplify run card collapse condition and comment Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
9028432e8a |
fix: embed a VERSIONINFO resource in the Windows binary (#11433)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
c728346a15 |
fix(apps): hide custom component host while it is not rendered (#11434)
Semi-lazy mode mounts unvisited subgrids' components with render=false so they initialize outputs. The custom component always kept its host div visible and the user's renderer draws into it regardless of render, so its content landed in the parent's layout flow and pushed the visible tab's components down until the owning tab was first opened. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
cec8eaeadb |
test: fix CLI and Windows cargo test failures on 1.820.0 (#11429)
* test(cli): stop CLI tests resolving a just-published windmill-client Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test: quote the Windows cert path in the pg attach assertion Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(cli): note when the windmill-client pin must move Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
039f49ef12 |
feat: dispatch ai agent tools through the worker queue (#11227)
* feat: dispatch ai agent tools through the worker queue * fix: respect worker tags when executing ai agent tools locally * fix: cancel only direct-child tool jobs on agent failure * fix: cancel queued descendant tool jobs on agent failure * fix: route ai agent tools by the flow's tag rule |
||
|
|
f890355211 |
chore(main): release 1.820.0 (#11404)
* chore(main): release 1.820.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.820.0 |
||
|
|
0fdf17d339 |
feat: data table cards and a managed-first add wizard (#11419)
* fix(datatables): refuse a save that drops a data table's roles through an undeclared rename
A data table's roles follow its entry only through a declared rename. A
settings sync sends the whole map and never declares one, so renaming a
data table under roles there read as a delete and a new entry on the same
database: the new entry carried no roles, and every caller connected as
admin. Such a save is now refused, naming both entries.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* fix(datatables): no entry without roles may newly reach a database under roles
The previous guard only caught a new name replacing an entry under roles.
A whole-map save could also repoint an existing entry without roles at
that database, or another workspace could point one there, and every
caller of that entry would connect as admin. The rule is now stated on
the saved entries: one that carries no roles and newly points at an
instance database any entry under roles uses, in this workspace or
another, is refused. A declared rename carries its roles and passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* feat(datatables): move data table role catalog and resolution to the enterprise edition
Roles are an Enterprise Edition feature. The catalog, the Postgres logins,
CONNECT convergence, tenant evaluation and the role half of connection
resolution move to windmill-ee-private. Every public function keeps its path
and signature and forwards through datatable_roles_oss, which re-exports the
enterprise implementation or, without it, refuses.
Without the enterprise edition a data table under roles, or a caller naming a
role, is refused a connection rather than resolved as admin, and the reach and
admin-access checks refuse one under roles. A data table not under roles
resolves as before in every edition, and an instance database keeps the
CONNECT grants it was created with. The catalog lock, the stream lock, the
tenant cascades and the permissions stripping stay in OSS: they only restrict.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* feat(datatables): move the data table permissions endpoints to the enterprise edition
The permissions read, save and usable-roles handlers move to
windmill-ee-private; the routes stay registered and, without the enterprise
edition, answer that data table roles are an Enterprise Edition feature.
ensure_governs_datatable and ensure_reaches_datatable keep their paths: the
first refuses, the second passes a data table not under roles.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* feat(datatables): move the data table role catalog endpoints to the enterprise edition
The superadmin list, create, update and delete handlers move to
windmill-ee-private. The routes stay registered and, without the enterprise
edition, refuse after authentication.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* test(datatables): run the roles tests on the enterprise edition, refusals without it
Each test that exercises roles runs with private and enterprise. Two tests run
without them: every roles route answers the Enterprise refusal, and a data
table saved under roles, or a named role, is refused a connection while one
not under roles resolves as before.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* feat(datatables): gate the roles UI mount sites on an enterprise license
Both mount sites are still commented out; the gate travels with them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* test(datatables): run the tenant matcher test on the enterprise edition
The matcher it covers is enterprise code now, so without the enterprise
edition the test hit the stub and failed the default windmill-common run. It
runs with private and enterprise, and a counterpart without them asserts that
no tenant list covers anyone, the wildcard and a workspace admin included.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* chore: update ee-repo-ref to a1873dbb67f2302b85ff5362f8387b48eccdb607
This commit updates the EE repository reference after PR #783 was merged in windmill-ee-private.
Previous ee-repo-ref: 5c853e2c20eca6b748415fc0d6862a6ebfb5fec4
New ee-repo-ref: a1873dbb67f2302b85ff5362f8387b48eccdb607
Automated by sync-ee-ref workflow.
* fix(datatables): refuse roles while a same-workspace alias reaches the database
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat(datatables): add an ACL editor for data table roles
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat(datatables): data table roles in the DB manager and raw apps
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: never add a role to the reference of a data table whose name contains '?'
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: read the roles of a data table whose name contains '?'
The generated client leaves a '?' in a path param unencoded, so the lookup
404'd and the raw-app picker blocked Start on such a data table.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: take every pooled connection before the ACL apply locks
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BRoYE5ZeAVvrDYdfhDAYXb
* fix: refresh grant options only after the ACL apply validates its plan
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BRoYE5ZeAVvrDYdfhDAYXb
* fix(datatables): refuse a reference naming both a legacy data table and a role
When a workspace stores both `sales` and a legacy `sales?role=analytics`, the
reference resolved to the legacy entry without a role, so browsing `sales` as
`analytics` reached another data table.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: declare the default role in migrations written for a data table whose name contains '?'
Such a data table connects as its default role without naming it, so the
migrations the manager wrote for it declared no role and ran as admin.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(datatables): let CE migrations connect as an explicitly named admin
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: add only missing grant options before an ACL apply, never default privileges
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BRoYE5ZeAVvrDYdfhDAYXb
* fix(datatables): serialize roles going on with aliases saved from other workspaces
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs(datatables): note that legacy names with ? cannot be migrated
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: run one data table ACL apply at a time per server before it connects
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BRoYE5ZeAVvrDYdfhDAYXb
* feat(datatables): set up an external instance cluster for data tables
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(datatables): send external cluster passwords as SCRAM verifiers
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(datatables): scope external cluster credential readers to the crate
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* [ee] feat(datatables): external_instance data tables on the external cluster
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: hold the ACL connection to the database that was authorized
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BRoYE5ZeAVvrDYdfhDAYXb
* fix(datatables): compare the external cluster settings under a row lock before storing setup
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(datatables): only drop external databases Windmill marked, and check use under the lock
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: build the ACL connection from the authorized data table entry
Resolving the settings again could land on a resource with the same
database name on another server, which the later entry checks never see.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BRoYE5ZeAVvrDYdfhDAYXb
* fix: check ACL read reach against the entry it connects from
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BRoYE5ZeAVvrDYdfhDAYXb
* feat(datatables): put a data table's connection under Postgres roles
A data table backed by the instance database resolved to exactly one Postgres connection,
`custom_instance_user`, for everyone who could reach it at all. There was no way to say
this job reads, that one writes, this one never sees the salaries table.
A data table role is now a real Postgres login on the cluster, defined once for the
instance by a superadmin and named exactly as they named it. A script that declares
`-- role analytics` connects as `analytics`, and Postgres decides what it may touch —
grants are ordinary SQL. Windmill answers only "may this caller ask for this role", from
the tenant lists on the data table entry: `u/alice`, `g/analysts`, `f/finance` or `*`.
A data table with no `permissions` block behaves exactly as before.
Everything that opens a connection on someone's behalf goes through one chokepoint,
`get_datatable_resource_from_db`, which takes the identity explicitly and fails closed when
there is none. The role logs in as itself — never `SET ROLE`, which a script could
`RESET ROLE` its way out of.
A fork's data table entry becomes a pointer at the workspace that governs it rather than a
copy of it. The settings clone used to hand a fork a byte-identical entry naming the
parent's database, which a fork admin could edit to grant themselves `admin` there; a
pointer has nothing local to edit, and its tenants are evaluated as a member of the
governing workspace, by email. `permissions` is stripped from the workspace export and
ignored on import: tenants name principals of one workspace, and a settings push is not
where an access decision should be made.
Operations that see the whole database whatever the roles grant stay with the governing
workspace's admins: editing the roles, a migration that declares none, and opening a
replication stream for a Postgres trigger or capture.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): gate the paths that reach a whole database as admin
Auditing what still resolved through the unchecked resolver turned up three that act for a
caller and hand back the admin connection: `resolve_pg_source_checked` (behind schema
export, the full-schema read, database creation, import and the forked-database drop), the
connection test, and the schema snapshot a fork clone takes of its parent. On a data table
under roles each let any workspace member — or a fork admin who is nobody in the governing
workspace — read or copy the whole database whatever its roles grant.
All three now require admin reach on the governing workspace. A dump taken under a
restricted role would be a silently truncated copy rather than an error, so refusing is the
only right answer for the copy paths.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): confine roles to the instance database, and stop a fork reaching the parent's bookkeeping
A data table role is a login on Windmill's own Postgres. Nothing stopped a workspace admin
putting a *resource-backed* data table under roles, at which point the executor dialled the
host that resource names — one the admin chose — with the role's real cluster password, and
`CONNECT` is granted to every registered instance database. Both ends now refuse: the
permissions endpoint rejects the save, and the chokepoint refuses to substitute credentials
on a non-instance entry rather than trusting the record it read.
Two more places reached the governing database without answering to it. The initial-migration
generator returned a `pg_dump` of the whole schema to any member. And the migration
rename/delete cascade followed a fork's pointer into the parent, so a fork admin renaming or
removing their own local entry relabelled or wiped the parent's `_wm_migrations` — after
which the parent re-runs every migration from zero. The remote half is now skipped when the
entry resolves into another workspace, which is also just correct: a fork renaming what it
calls a data table changes nothing about the data table.
Also: revoking a tenant now bounces the replication streams of every workspace holding an
entry that resolves here, not only the governing one, so a fork's trigger stops rather than
living on inside its open connection; the instance role catalog and the governing workspace's
tenant lists are no longer returned to someone who cannot edit them; and the tenant rename
dedup collapses non-adjacent duplicates, per role rather than once any role changed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): fail loudly where a role or a pointer can be left half-recorded
Three ways the feature could end up in a state nobody could see or undo.
Creating a role writes the cluster first and the catalog second, but the catalog write was an
`UPDATE` that matched nothing when the instance Postgres settings row was absent — leaving a
live login with a password nobody recorded: invisible to the catalog, un-recreatable because
the name is taken, and un-deletable because there is no entry to delete. It now errors, so
the operation is retryable once the row is restored.
Deleting a workspace only nulls the fork lineage; the data table entries pointing at it are
left resolving to nothing. Sweeping them is not an option — turning a pointer back into a copy
would hand each fork the database outright — so the delete now names the data tables it
stranded, and resolving one says which workspace is missing rather than reporting a data table
this workspace never had.
`InstanceDatatableRole` derived `Debug` while holding a Postgres password; it is now
hand-written so `{:?}` on the catalog cannot put a live credential in a log line.
Adds the two branches the reviews found unpinned: a caller who is not a member of the
governing workspace at all, and `NoIdentity` — the compatibility path for an agent worker that
predates this and sends no job id.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): unbreak two operator messages and two comments that described other code
The two strings this branch added for states an operator hits once — the catalog write that
matched nothing, and the delete that stranded a pointer — were collapsed from their multi-line
form with the indentation left in, so both rendered with a fourteen-space gap mid-sentence.
`list_datatables` claimed to report a chain it cannot follow and then dropped it; it does drop
it, and the comment now says why that is the right place to stay quiet. The non-superadmin
check in `edit_datatable_config` was introduced as also covering references, which it does not
and need not: `reference` is overwritten from the stored entry for every caller before the
check runs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): serialize role catalog mutations, and state each helper's authorization contract
The catalog is one JSON document, so create, rename, enable and delete are all
read-modify-write. Two concurrent creates read the same snapshot, both succeed in the
cluster, and the second write drops the first — leaving a live Postgres login with a password
nobody recorded, which is the exact state the delete path exists to prevent. Every mutation
now runs in one transaction holding an advisory lock across the read, the cluster DDL and the
write, so a lost update cannot happen and a failure rolls the whole thing back. The DDL
helpers take that transaction rather than the pool, which is what makes the lock cover them.
Their statements moved off `sqlx::raw_sql`: the simple protocol is only needed for genuinely
multi-statement SQL, and its future is not `Send`, which an axum handler holding the
transaction requires. Each of these is one statement anyway.
The new cross-crate surface now says what callers must do. `read_role_catalog` returns
plaintext credentials; `create`/`rename`/`set_login`/`drop_instance_role` and
`converge_connect_grants` mutate cluster-wide state; `read_datatable_entry` reads a workspace's
raw config. All of them are superadmin-gated by their current handlers, but nothing said so at
the definition, which is where the next caller looks.
Also: the roles table reloads after a failed login toggle instead of leaving it claiming a flip
that did not land; the rename affordance is the design-system `Button`, not a raw one; and
`resolve_datatable_pg_as_caller` drops a `role` parameter no caller ever filled — browsing
resolves as the data table's default until the database manager grows a picker.
Why role passwords stay a plain `String` while the instance user's password beside them is a
`StringOrSecretRef`, asked three times across reviews: that one is a secret ref because an
operator supplies it and may want it from their own backend, while these are minted here and
never entered by anyone, so there is nothing for a ref to point at. Encrypting generated
secrets at rest is a separate change that would take the replication password with it. Now
said at the field.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): give the role catalog its own row, out of reach of the config machinery
Putting it inside `custom_instance_pg_databases` was the wrong call, and it cost two ways.
The catalog serializes a generated Postgres password per role, and that row is the
operator-facing instance config, so the passwords reached `get_instance_config` and its YAML
editor — a live cluster credential in a response body, a UI field and any log of either.
Worse in the other direction: `to_settings_map` strips the catalog, so a full-row upsert of
that key writes the row back without it and the catalog is gone, while the cluster keeps every
login it described.
`custom_instance_replication_pwd` is the precedent and says exactly why — a generated secret,
written only by the server, never operator-authored, hidden so the config machinery cannot
read, rewrite or drop it. The catalog is the same thing, so it now has the same shape:
`datatable_roles`, in `HIDDEN_SETTINGS`, `PROTECTED_SETTINGS` and the agent-worker denylist.
No redaction to keep in step with three code paths, and no way for a neighbouring write to
take it out.
Two races on the same shared documents. `edit_datatable_config` read the stored data tables
outside its transaction and then wrote the whole `datatable` document, so a permissions save
committing in between was silently rolled back; it now reads under `FOR UPDATE`. And
`set_datatable_permissions` validated role ids against the catalog before opening its
transaction, so a deletion in between let it write a deleted role back — including as the
default, which every later job then fails on; it now holds the catalog lock and the settings
row across validation and write.
Completes the authorization contracts the previous commit claimed but did not finish:
`read_datatable_entry` (which it named and missed), `resolve_governing_datatable`, whose whole
job is to answer for a workspace the caller may not belong to, and
`converge_connect_grants_with`, which had not inherited its wrapper's.
Also the generic Python SDK reference: `_format_py_params` learned the bare `*` last time, but
`extract_py_functions` is a second formatter and still rendered `datatable(name, role)`, so
code written from that page passed a keyword-only argument positionally.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): make the concurrency test pin the handlers, and the contracts describe what is enforced
The concurrency test reimplemented the read-modify-write inline, so deleting the lock from all
three handlers left it green — it pinned Postgres, not the code it was written for. It now
drives `create_datatable_role` twice concurrently and asserts the catalog kept both names.
Checked the way the last one should have been: removing the lock from the handler makes it
fail with "wmtest_a_… is a live cluster login the catalog forgot".
The contracts added last commit were stricter than this PR's own callers, which is worse than
none — the next reader sees a rule already broken and learns to ignore it.
`read_role_catalog` said superadmin-only while two of its four callers are open to any
workspace member, and `converge_connect_grants` said superadmin while
`set_datatable_permissions` reaches it as a workspace admin. Both were fine on substance: the
rule that actually holds is about the credential never reaching a response, log, audit record
or export, not about who may call. They now say that. `read_datatable_entry` gets the same
treatment rather than the one the earlier message claimed for it: it is the primitive every
resolution goes through, so it is deliberately open, and what must not escape is `permissions`
— it names the governing workspace's users, groups and folders.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): close the last ways a role or a pointer can be left pointing at nothing
The raw settings readers hand back whatever is in the row, so moving the catalog into its own
`global_settings` key protected the config machinery and left `GET /settings/global/datatable_roles`
and the settings listing returning every live password. Both now filter that one key. The
neighbouring `custom_instance_replication_pwd` has the same shape and is not touched here: it
predates this and widening the fix to it is a decision about an operator workflow, not a
consequence of this change.
Three ways a save could leave something resolving to nothing:
A permissioned data table could be moved to a PostgreSQL resource. The block was carried across
as a server-owned field, the runtime refuses roles on a resource-backed table, so the save
succeeded and every job afterwards failed. Refused instead — turning roles off first is one step,
and it keeps discarding an access decision something somebody chose.
Renaming a governing data table left every fork pointing at the old name: the data table
disappears from their pickers and their jobs stop, with nothing in the renaming workspace to
suggest why. The rename now follows into the pointers in the same transaction.
Deleting one cannot be followed the same way, so it is reported instead — the response names what
it stranded, the way deleting a workspace does, and the fork's own error already says which
workspace is gone.
Also: `ensure_instance_db_grant_options_unchecked` claimed superadmin while the permissions
handler reaches it as a workspace admin (the same class fixed last commit, one instance missed);
the role entry kept an `instance_config_schema` derive it no longer needs; `write_role_catalog`
was the one writer of that table not stamping `updated_at`; and the concurrency test dropped its
roles only on success — a failing run is exactly the one that creates them without recording them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* refactor(datatables): put the role catalog in its own table, not in global_settings
Five findings across three rounds were all the same choice. A set of live Postgres credentials
was living in `global_settings`, which has generic read, list, write, config-export and CLI
round-trip paths that know nothing about what they carry: the passwords reached the instance
config and its YAML editor, a full-row upsert of a neighbouring key erased the catalog,
`GET /settings/global/{key}` and the settings listing returned them raw, and this round the
redaction that fixed the last two turned `wmill instance push` into something that wipes every
password — a fix breaking the assumption the previous fix made. `POST /settings/global/datatable_roles`
could also empty it outside the lock.
The approved plan offered a table or `global_settings`, so this is the other option it already
allowed rather than a new design. `datatable_role` is a table: no generic settings path can read
it, list it, export it, write it or round-trip it, so none of the five needs a guard. The
redaction, the hidden/protected/agent-denylist entries and the JSON document all go with it.
One row per role also removes the read-modify-write the concurrency work was about: two
concurrent creates are two inserts, and the unique index on `name` is what settles a collision.
The advisory lock stays for the one window rows do not cover — `CREATE ROLE` is invisible to
another transaction until commit, so without it both creates pass their `pg_roles` check.
Also from this round: rename mappings are checked against the configuration they claim to
describe, since fork pointers are rewritten from them — a caller could otherwise submit
`main -> missing` against an unchanged config and repoint every fork of `main` at a name nothing
has, and `A -> B` plus `B -> C` moved what pointed at `A` all the way to `C`. And the warning
naming forks a delete stranded reached the response but not the screen: both the data table
settings save and the workspace delete now show it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): validate a rename against the save it describes, and re-check under the locks
Three from the round, all about deciding on state that could already have moved.
A permission save resolved the data table and checked it was instance-backed before taking any
lock, then wrote under one. A config save committing in between could move the table onto a
PostgreSQL resource — recreating exactly what the transition guard refuses — or rename it, in
which case the write targeted a key that no longer existed and reported success having changed
nothing. It now re-resolves and re-checks on the locked state.
Rename validation checked that the source existed before and the target existed after, which
still accepts `main -> decoy` against a save that keeps both: every fork of `main` then follows
onto a different data table, silently, because it keeps resolving. The rule is now the actual
old-to-new key transition — a source may only survive if another rename took its name, and a
target may only pre-exist if another rename freed it. That also stops two sources sharing one
target, and it admits a swap, which the previous guard refused: `datatables` is keyed by name, so
a swap cannot be done one save at a time, and refusing it was a regression against main. The
pointer cascade now runs in two passes through a temporary name, the way the migration cascade
one layer down already handles the same shape, so `A -> B` with `B -> C` moves each pointer once
from what it named before the save.
The tenant mutators say what they are for: they write an access decision for any workspace named,
with an arbitrary mutation, and exist for the transaction that frees or renames a principal.
Editing a decision on purpose belongs in the permissions endpoint.
Carried in the same change: the stranded-fork list is a field rather than a phrase to grep out of
a success string; the pointer cascade matches with `EXISTS` instead of a `LIKE` over the whole
document, so a workspace whose pointers name something else is not rewritten to a byte-identical
value under an exclusive lock; and `InstanceDatatableRole` drops the serde derives left over from
the JSON document, one of which would emit `pwd`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): cascade on the leave route that is used, gate migrations before the admin connection, and drop a role atomically
The tenant cascade on leaving went onto `/users/leave`. The UI and the generated client call
`/workspaces/leave` — a different handler in a different crate with the same name — which
deleted the membership and left `u/<username>` in the tenant lists. Leaving and rejoining
therefore restored the access the leave was supposed to end, and a later account taking the
username would have inherited it. The regression test drives the route the client actually
calls; without the fix it fails with "leaving kept the tenant".
The migration endpoints authorized too late. `run_datatable_migrations` opened the data table's
admin connection, created `_wm_migrations` and read it before reaching the per-migration role
check — so with nothing pending, nothing was checked at all. Rollback returned before its check
when nothing was applied, and the status endpoint had none. All three now ask, before any
connection is opened, whether the caller can reach the data table as any role at all; which role
a given migration runs as is still decided per migration, and by the executor after that.
Deleting a role committed the cluster drop and the catalog row, then swept the tenant lists in
separate transactions. A sweep failing part-way left workspaces naming a role nothing can connect
as, while the retry answered `NotFound` because the catalog entry was already gone. The sweep now
runs in the same transaction, so the drop, the row and every tenant list commit together.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): refuse to copy a data table that is under roles
pg_dump carries no roles and the import runs with --no-privileges, so a copied
data table arrives owned by the admin connection with no GRANT for any role.
The settings clone brings `permissions` across, so the fork's tenants pass
Windmill's check, connect as the role they were given, and are denied by
Postgres on everything: an entry that reads as configured and answers nothing.
Refuse the copy — in the import endpoint before any data moves, and in the fork
path the CLI takes. Replaying the source's owners and ACLs into the clone is
what lifts this, and is a change of its own. Dropping `permissions` from the
copy instead would be the unsafe half, since the copy holds the parent's rows.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): refuse the clone's database too, not only its data
A clone is two endpoints: `create_pg_database` then `import_pg_database`. Only
the second refused a data table under roles, so a fork asking to clone one
created and registered an empty `wm_fork_…` instance database and then failed —
and nothing collects it, since `drop_forked_datatable_databases` only drops
entries carrying `forked_from` and no entry names this one.
Refuse in both, so the clone stops before a database exists.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* nit worker error msg
* fix pg_dump stuck on version 17 on nix
* fix(datatables): refuse a malformed role annotation instead of ignoring it
`-- Role operator`, `-- role operator;` and `-- role operator -- why` all failed
the annotation parser's exact-match rule, so the query fell through to the data
table's default role and ran, silently, under a login the author did not choose.
Naming a role exists precisely to not do that.
A leading comment whose first word is `role` is now an annotation attempt: the
keyword matches case-insensitively, one trailing `;` is tolerated, and anything
else is an error naming the line. Only callers that already know the target is a
`datatable://` reference ever run this, so ordinary SQL keeps its comments.
Also bumps the dev shell's postgres client to 18 — it trailed the server the dev
database runs, which takes out every data table export, clone and fork-with-data.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): refuse a malformed role query string instead of ignoring it
`?Role=analytics`, `?role=` and `?x=1&role=…` all fell through the reference
parser's exact-match rule, so the connection resolved to the data table's default
role and ran under a login the caller never asked for — the URI half of the same
trap as a malformed `-- role` annotation.
The key now matches case-insensitively, and anything else in the query string is
an error naming it; `role` is the only parameter a reference takes. Callers that
only need the entry keep a lenient `datatable_ref_name`, since they never act on
the role. The DuckDB `ATTACH` parser propagates it rather than attaching under
the default.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
* fix(datatables): carry the role annotation into the row_to_json retry
The retry rebuilds its SQL from `pruneComments(code)`, so the leading comment
block never reached the second attempt — and with it the `-- role <name>` line
that decides which login the query runs as. The retry connected as the data
table's default role instead, so a query the first attempt was denied could
succeed on the second, reported as "recovered with the row_to_json fix".
Carry the leading comment block over. The retry itself is unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* chore(datatables): don't mount the roles UI until the ACL editor lands
Enforcement ships first. The permissions drawer is what turns roles on, and the
catalog section is what creates them — both are only useful once there is a way
to grant a role the privileges it needs, which arrives with the ACL editor. Left
mounted they would offer a feature whose other half does not exist.
The two components are complete and reviewed; only their call sites here are
commented out, with a note pointing the follow-up PRs at them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* fix(datatables): honour `-- role: x`, and fix the DuckDB attach test
Two review findings, both real.
`attach_datatable_parses_name_and_role` never compiled: `parse_attach_datatable`
returns `Result<Option<_>>` now and one call site kept a single `unwrap`. Its
`?Role=analytics` case also asserted a refusal, contradicting the parser in the
same commit, which matches the key case-insensitively. Replaced with the cases
that are genuinely malformed, and a positive one for the cased key.
`-- role: analytics` fell through to the default role — the silent fallback the
strict parser exists to remove, for the spelling most likely to be typed. The
keyword now accepts an optional colon, attached or spaced, while a word that
merely starts with it (`rolebased`) is still not an attempt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* fix(datatables): clone a fork's pointer instead of failing after the copy
Forking a fork with cloning left an orphan database. The preflight resolves the
pointer and sees the governing entry, so both endpoints ran and filled the new
database; `apply_forked_datatable` then refused the inherited pointer and rolled
the fork back, stranding a registered `wm_fork_*` that no entry names and whose
name blocks the retry.
Refusing earlier would have been the smaller change, but forking a fork and
cloning worked before pointers existed, so it would trade an orphan for a
regression. Resolve what the pointer names and write the terminal entry the
clone needs: the whole `database` object rather than a patch of its
`resource_path`, since a pointer has none, and `reference` removed with it.
Also accepts `-- role=x` and `-- Role = x`, two more spellings that fell through
to the default role.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* fix(datatables): refuse to roll back the catalog while roles exist
The down migration dropped the table and left every role behind: live Postgres
logins whose passwords only that table carried, so after a revert Windmill could
neither use, disable nor delete them, and re-applying could not recreate them
because the names were taken. Cleaning up here is not possible either — dropping
a role means reassigning what it owns in every instance database, and a
migration runs in one — so it now refuses while the catalog is non-empty and
says to delete the roles through instance settings, which does the cluster work.
Also enforces the instance-only invariant the resolved-pointer clone relies on
rather than only asserting it in a comment.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* refactor(datatables): settle clonability in one place, before anything is created
A clone is three stages a workspace apart — `create_pg_database`, then
`import_pg_database`, then `apply_forked_datatable` inside the fork transaction.
Only the third can roll back, and `CREATE DATABASE` is not transactional, so any
refusal that lives there strands a registered `wm_fork_*` that no entry names
and whose name blocks the retry.
That orphan has now been fixed three times, most recently reintroduced by a
guard added one commit ago. Patching each new refusal into the first endpoint is
not the fix; having two places that can refuse is. `ensure_datatable_is_clonable`
now answers every reason a copy can be refused and returns what it resolved, and
the stage that writes the entry only does the work.
Also takes an ACCESS EXCLUSIVE lock before the rollback guard counts, so a role
created concurrently cannot slip between the check and the drop.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb
* fix(datatables): let a retried clone reclaim its own leftover database
A clone creates its target database one request before it copies into it, and
the fork that would name it is written a request after that. Any failure in
between — a pg_dump error, a bad restore, a dropped connection, the source's
roles changing mid-flow — left a registered `wm_fork_*` that no entry names,
and every retry then failed on its name. This predates data table roles.
`create_pg_database` now reclaims such a leftover before creating: only a
`wm_fork_*` database Windmill registered as a data table database and that no
data table or ducklake entry names, in any workspace, archived ones included.
The drop never terminates connections, so a clone still copying into it makes
the reclaim fail instead of being cut off. It is limited to callers who
administer the source — reaching it is not enough, since on a data table
without roles every member reaches it — and anyone else gets the refusal an
existing database always got.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Revert "fix(datatables): let a retried clone reclaim its own leftover database"
This reverts commit
|
||
|
|
235410c1e4 |
feat: show native web search in the assistant settings modal (#11394)
* feat: show native web search in the assistant settings modal Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UeyhSVDKENUzX8gKj5UXYE * refactor: clarify provider tools subscriptions and give their test its own group Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UeyhSVDKENUzX8gKj5UXYE --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c5f59d6ccc |
fix: drop caller-supplied _MODULES at push for every job (#11418)
* fix: drop caller-supplied _MODULES at push for every job Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: never interpolate _MODULES into a tag and drop unused mut Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
bb12bc766c |
serve the parser wasm in the vitest bridge (#11420)
* fix(ai_evals): serve the parser wasm in the vitest bridge The parsers behind inferArgs load their wasm from a vite ?url path that only a dev server answers, so every script draft in the global evals got an empty schema. test_run_script then told the model its arguments were undeclared, and gemini rewrote a correct script until it hit max turns. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ai_evals): match wasm urls past a base path and decode them Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ai_evals): decode wasm urls after the suffix check; fail the run when inference breaks Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
83b8954ae2 |
fix: turn the default raw app into a feature tour (#11417)
* feat: turn the default raw app into a feature tour Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: don't present ctx fields as unforgeable in the starter app Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: format raw app templates Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
05bcc361af |
stop billing service accounts twice after a session refresh (#11408)
* fix: stop billing service accounts twice after a session refresh Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: refuse refresh for expired, swept or impersonation tokens Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: update ee-repo-ref to 5a2b6b8527250bd12cf856d8a667a9ef3106ec60 This commit updates the EE repository reference after PR #835 was merged in windmill-ee-private. Previous ee-repo-ref: 8cc94ec6aeb603b6f6ebbe1fa95b32fbec074b74 New ee-repo-ref: 5a2b6b8527250bd12cf856d8a667a9ef3106ec60 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
d1260d7c5a |
feat: refuse OIDC tokens to previews that impersonate a path their user cannot write (#11396)
* feat: add provenance claims to job OIDC tokens and mark preview sub Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: require a flow or script job's version to belong to its path for deployed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: derive app script paths server-side and test job provenance in CE Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: count an app script as deployed only when a deployed app run stamped it Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: state the deployed condition for the preview sub prefix Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: keep the plain OIDC sub for previews by users who can write the path Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: refuse OIDC tokens to previews by users who cannot write the path Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: keep OIDC token issuance unchanged, leaving provenance to the claims Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: name the root job's trigger claim root_trigger_kind Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: report the request-supplied paths in a job's provenance Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: count a worker-pushed preview under deployed code as deployed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: drop the claimed parent of a restarted flow preview Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: only read a job's modules from its args when it is a preview Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: never count a preview whose modules came in its args as deployed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to dba91044a174f8c9275fefea2619dc966b0f9250 This commit updates the EE repository reference after PR #832 was merged in windmill-ee-private. Previous ee-repo-ref: a703cb17776d0858255fbfd817dce132377d3e80 New ee-repo-ref: dba91044a174f8c9275fefea2619dc966b0f9250 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
50ffad52d7 |
fix: surface raw app build errors to the session AI (#11415)
* fix: surface raw app build errors to the session AI Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: route app build state per preview and report pending builds Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: name open previews when app logs are ambiguous, re-wait on retry Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |