mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-13 16:02:59 +00:00
simplified-flow-view
9148
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
499b7c3fa2 |
fix: address simplified view review nits (collapsed group steps, selection placeholder)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
e2369103be |
fix: address simplified view editing review findings
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
da1c1fe690 |
feat: show and edit groups in the simplified view
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
13d9ec652e |
feat: multi-select steps in the simplified view
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
931892d7c1 |
feat: edit steps from the simplified view (menus, insert, branches)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
27728ae895 |
feat: offer the simplified view in the flow editor
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
a7209d7cbb |
style: drop the simplified node icon badge and enlarge the icon
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
313b0bece9 |
fix: address simplified view review nits
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
0bed5d1845 |
feat: frame simplified node icons in a centered badge
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
1683bfbe26 |
fix: keep the simplified view out of diffs and share the graph selection
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
158fae46c1 | Merge remote-tracking branch 'origin/main' into simplified-flow-view | ||
|
|
5324d99562 |
feat: add a simplified left-to-right flow graph view
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
3974bbeac6 |
chore(main): release 1.818.0 (#11294)
* chore(main): release 1.818.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com> |
||
|
|
da866c5eff |
feat: alert on and optionally cancel jobs stuck on unserved tags (#11354)
* feat: alert on and optionally cancel jobs stuck on unserved tags Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: group stranded jobs in sql and recheck each job before canceling Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: guard stranded-job alerts and cancels against outages and pickups Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: count priority tags as served and retry lost stranded-job cancels Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: send one daily stranded-jobs alert that can be muted Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: cover native retries and finish lost stranded-job cancels unconditionally Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
9a1c6e5081 |
feat: let a workspace withdraw operator schedule and trigger writes (#11226)
* 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: 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: keep admin and operator exclusive when setting a workspace role Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: use the shared section component for operator settings groups Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
e14da5c6bc |
feat(bedrock): add OIDC role assumption as a fourth auth mode (#10936)
* feat(bedrock): add OIDC role assumption as a fourth auth mode Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YCVb91fZp3dqM14KRPzoEn * fix(bedrock): gate the OIDC cache correctly and assume the role once per job Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YCVb91fZp3dqM14KRPzoEn * refactor(bedrock): check the OIDC region before minting a token Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YCVb91fZp3dqM14KRPzoEn * fix(bedrock): keep OIDC session names collision-resistant, gate the copy on EE Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YCVb91fZp3dqM14KRPzoEn * fix(bedrock): check the OIDC region before reusing cached credentials Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YCVb91fZp3dqM14KRPzoEn * fix(bedrock): clear assumed-role sessions when AI settings change invalidate_ai_request_cache_for_workspace cleared AI_REQUEST_CACHE only, so a workspace's AI settings edit reset one cache and left the assumed-role sessions keyed on the old config in place until STS expired them. Also name the region requirement in the credentials-check hint, so following it does not land on the OIDC path's region guard. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YCVb91fZp3dqM14KRPzoEn * chore: update ee-repo-ref to de73db2bacfdc3eaa2e63b1827178bc198d54e5c This commit updates the EE repository reference after PR #770 was merged in windmill-ee-private. Previous ee-repo-ref: c43dab1e69b1cb3f685e6df07bff634dc2a0b734 New ee-repo-ref: de73db2bacfdc3eaa2e63b1827178bc198d54e5c Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
94e4fb1c84 |
fix: carry labels when deploying variables, resources and folders (#11222)
* fix: carry labels when deploying variables, resources and folders across workspaces Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: clear a folder's labels in the target when the source has none Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test: pin that the frontend deploy adapter carries variable labels Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
d3d5392917 |
feat: add an options field to the postgresql resource (#11223)
* feat: add an options field to the postgresql resource Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: keep a literal plus in postgres connection string parameters Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: pass postgres options to trigger connections Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: read DATABASE_URL options the way sqlx does Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat: include postgres options in databaseUrlFromResource Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f183bd43fb |
chore: retire the standalone lsp and multiplayer images from examples, drop lsp/Dockerfile (#11341)
* chore: retire the standalone lsp and multiplayer images from examples, drop lsp/Dockerfile Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: drop the unbuilt DockerfileMultiplayer, document running the LSP from windmill-extra Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(examples): ecs terraform destroys cleanly and gives private instances no public ip Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(examples): give windmill-extra on ecs a WINDMILL_BASE_URL for multiplayer auth, address review Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(examples): make the ecs example upgrade cleanly from the standalone lsp/multiplayer stack Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(examples): name the extra target group by prefix so create_before_destroy can replace it Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(examples): note the brief editor-socket gap when upgrading the ecs example Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(examples): the debugger stays off after the ecs upgrade unless enabled Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
3bd89e92d8 |
feat: collapse the fork members setting and show its state in a badge (#11220)
* feat: collapse the fork members setting and show its state in a badge Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: show the fork members badge next to the title, only when on, like other section badges Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
1d119e6b25 |
fix: correct the tool controls and name field of a nested AI agent (#11221)
* fix: hide tool controls a nested AI agent cannot use Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor: drop the tool navigation prop an agent tool now implies Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: ask for a tool name on every kind of agent tool Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: keep enabled_tools reachable on a linked nested agent tool Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs: name the tool kinds the header's name field actually renders Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs: state the tool-name rule without listing the kinds it covers Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
4fd7d62bd0 |
feat: rework the db manager: native grid, tabs, sql editor, joined columns (#11340)
* feat: replace ag-grid in the db manager table viewer with a native grid Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: add user-managed data, diagram and sql editor tabs to the db manager Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: add schema autocomplete to the db manager sql editor and polish its layout Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: add joined foreign key columns and draggable tabs to the db manager Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: move db manager tabs on drop instead of mid-drag Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: open followed foreign keys in a new db manager tab Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: scroll large tables, drop stale joins and return to the last tab on close Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: tolerate the db manager tabs going away while switching data table Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep saved joined columns while metadata loads, test joins in every dialect Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: put the db manager grid on the input surface in dark mode Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: address db manager review nits on joins, boolean keys and sql quoting Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep the dark border color on the left pinned column edge Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: tone down the db manager tree menu icons Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: write json and jsonb values from the db manager through a text cast Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: dim unrelated diagram tables less on hover Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: match json columns as text when deleting a db manager row Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: compare postgres json columns as text in exact db manager filters Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: pick the columns the db manager grid shows Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: toggle every db manager column from one checkbox Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: word joined columns as a view in the db manager Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: keep data table roles and access visible when unavailable, with the reason Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: keep data table and instance roles visible in settings when unavailable Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: hide a db manager column from its header menu Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: format db manager columns with a unit, significant digits and color rules Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: drop the before/after hints from the db manager unit picker Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: write the euro after the amount and keep units off non-numeric values Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: color rule presets, bold and italic, layered and reorderable rules in the db manager Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: decimals, thousands separator, compact notation and alignment in db manager column formats Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: compact db manager format controls, a notation toggle group and a reset button Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: db manager format and filter nits Keep the value's scale when decimals are auto, read boolean color-rule conditions as booleans, let a rule's text color reach foreign-key links, close the formatter when the columns picker opens, and filter BigQuery complex columns through TO_JSON_STRING. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
2e5f6d0e76 |
fix(frontend): keep the session when the persisted workspace is stale (#11344)
* fix(frontend): keep the session when the persisted workspace is stale A single-use login link signs a different account in while `workspace` in session/localStorage still names the previous account's workspace. `loadUser` read that workspace, got no membership back, threw `Not logged in` and logged the brand-new session out, landing on `/user/login?rd=...`. A missing membership says nothing about the session, so forget the workspace and continue down the no-workspace path, which logs out only when `globalWhoami` shows the session itself is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(frontend): confirm the session before the workspace-picker redirect `loadWithoutWorkspace` fired the `/user/workspaces?rd=…` navigation before awaiting `globalWhoami`, so when the session turned out to be gone the logout read whichever URL the race had left in `page.url` and carried the picker as its `rd`. Ask first, then redirect. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(frontend): stop the loadUser comments overclaiming what they know Neither comment can promise what it stated: `getUserExt` collapses every failure into `undefined`, so the branch cannot tell a real non-membership from a transient one, and `loadWithoutWorkspace` throws on any `globalWhoami` rejection rather than only on a dead session. Say what each call actually answers about. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
733c119fd9 |
feat: schedule hub scripts (#11330)
* feat: schedule hub scripts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test: pin hub script schedule push Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: retry scheduled hub scripts natively Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: address review nits on hub schedules Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: open the hub picker from the script select Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: use a subtle button for the hub row Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
421fdab3d8 |
fix: always save slack/teams/email handlers as scripts (#11345)
* fix: always save slack/teams/email handlers as scripts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: key the handler kind on the selected tab, not the hub/ prefix Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: recognise email recovery and success handlers when loading a schedule Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
4b09558e13 |
feat: start a deferred queued job now without changing its id (#11347)
* feat: start a deferred queued job now without changing its id Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: refuse starting a schedule's upcoming tick early Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: hide run now on upcoming schedule ticks and register its audit op Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
245628210f |
perf: skip parent status write when a parallel loop iteration starts (#11348)
* perf: skip parent status write when a parallel loop iteration starts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep the loop viewer off the parent job while a parallel loop runs Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: state what a parallel module's job would hold Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * perf: test the parallel module with one containment check Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
d18d7043df |
feat: infer a script's schema when a deploy (e.g. MCP) sends none (#11339)
* feat: infer a script's schema from its code when a deploy sends none Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: merge an inferred schema into the previous one the way the editor does Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: parse non-JSON TS defaults natively and keep the schema on a failed inference Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: type untyped TS params from their literal shape when the default can't be evaluated Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: read literal TS defaults off the AST so the server types them like the editor Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: word the script schema description for both create and update Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: note that dbt scripts derive their schema from the descriptor Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
1fd729ac1a |
feat: add an instance-wide accent color setting with sidebar tint (#11335)
* feat: add an instance-wide accent color setting with sidebar tint Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: paint the cached accent before the license resolves Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: serve the banner and accent color from one cached endpoint Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: invalidate the instance ui cache and bound it with a ttl Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep the instance ui ttl under the client poll period Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: load the banner and accent color once per page load Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: read the banner and accent color without a server cache Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: show a cleared accent color as off Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
ebb3048ca0 |
feat: mount session list pages in process instead of iframes (#11289)
* feat: mount session list pages in process instead of iframes * fix: seed filter defaults from the query, not the cached search params * fix: type trigger list rows from the generated trigger types * fix: judge hosted lists by the operating workspace's rules and keep role-gated filters * fix: keep the user folders filter key for every role, hidden where it does not apply * fix: drop the user folders filter for users it is not offered to * fix: wait for a known user before dropping the user folders filter * style: tint trigger rows for every kind and align the schedules footer wording * fix: stamp edited_at when a schedule is updated --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
d02ff9ac24 |
fix: centre the toggle knob inside its track (#11314)
* fix: centre the toggle knob inside its track The knob was positioned against the toggle's wrapper rather than the track, so its 2px inset resolved to a 1px gap inside the track's 1px border. On a 1x screen a toggle that lands on a fractional x blurs its edges across a whole pixel, which swallows that 1px gap and makes the knob look like it overflows the track. Position the knob inside the track's border with a 2px gap on every side, size the toggle in whole px so the 18px root font of large screens cannot make the track fractional, and give each size an explicit checked translate now that the knob is no longer exactly one translate-x-full wide. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: hoist the toggle knob's shared inset out of the size branches Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore(frontend): add a Toggles tab to the kitchen sink Covers the four sizes, the three colors, the label and EE-badge variants, and a grid of quarter-pixel offsets: the knob's gap against the track border only misreads once the track lands between device pixels. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
1b74939952 |
feat: support aiagent steps in test_run_step (#11321)
* fix: support aiagent steps in test_run_step Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: offer the agent's tools as a picker in the step run form Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: run a blank tool list as no tools when the step form is bypassed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
8525206361 |
fix: pass the schedule's custom tag when using run now (#11322)
* fix: pass the schedule's tag when using run now on a schedule Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep flow schedules on the flow's own tag for run now Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
98d3897b8c |
fix: hide answer actions until the chat turn ends (#11323)
* fix: hide answer actions until the chat turn ends Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep the last turn's answer actions during a manual compaction Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: note answer actions stay hidden while a turn waits on the user Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
2f2882adff |
fix: label chat job links with the end of the job id (#11324)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
c232ea43b4 |
fix: limit compare page guidance to fork deploys (#11300)
* fix: limit compare page guidance to fork deploys * fix: make open_page compare fork-only and drop stale api catalog bullet * fix: always open the compare page in fork mode from open_page * fix: drop the ignored mode argument from open_page |
||
|
|
80903c9a64 |
feat: per-folder AI chat instructions via ai_instruction resources (#11325)
* feat: give the AI chat per-folder instructions from ai_instruction resources Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: hold a change back until the model has read its folder instructions Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: find nested trigger paths and scope instruction deliveries by workspace Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: cap folder instructions per result and record holds as their own outcome Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: show a held call as its own row and cover group folders Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: state how folder instructions combine with workspace and user ones Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
504d01a563 |
feat: rework the git sync setup into a guided flow (#11308)
* feat: rework git sync settings into a flat repo list and setup modal Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: add the connect step for gitlab and github in git sync setup Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: open the github app install page from the git sync setup next step Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: let git sync setup set the repository folder Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: add the configure sync step to git sync setup Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: even out the git sync filter settings columns Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: pin the filter input to the bottom of the filter list Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: frame the git sync path filters in a box with an empty hint Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: use a multiselect for the git sync path filters Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: grey out the skipped connect step in git sync setup Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: move the check job line to the bottom of the setup modal Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: hide the check job line once the repository check resolved Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: center the repository check loader in the setup modal Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: stop the setup modal shifting when the check job id arrives Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: move the existing resource hint to the setup modal footer Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: always show the existing resource option when one exists Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: drop the card and collapse from the git sync filter settings Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: use a success alert for the pull from git notice Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: make initializing the repository a step of the git sync setup Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: hide the push job lines once they succeed Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: reword the push step intro Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: copy button on the cli snippet and a taller changes list Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: match the push step loading to the check step Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: stop the push step shifting when a job id arrives Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: let the changes list fill the push step Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: end the git sync setup on a done step instead of a modal Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: delete a git sync repository from a row menu with a confirmation Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: lift the git sync done message off the notices Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: restore github app installation transfer between instances Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: address regressions from the git sync setup rework Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: keep the overlay z-index floor in step with the ai chat Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: hold the push state in the setup dialog, not in the step it destroys Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: block every dismissal while setup work is in flight and keep sync reachable Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: regenerate the resource path when the repository changes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: configure the resource the connect step actually created Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: keep a modal open when a drawer above it takes the click Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: snapshot the topmost surface for keyboard clicks too Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: size the add repository buttons and explain git promotion Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * revert: drop the promotion-first action from the empty state Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: shrink the test connection result line Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: offer the fork sync and fork pull request toggles during setup Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: group promotion repositories under their own label Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: offer the deploy branch pull request toggle during setup Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: wait for the repository credential before saving the setup Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: ignore a superseded credential load and drop the bindable default Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: key setup readiness to the repository it was loaded for Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: tie setup readiness to the attempt that asked for it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: link to where the access token is created Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: say plainly how each provider connects Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: sync resources, variables, schedules and triggers by default Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: use the accent colour for the token help link Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * style: move the CI/CD deploy hint next to the pull toggle Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: keep setup gated when the connection could not be read Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: only explain pull-from-git where the workspace can turn it on Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: offer a save retry once the repository is initialized Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: say when pulling fell back to polling on the last setup step Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: clear the initialized flag when a new draft starts Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
6cd70a8e08 |
feat: filter ai session tools to the user's workspace capabilities (#10719)
* feat: filter ai session tools to the user's workspace capabilities Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: correct and tighten comments on the session capability filter Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: gate session deploy tools on DisableDirectDeployment and the pipeline prompt * fix: gate create_folder on the deploy capability * refactor: assemble session prompt and tools through one seam * docs: state the capability filter as best-effort, not a guarantee * refactor: take the whole deploy gate from the shared preflight `checkDeployPermission` now evaluates `DisableDirectDeployment` and folds superadmin into the admin bypass itself, so the resolver's local composition of those two terms is redundant. Delegate outright and drop the protection-rule fetch it needed, along with the two tests that restated rule semantics the preflight's own suite now pins. The preflight's per-kind narrowing stays unused: the filter runs on tool names, before the model has named a kind, so a direct-deployment lock withholds the deploy tools for schedules and triggers too. * fix: address review findings on the session capability filter Six findings from the Claude and Codex review rounds. - `discard_local_draft` is ungated. The backend exempts discarding your OWN draft from `require_can_write_path` precisely so drafts stay cleanable after a role change; gating it stranded that cleanup. - `deploy` splits into `deploy` and `deploy_gated_kinds`, mirroring `deployPermissionForKind`. A direct-deployment lock stops only the kinds that reach `check_deploy_rules`, so schedules and triggers stay deployable and the two kind-taking deploy tools survive the lock; `create_folder` does not, folder being a gated kind. The prompt now names the lock and what it leaves deployable, instead of implying nothing can be deployed. - `COVERED_ENDPOINTS` keyed `createApp` / `updateApp`, which the MCP catalog does not expose; the app-authoring endpoints it does expose, `createAppRawSource` and `updateAppRawSource`, were uncovered and reachable through `call_api_endpoint`. - The YOLO tooltip listed tools a restricted session never ships. Both it and the token estimate now read one `shippedTools`, and `sessionAccess` is reactive so the UI follows the resolution. * fix: restore the covered API-catalog names for the raw-app endpoints `COVERED_ENDPOINTS` is matched against `EndpointTool.name`, which openapi.yaml overrides with `x-mcp-tool-name` for these two operations: `createAppRawSource` and `updateAppRawSource` are served as `createApp` and `updateApp` (`mcp/auto_generated_endpoints.rs`). Keying them by operationId left both raw-app POST endpoints discoverable and callable through the API catalog tools. Restore the exposed names and record why they differ from the operationIds. * docs: state each capability invariant once, and document the draft discard The asymmetric admin/operator precedence was restated three times in sessionAccess.ts and again in its test, the fail-open rationale twice, and the deploy split across four sites. Each now lives at the one place someone would break it, within the four-line budget, with the other sites pointing at it. Ungating discard_local_draft left it undocumented for the read-only profile, which is the profile the backend exemption exists for: the only bullet naming it sits under the draft-writing gate, beneath an opener saying no change is possible. Add the one line that profile needs. * docs: record why the session tool filter runs unconditionally The filter would strip everything from a non-GLOBAL toolset, whose names carry no policy entries. That cannot happen — `changeMode` refuses to move a session chat out of GLOBAL, and `sessionAccess` is only ever set for session chats — but the dependency was not visible at the filter itself. * fix: match the server's deploy gate exactly, never exceed it The filter must be as strict as the server and no stricter. Schedules and triggers reach no deploy rule — `check_deploy_rules` runs only from the gated kinds' handlers — so no workspace refuses `deploy_workspace_item` or `delete_workspace_item` outright, whatever refusal `checkDeployPermission` reports. Gating them on a deploy capability withheld operations the server performs. Neither tool now requires a capability. Deploying still needs a draft to deploy, so it keeps the authoring relevance; deleting a deployed item does not, so it is ungated. `deploy` returns to one capability, covering the kinds the rules gate, and `create_folder` — whose kind is one of them — is the only tool that names it. The session-state note now states which kinds a refusing workspace still accepts. * feat: gate the new app-runnable preview tool on run_preview Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: fail open when whoami resolves without a role Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: count plan-mode tools in the shipped toolset Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * docs: drop the dead capability assertion and the repeated deploy rationale Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * refactor: drop dead code and a duplicated invariant from the session filter Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * refactor: reduce SessionAccess to the capability set it is read for Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * refactor: gate session tools on permission alone, never on relevance Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * test: pin the filter to the outbound request and widen the description sweep Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * refactor: collapse SessionAccess to a capability set and merge adjacent gates Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: gate get_db_schema on run_preview, it runs a query script Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: reuse the cached workspace role and derive the exhaustiveness list from assembly Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * revert: keep tool names in descriptions that ship with them Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: let an admin who is also an operator deploy, as the server does Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: derive the deploy capability from the protection rules alone Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: stop the datatable instructions naming a tool a session may not have Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: keep the prompt and tool results honest for a profile that cannot draft Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * refactor: move tool policies onto the tools and gate kinds per handler Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * chore: tighten stale comments and name deploy in the operator prompt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: keep the assembled tool list raw so narrowing can clone its defs Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: point an operator at a workspace admin for code the role refuses Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * fix: resolve session permissions when the assistant settings modal opens Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L99mAR4LitqTcYY1Kn1ATH * refactor: return per-chat tool schemas instead of writing them to shared tools Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: forward this through the eval tool wrapper so tools see their sent def Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test: pin identity and contents in the session filter and schema tests Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: note why the overhead estimate skips per-chat tool schemas Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0e53d53b07 |
fix: space chat rows evenly after thinking and answers (#11315)
* fix: space chat rows evenly after thinking and answers Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep a flow step's answer actions and space its step label Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: pick the answer that shows actions from later answers, not the next row Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: group answer actions by the step run's job, not its label Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: state the per-run action row rule in AssistantMessage comments Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
62d0088de5 |
feat: show restart from failed step in run page top bar (#11317)
* feat: show restart from failed step in run page top bar Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep failed-step restart button when selection is not restartable Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: add restart link to the failed run status line Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: use the input error color for the progress bar error state Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: mention restarting on a fixed flow version in the error line Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: show a chevron on the restart button when it opens a picker Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: shrink run page top bar buttons so the bar fits on one line Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: target the step that failed the run, not a tolerated failure Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: address review nits on the restart link Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: skip canceled runs and match the restart link label to its text Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
5b03c1732e |
fix: build ag grid link cells as DOM nodes with a vetted href (#11316)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
1de54eeea4 |
feat(ai-chat): show native script edit diffs (#11278)
* feat(ai-chat): show native script edit diffs * fix: render streamed edit diffs * fix: render in-editor script edit diffs * style: soften diff context separators * fix: render full script update diffs * fix: support empty script diffs * fix: bound streamed tool diffs * fix: preserve trailing diff context * fix: defer collapsed tool diffs * fix: retain full-code streaming previews * fix: preserve created script diffs * fix: disambiguate collapsed diff keys * fix: render final newline diffs * fix: preserve multiline diff highlighting * fix: highlight diff sides as complete sources * fix: bound completed tool diffs * fix: diff large completed tool edits Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: bound tool diff rendering Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: bound tool diff highlighting and expand omitted rows Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: reveal omitted diff rows in chunks and bound long-line highlighting Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: collapse written scripts, skip empty diff bodies and fit line numbers Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep whole-file tool diffs collapsed while running Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: classify whole-file tool calls by argument shape Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: reopen failed diff cards and keep empty streamed replacements Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
fa0fc24269 |
feat: render a tool's web search result as the session web search card (#11313)
* feat: render a tool's web search result as the session web search card
Any tool whose result is exactly `{ sources: [{ url, title? }], query? }`
now renders as the card the AI session shows for a provider-side web
search, in the agent step trace and in the flow chat. The provider-side
search itself gets the same card on both surfaces: its citations, which
the worker records on the assistant turn that follows, move onto the
search row.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: keep the trace tool label off the lazily fetched job
The web search card's label read the tool's job, which is only fetched
once the row is expanded, so the query suffix appeared only after the
row had been opened. The shape of the result decides the label; the
job's failure still decides whether the sources or the error show.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: keep unrenderable sources and tool hostnames out of the search card
A result whose urls the card cannot render — relative, or javascript: —
matched the shape and replaced the tool's own output with an empty list,
so the predicate now requires what the renderer accepts. A tool's sources
can name internal services, so they no longer resolve a favicon through
Google's service; provider-side search results still do. An absent
optional reaches JSON as null from a Python tool, which now reads as
absent rather than rejecting the whole result.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: name the host when a source carries a blank title
A source whose title is an empty string rendered as a link with no text
at all, the empty title also suppressing the hostname beside it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
d8aaa73573 |
feat: chat with a saved agent from the agent editor (#11292)
* feat: chat with a saved agent from the agent editor * fix: keep agent chats apart from a same-path flow's conversations * fix: point an agent editor chat's model gap at the agent, not a step * fix: match the memory gate's icon to the chat's empty state |
||
|
|
89323fb025 |
refactor: separate the tools the chat sends from the ones it has (#11295)
* refactor: split the chat's tool list into sent-now and available-in-session views Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: drop the forward-looking ticket reference from the tool-base comment Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: make the readonly tool seam enforceable and the comments accurate Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ea0b947644 |
fix: stop the chat repeating run results the card already shows (#11293)
* fix: tell the chat not to repeat run results the card already shows * fix: add the run result note on completion, background runs included * fix: skip the run result note on failed runs * fix: keep the run result note off background completions |
||
|
|
592ef73610 |
fix: keep a watched job's code when its completion update drops it (#11290)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
7dec3d9771 |
feat(db-manager): add a schema diagram view (#11030)
* 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 |
||
|
|
25c8bfaab4 |
chore(main): release 1.817.0 (#11268)
* chore(main): release 1.817.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com> |