Commit Graph
9084 Commits
Author SHA1 Message Date
GuilhemandClaude Opus 4.7 b0ed27096d feat(editors): responsive top-bars + collapsible raw-app sidebar (#9237)
* feat(editors): responsive top-bars + script test-pane pixel-min + flow graph overlay

Editor top bars now collapse on narrow widths (measured via container
clientWidth, not viewport — they live inside drawers / session panes
where the viewport stays wide):

- FlowBuilder: Diff + Save draft fold into the ellipsis menu when
  the top bar narrows below 720px (Save draft keeps its ⌘S / Ctrl+S
  shortcut indicator). Test-flow button moves out of the top bar
  and into a graph-pane overlay matching the dev page; the overlay
  position flips from top-2 right-2 to top-14 left-1/2 when the
  graph pane itself is narrower than 800px. FlowEditor exposes a
  graphOverlay snippet prop for that.
- ScriptBuilder: Settings + Draft labels collapse to icon-only;
  a new DropdownV2 ellipsis surfaces Tag / Settings / Save draft
  when even icons don't fit. The ellipsis itself uses variant=subtle.
- AppEditorHeader / RawAppEditorHeader: fullscreen / dark-mode /
  breakpoint toggle group + Debug-runs / Jobs buttons hide; Save
  draft moves into the Deploy dropdown.
- EditorBar: a "Helpers" DropdownV2 collapse for Context var /
  Variable / S3 / Resource / Git repo / Resource type / Database /
  Ducklake / Data table / Reset when the bar narrows below 800px
  (EDITOR_BAR_HELPERS_COMPACT_THRESHOLD). Above that, the existing
  icon-only mode (1420px threshold) still applies.
- ScriptEditor's test pane gets a pixel-based minimum width (400px)
  derived from the splitpane's clientWidth. The Pane uses Svelte 5
  function-binding so the splitter writes to a raw $state while the
  splitpane reads the clamped derived value — no $effect, no
  release-time bounce, drag stops at the boundary. Cap raised to
  80% so the test pane can take most of the editor on very narrow
  layouts while leaving a sliver of code visible.
- VS Code button on ScriptEditor: collapses to icon-only below the
  EDITOR_BAR_WIDTH_THRESHOLD (1420px) instead of being hidden
  entirely by viewport `lg:` breakpoint; hidden completely when the
  editor is rendered inside a session pane.
- AI wand button on ScriptEditor + RawAppEditorHeader: hidden inside
  a session pane (detected via `getContext('aiChatManager')`) — the
  session owns its own AI chat.
- DeployButton: drops the unused `newFlow` gate (callers updated).
- FlowDiffViewer / FlowGraphDiffViewer: inlineDiff prop forwarding
  + onHeight callback on FlowGraphV2 so diff viewers can equalize
  side-by-side graph heights.

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

* ui: unify Debug / wand / test-toggle button sizes + HideButton defaults

Two small consistency passes on shared button components:

- ScriptEditor's Debug, AI wand and Test-panel-toggle buttons all
  use unifiedSize="sm" so they line up in the toolbar; Test toggle
  switches from custom marine btnClasses to variant="accent-secondary".
  HideButton gains a passthrough unifiedSize prop so the wand and
  test toggle can match Debug without overriding btnClasses.
- HideButton's own defaults shift to variant="subtle" + sm
  unifiedSize, dropping the legacy color="light" / variant="contained"
  + tailwind-merge background overlay; the selected (hidden) state
  is now a tinted wrapper div instead of overriding btnClasses.

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

* ui(script): editor toolbar polish

Small consistency tweaks on the script editor's top-right overlay:

- Lowercase "test" / "Exit debug" panel labels.
- `bg-surface` on the overlay container so the absolute-positioned
  buttons read as a single panel over the graph rather than disjoint
  pills.
- Debug button picks up `destructive={debugMode}` so the active
  state reads as "you're in debug mode" instead of accent.
- Console and "Delegating to git repo" buttons drop the custom
  `btnClasses` border-on-surface treatment and switch from
  `size="xs"` to `unifiedSize="sm"` so they match the other buttons
  in the cluster.

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

* feat(raw-app): collapsible file sidebar, default-collapsed in session preview

The raw-app editor's left sidebar (file tree, runnables, history) ate a
lot of horizontal space — fine in the standalone editor, painful in the
session preview pane where the chat is already taking half the screen.

Add a small collapse / expand toggle. Persist the user's preference in
localStorage so it sticks across opens.

Two independent localStorage keys via the new `sidebarStorageKey` prop:
- standalone editor: `raw-app-sidebar-collapsed` (default expanded)
- session preview:   `raw-app-sidebar-collapsed-preview` (default collapsed)

Otherwise the two contexts would race for the same key — whichever
opens first would dictate the other's default. Splitting the keys lets
each have its own remembered preference.

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

* fixup(editors): use untyped getContext for AI-chat-manager session detection

The cherry-picks landed `getContext<AIChatManager>('aiChatManager')` to
hide per-editor AI/VSCode buttons when rendered inside a session pane.
The `AIChatManager` class is exported only on the sessions branch (used
for typing session-provided manager overrides). On `main` the manager
file exports only the singleton instance, so importing the class fails
the type-check.

The session-pane detection just needs a truthy/falsy probe — drop the
type parameter and the class import. `inSessionPane` ends up as
`getContext('aiChatManager')` (returns `unknown`, coerced to boolean
via `!!`). Same runtime behaviour, no class-export dependency.

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

* ui(editors): flow test in top bar; ellipsis folds draft/jobs/tutorials

* refactor(app-editor): drop dead AppEditorTutorial button path

* ui(editors): wire compactHelpers in flow-step + raw-app inline editors

* ui(raw-app): sidebar Cmd/Ctrl+B toggle + uppercase section titles

* ui(editors): keep Diff/Settings inline as icon-only when narrow

* fix(editors): address review nits on test-pane/Helpers/thresholds

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:55:20 +00:00
Guilhem 7909878313 feat(chat): waiting-for-user indicator + scroll-to-latest polish (#9252)
* feat(chat): waiting-for-user indicator and arrow polish

- Show "Waiting for your input" (text-accent + flipping Hourglass) instead
  of the typing dots when the latest tool is staged for confirmation
  (Run/Cancel) or has an active askUserQuestion. The dots imply the AI
  is working, which is misleading when the loop is paused on the user.

- Scroll-to-latest arrow:
  - Move up to bottom-12 when the flow Accept/Reject row is visible so
    they no longer overlap.
  - Wrap in a solid bg-surface + shadow + border badge so the icon
    doesn't bleed into messages behind it.
  - Bump unifiedSize xs → sm for a slightly larger target.

- Hourglass uses a custom CSS keyframe (:global so the rule reaches the
  Lucide SVG root) with 4 s period and cubic-bezier(0.65, 0, 0.35, 1)
  easing — feels like flipping the hourglass rather than spinning.

* fix(chat): raise waiting indicator above accept/reject row

* fix(chat): solid background behind reject all button

* feat(chat): @ picker in controls row, badges above input, polish
2026-05-20 12:54:23 +00:00
Diego ImbertandClaude Opus 4.7 31b781000e feat(frontend): sync home search bar state to URL (#9256)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:54:01 +00:00
Ruben Fiszelandwindmill-internal-app[bot] 78cf6c7f81 fix(saml): preserve deep links from /a/[...path] across SAML round-trip (#9259)
* [ee] fix(saml): preserve deep links from /a/[...path] across SAML round-trip

Fixes WIN-1962.

PR #9225 only covered users who pass through /user/login on their way to
the IdP — that's where `redirectSaml()` runs and where the deep link gets
stuffed into `RelayState`. The reported flow doesn't go through that
page: it hits `/a/[...path]` (the public-app custom-path route, outside
the `(logged)` layout) where `PublicApp.svelte` renders its own `<Login>`
and was passing `page.url.toString()` as `rd` — the full URL.

Three problems compounded:

1. `redirectSaml()` only set `RelayState` when `rd.startsWith('/')`,
   so a full URL silently fell through and the deep link was lost.
   The IdP echoed back the SP-library default (BASE_URL), which the
   ACS validator correctly rejected as a potential open-redirect.
2. `persistRd()` stored the full URL in `localStorage.rd`. On the
   fallback landing at `/user/login`, the post-login redirect saw
   an `http://...` value, hit the cross-origin branch, and bounced
   to `/` — which from a logged-in but workspace-less state shows
   the "Loading user…" modal forever (bug 2).
3. The EE `safe_relay_state_redirect` validator rejected any full
   URL, including same-origin ones, so even IdPs that prepend the
   origin or that pass a configured absolute deep link via
   IdP-initiated SSO got dropped on the floor.

The fix is a single concept applied at every layer: reduce a redirect
target to a safe same-origin relative path, or refuse it.

Frontend:
- `logoutRedirect.ts`: new `toSameOriginRelativePath(rd)` helper that
  accepts both `/foo` and `https://current-origin/foo`, with the same
  open-redirect guards as the backend (length cap, control chars, no
  protocol-relative or back-slash tricks). Returns `null` for
  cross-origin or malformed input.
- `PublicApp.svelte`: pass `pathname + search + hash` to `<Login>`
  instead of the full URL — this alone fixes the happy path.
- `Login.svelte`: `redirectSaml()`, `persistRd()`, and `redirectUser()`
  all route through the helper, so full URLs from `/a/[...path]` are
  reduced before being put in `RelayState`/`localStorage`/`goto()`.
- `/user/login/+page.svelte`: the same reduction is applied to the
  resolved `rd` so any stale full-URL value in `localStorage.rd` still
  navigates to the intended page instead of falling into the
  cross-origin branch.

Backend (EE companion: windmill-ee-private#TBD):
- `safe_relay_state_redirect` now reduces a `RelayState` whose origin
  matches `BASE_URL` to its path before applying the same-origin path
  safety rules. Bare BASE_URL with no path still falls back to
  `/user/login` (no useful deep link to honor).
- New `same_origin_relative_path` helper + expanded unit tests.

Test plan:
- [x] Frontend: `vitest run src/lib/logoutRedirect.test.ts` — 9 passed
- [x] Backend: `cargo test -p windmill-api ... saml_ee::tests` — 3 passed
  (`honors_same_origin_relative_path`, `reduces_same_origin_full_url_to_path`,
  `falls_back_on_open_redirect_attempts`)
- [ ] Manual e2e (needs configured SAML IdP — not on local CE):
  - Unauthenticated visit to `/a/<path>` → click SSO → SAML → land on
    `/a/<path>` (RelayState now carries the relative path).
  - IdP that echoes BASE_URL as default → ACS still falls back to
    `/user/login` (no useful path to honor), but the page no longer
    hangs: the stale full-URL `localStorage.rd` is reduced to its path
    and the post-login redirect navigates to it.
  - Tampered `RelayState` (`//evil.com`, `https://evil.com/x`) → ACS
    rejects, lands on `/user/login`.

* chore: update ee-repo-ref to 3489c243b0e5a8eb0dbc86e90917fbe72843573b

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

Previous ee-repo-ref: 635ff3eeb8e47bb84d5686942605f67f8f6224b4

New ee-repo-ref: 3489c243b0e5a8eb0dbc86e90917fbe72843573b

Automated by sync-ee-ref workflow.

---------

Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-05-20 12:46:58 +00:00
f6fcdb5599 feat: open ai chat path links in drawers (#9220)
* feat(ai-chat): link workspace paths and show tool item references

Detect Windmill paths (u/..., f/...) in assistant messages and render
them as clickable pills with the right icon, resolved against a per-
workspace cache. Tool execution headers now list the script/flow/app
paths referenced in tool parameters as external links.

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

* feat(ai-chat): linkify inline-code paths, refine pill styling

- Inline-code spans whose value is exactly a Windmill path now render
  as a link pill (paths inside larger inline code or fenced blocks
  stay as code).
- Tool-header chips moved to their own row to avoid overflow clipping
  when the title wraps.
- Borderless pills, no default background (hover only), kind icons
  use the home-page palette (script blue, flow teal, app orange),
  and the external-link indicator only appears on hover.

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

* feat(ai-chat): linkify variables/resources/triggers + inline drawer

- Workspace item registry now also lists variables, resources, schedules,
  and all 10 trigger kinds; resource wins over variable on path collisions
  (Windmill auto-creates a companion variable for every resource).
- Pill icons delegated to the canonical RowIcon component so each kind
  matches the home-page styling (script blue, flow teal, app orange,
  resource boxes, schedule calendar, etc.).
- Pill href includes the hash fragment each list page already consumes
  (#/resource/<path>, #<path> for variables/schedules/triggers), so
  opening the link puts the user on the list page with the matching
  editor drawer already open.
- For variable and resource pills, a hover-revealed side-panel button
  opens (or toggles closed) the editor drawer inline next to the chat,
  without navigating away. VariableEditor and ResourceEditorDrawer gain
  a closeDrawer() export and forward their close event so the host can
  drive toggling.

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

* refactor: simplify ai chat workspace item links

* refactor: keep ai chat path linkification only

* perf: avoid eager ai chat path cache loads

* refactor: simplify ai chat path linking

* feat: open ai chat path links in drawers

* refactor: homogenize workspace item kinds

* fix: toggle ai chat item drawer

* refactor: trim ai chat path cache

* fix: cancel ai chat drawer reopen

---------

Co-authored-by: Guilhem Lemouel <guilhemlemouel@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-05-20 10:00:16 +00:00
Diego ImbertandClaude Opus 4.7 cc141effa3 fix(frontend): flow progress bar for early-stop completion and error handler (WIN-1961) (#9254)
Two FlowProgressBar bugs:

1. stop_after_if (without 'label as skipped') ends the flow with
   step < modules.length, leaving the bar at <100% with a spinner.
2. failure_module execution drives step past modules.length, so the bar
   overflows past 100% and never reflects the error.

The fix clamps progress to the failed module when the error handler
runs, and forces 100% Done when the flow completed successfully but
stopped early.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 09:54:09 +00:00
GuilhemandClaude Opus 4.7 31a046973a feat(chat): visual redesign — input, streaming indicator, scroll polish (#9232)
* feat(chat): visual redesign — input, streaming indicator, scroll polish

Visual refresh of the AI chat surface used in both the global right-side
panel (Cmd+L) and inline editor panels. No new features, no system-prompt
or tool changes, no sessions code.

Input redesign
- Default textarea to `rows={1}` and autosize as the user types.
- Drop the separate Send button row in favour of a single
  `<Button variant="subtle" iconOnly>` overlaid bottom-right of the
  textarea — `ArrowUp` when idle (disabled until text is typed),
  `Square` when loading (cancels via `aiChatManager.cancel()`).
- Padding `!pl-3 !pr-10 !py-2` keeps text clear of the floating button.
- Top spacing `mt-1` on the outer wrapper restores breathing room
  above the input (lost when the old @-button row was removed).
- Context chip row renders only when something is selected.
- `ContextTextarea` `min-height: 2.25rem` so the empty textarea
  collapses to a tight single line.

Streaming indicator
- Replace the old floating "Stop" button with a sticky-bottom badge
  showing three animated typing dots and a formatted wall-clock
  (`Xs`, `Xm Ys`, `Xh Ym`) — driven by `aiChatManager.loading`.
- CSS keyframes `chat-typing` with staggered animation-delay for the
  wave effect.

Scroll behaviour
- Replace `onwheel`-based stick-to-bottom detection with `onscroll`
  position check (8px threshold). Auto-scroll re-engages when the
  user scrolls back near the tail.
- Smooth scroll → `behavior: 'auto'` so token-append doesn't race
  the animation.
- New `enableAutomaticScroll` method on `AIChatManager`, complement to
  the existing `disableAutomaticScroll`.
- Floating "scroll to latest" arrow (`ArrowDown` design-system Button,
  `transition:fade`, `unifiedSize="xs"`, `iconOnly`) appears once the
  user scrolls >200px above the tail; click re-enables auto-scroll
  and jumps to bottom. Centered horizontally over the scroll viewport.

Message rendering
- Assistant markdown tuned: `prose-headings:font-medium`, h1 `text-sm`,
  h2+ `text-xs`, plus `prose-p:text-xs prose-li:text-xs
  prose-code:text-xs prose-pre:text-xs`. Stops AI replies blasting
  oversized titles.
- Fenced code blocks shrink to `!text-xs` on the `not-prose` wrapper
  so fenced code matches inline code at 12px.
- User-message wrapper switches to symmetric spacing (`mt-4 mb-6`)
  with a new `isLast` prop that adds `!mb-12` to the latest message
  — breathing room between the last bubble and the input without
  affecting siblings.

Layout / padding
- Wide-layout messages tightened to `px-7` (was `px-8`); input outer
  to `px-6`. The input box sits a touch left of the message text;
  textarea's own `!pl-3` brings the typed text back into alignment
  with the messages above.

Other
- `AIChatManager` class is now exported (was private). Allows callers
  to type a `getContext<AIChatManager>('aiChatManager')` provider
  override. No behaviour change for the global singleton.

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

* refactor(chat): restore @ picker, extract typing indicator and shared helpers

* feat(chat): cap non-wide chat at max-w-2xl, add side padding, drop input top border

* feat(chat): esc cancels active generation, tone down snapshot row

* fix(chat): only draw tool-content fade when content actually overflows

* style(chat): tighten non-wide side padding (px-4/px-3 -> px-3/px-2)

* fix(chat): inline ⌘K shows dots + stop button, swallow programmatic scroll events

* fix(chat): keep scroll-to-latest fresh during cooldown; ResizeObserver for tool-content fade

* fix(chat): contain wide content - propagate showFade, table scroll, bubble + inline code wrapping

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 07:10:25 +00:00
d08f72b3e1 feat(vault): optional KV secret path prefix setting (WIN-1960) (#9249)
* feat(vault): add optional KV secret path prefix setting (WIN-1960)

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

* chore: update ee-repo-ref to 0189ba6504fd70eb4929e4881d624d48efd14aee

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

Previous ee-repo-ref: e32e8d6483550c67897e09b6f900dff1034bdae8

New ee-repo-ref: 0189ba6504fd70eb4929e4881d624d48efd14aee

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-05-20 06:09:26 +00:00
285a78752a feat(indexer): observability for unavailable search index (WIN-1956) (#9239)
* [ee] feat(indexer): observability for unavailable search index

A user hit `Not found: There is no index reader to search from` when
searching service logs and could not tell whether it was a config
error or a bug, and asked for visibility into the indexer status
(WIN-1956).

Backend (EE companion PR):
- Replace the opaque error with an actionable message explaining the
  likely causes (indexer disabled, still starting, or blocked
  acquiring the indexer lock) and pointing to the status panel.
- Add a coarse `state` (running | stale | never_started) to
  `/indexer/status`, derived from the lock row, distinguishing a
  never-configured indexer from a stale/blocked one.

Frontend:
- Instance Settings > Indexer now shows Running / Stale / Not started
  with a tooltip explaining what to check for each.
- Service logs search now catches failures and shows an inline,
  actionable Alert instead of an unhandled rejection.

Fixes WIN-1956

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

* chore: update ee-repo-ref to 017d36418a65ce5c840c502e3174df0c393612ba

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

Previous ee-repo-ref: 18b7e1b30a1ff582c4a072580bbb8aec34e22cdc

New ee-repo-ref: 017d36418a65ce5c840c502e3174df0c393612ba

Automated by sync-ee-ref workflow.

* fix(indexer): address review nits

- IndexerMemorySettings: older backends without `state` reporting
  `is_alive: false` now show "Stopped" (red) again instead of
  falling through to "Unknown" (codex/cubic P2).
- ServiceLogsInner: clear stale logs/counts on a failed search so the
  error isn't shown alongside results from a previous query (codex P2).

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-05-19 16:37:08 +00:00
hugocasaandClaude Opus 4.7 f51b51a9a1 fix(frontend): open customer portal in popup synchronously to bypass Safari blocker (#9242)
* fix(frontend): open customer portal in popup synchronously to bypass Safari blocker

Safari blocks window.open() called after an await because it loses the
user-gesture context. Open a blank tab synchronously on click, then
assign location.href once the portal URL resolves.

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

* chore(backend): wire dev_override feature flag in backend crate

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:26:32 +00:00
Ruben Fiszelandwindmill-internal-app[bot] ba6fb7021b feat: export audit logs to a dedicated object store folder (#9207)
* feat: export audit logs to dedicated object store folder

* fix: gap-free audit export via snapshot-xmin gate and stable object keys

* test: add integration test for audit log object store exporter

* fix: cursor audit export on snapshot xmin to prevent id-leapfrog loss

* fix: protect audit s3 checkpoint from config sync and bound export interval

* fix: anchor audit s3 checkpoint at enable time to not skip first-window rows

* fix: anchor first audit export at the enable transaction's xid

* fix: use epoch timestamp floor on first audit export run to not drop old backlog

* fix: anchor audit export at startup for env-var enable path

* fix: anchor audit export via enabling-txn snapshot xmin trigger

* fix: bound the bootstrap audit export to MAX_XID_INTERVAL per tick

* refactor: store audit export cursor in background_task_state, add status endpoint

* docs: align store_audit_logs_s3 setting text with the actual enable-boundary contract

* [ee] refactor: move audit s3 export core logic to EE, gate on Enterprise license

* chore: update ee-repo-ref to ec3cd353245e1cdf6a290528dbd7f2ac2498386c

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

Previous ee-repo-ref: 4ffc6d5f874e64d7dc4a147b4e73baa6c44867a5

New ee-repo-ref: ec3cd353245e1cdf6a290528dbd7f2ac2498386c

Automated by sync-ee-ref workflow.

---------

Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-05-19 14:43:54 +00:00
Diego ImbertandClaude Opus 4.7 bd062825a2 fix: scope VSCode webview clipboard paste to focused editor (#9221)
* fix: scope SimpleEditor webview paste to focused editor instance

* fix: scope webview clipboard paste to focused editor instance

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

* fix: bail on missing selection instead of pasting at document start

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

* fix: hide SimpleEditor paste sink input from a11y tree and tab order

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:02:09 +00:00
Ruben Fiszel 8c1f6ccc5d fix: prevent undefined user flickering in multiplayer presence list (#9231) 2026-05-19 07:30:27 +00:00
Ruben Fiszelandrubenfiszel c8ab030aa4 chore(main): release 1.704.1 (#9226)
* chore(main): release 1.704.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-19 05:46:13 +00:00
Ruben FiszelandClaude Opus 4.7 9c6deec8ff avoid stale localStorage rd when SAML RelayState carries the deep link (#9228)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 05:40:48 +00:00
89306d7dbc fix: honor SAML RelayState to redirect to deep link after SSO login (#9225)
* fix: honor SAML RelayState to redirect to deep link after SSO login

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

* chore: bump ee-repo-ref for SAML RelayState validator test

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

* chore: update ee-repo-ref to a3fefe85f5f2f52bb473fa47acc9efa8fd0b2206

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

Previous ee-repo-ref: 445a22536b1a6c342cde0baa6fbca9e25092f94b

New ee-repo-ref: a3fefe85f5f2f52bb473fa47acc9efa8fd0b2206

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-05-19 05:26:18 +00:00
Ruben Fiszelandrubenfiszel 11c03ca14e chore(main): release 1.704.0 (#9210)
* chore(main): release 1.704.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-19 00:04:41 +00:00
centdix 49ebf6f8ba feat: add global chat selected context (#9216)
* feat: add global chat selected context

* refactor: store workspace context as references

* fix: refresh db context after global mode
2026-05-18 22:35:08 +00:00
centdix f965512c7a feat: add global ask user question tool (#9217)
* feat: add global ask user question tool

* feat: add keyboard navigation to user questions

* feat: simplify ask user question answers

* fix: disable strict mode for optional tool schemas

* fix: scope ask question keyboard events

* fix: clean up ask question display state
2026-05-18 21:36:52 +00:00
2e05bdd73a feat: show job status in favicon on the run page (#9206)
* feat: show job status in favicon on the run page

* test: cover getJobStatusKind favicon status mapping

* chore: remove favicon unit tests

Co-authored-by: Diego Imbert <diegoimbert@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Diego Imbert <diegoimbert@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 17:43:53 +00:00
hugocasa 156eb0b045 fix: resolve absolute-path imports in monaco ts editor (#9213)
* fix: resolve absolute-path imports in monaco ts editor

* fix: dispose absolute-path extra libs on editor teardown and reset

* fix: skip late ata local-file callbacks after editor teardown
2026-05-18 16:45:19 +00:00
centdix fec4008696 fix: preserve ai reasoning content (#9208)
* fix: preserve ai reasoning content

* fix: avoid text-only reasoning replay

* feat: add deepseek ai eval models
2026-05-18 10:40:18 +00:00
Ruben Fiszelandrubenfiszel 4e91f83b8f chore(main): release 1.703.3 (#9200)
* chore(main): release 1.703.3

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-18 09:09:50 +00:00
Ruben Fiszel e1df6b45e9 chore: remove alpha/beta warnings from tested frontend features (#9196) 2026-05-17 14:41:10 +00:00
Ruben FiszelandClaude Opus 4.7 8bc2295b94 fix(mcp): validate oauth dynamic client registration redirect_uris (#9197)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 14:00:06 +00:00
Ruben Fiszelandrubenfiszel 20719b4731 chore(main): release 1.703.2 (#9195)
* chore(main): release 1.703.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-17 12:59:58 +00:00
Ruben FiszelandClaude Opus 4.7 25172bdc28 sidebar rendering expanded-but-empty at sub-pixel widths near 768px (#9191)
* fix: sidebar menu rendering expanded-but-empty near 768px width

The desktop sidebar branch is gated by JS (`innerWidth < 768`), but its
width was set only via Tailwind `md:` classes (`@media (min-width:768px)`).
`window.innerWidth` rounds fractional viewport widths, so at e.g. 767.8px
JS rounds to 768 and renders the desktop sidebar, while the CSS media
query does not match and no width class applies — leaving the sidebar
shell expanded with no width/content. Drop the now-redundant `md:`
prefix so width tracks the JS branch decision.

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

* fix: align content offset breakpoint with sidebar JS gate

The sidebar width now follows the JS innerWidth gate, but the main
content left-offset in AiChatLayout still used the `md:` CSS media
query, leaving the two breakpoints out of sync in the same sub-pixel
band. Pass an `isMobile` flag from the layout (mirroring the sidebar's
`innerWidth < 768` condition) and gate the content padding on it with
unprefixed classes so sidebar width and content offset always flip
together.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 12:13:15 +00:00
Ruben Fiszelandrubenfiszel fa090f3081 chore(main): release 1.703.1 (#9182)
* chore(main): release 1.703.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-16 08:42:33 +00:00
Ruben Fiszel 302ce58e98 harden UI builder artifact bootstrap with verified pinned metadata (#9189)
* feat: harden UI builder artifact bootstrap with verified pinned metadata

* fix: emit tab-indented artifact json to match prettier config

* refactor: rewrite artifact json with node instead of python

* refactor: simplify bootstrap to flat script, drop test scaffolding
2026-05-16 07:40:29 +00:00
Ruben Fiszelandrubenfiszel e3a3dbb89c chore(main): release 1.703.0 (#9170)
* chore(main): release 1.703.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-15 13:15:28 +00:00
Ruben Fiszel b7bc9b44b4 chore(frontend): update vite to 8.0.13 (#9179) 2026-05-15 12:45:00 +00:00
Ruben Fiszel d48d61cc79 feat(otel-tracing-proxy): configurable tracing MITM NO_PROXY hosts (#9169)
* feat(otel-tracing-proxy): configurable NO_PROXY hosts

* refactor(otel-tracing-proxy): NO_PROXY only governs job-side bypass

* fix(otel-tracing-proxy): restore empty NO_PROXY default

* test(otel-tracing-proxy): unit tests for NO_PROXY normalization

* fix(otel-tracing-proxy): gate normalize_no_proxy_hosts to EE features
2026-05-14 14:03:47 +00:00
Ruben Fiszelandrubenfiszel 7f589a8c7d chore(main): release 1.702.1 (#9166)
* chore(main): release 1.702.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-14 10:54:35 +00:00
Ruben Fiszelandrubenfiszel 90f494975d chore(main): release 1.702.0 (#9160)
* chore(main): release 1.702.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-14 09:18:42 +00:00
Ruben FiszelandClaude Opus 4.7 e5286f4607 feat: include service accounts in instance settings users list (#9157)
* feat: include service accounts in instance settings users list

Service accounts (workspace-scoped, no password row) now appear in the
superadmin users list with a Bot icon, workspace badge, and a link to
manage them in the workspace settings. Role is locked to Operator.

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

* chore: update sqlx offline cache

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

* fix: use composite key for users each block

Service accounts can share emails across workspaces, so key by email + workspace_id to avoid Svelte each_key_duplicate.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 06:46:48 +00:00
Ruben Fiszelandrubenfiszel 4f3a1e3109 chore(main): release 1.701.0 (#9131)
* chore(main): release 1.701.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-13 16:19:55 +00:00
d666e8431c feat: read-only flag on API tokens (#9144)
* feat: read-only flag on API tokens, orthogonal to scopes

Add a per-token `read_only` boolean set at creation time. When true, the
token can only call HTTP methods classified as Read (GET/HEAD/OPTIONS).
Mutating methods and job-run actions are rejected with 403, regardless of
which scopes are attached. Surfaced as a prominent toggle in the standard
token-creation flow and a discreet `2xs` toggle in MCP mode (where users
often want write access, so we don't bias them toward enabling it).

MCP enforcement: read-only tokens hide all script/flow/hub tools from
`list_tools` and only see endpoint tools whose method is GET, and the
runner rejects `call_tool` on anything mutating.

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

* fix: review fixes for read-only token flag

- Exempt /api/mcp/* and /mcp/* paths from the read-only middleware check.
  MCP transport runs over POST (streamable HTTP / SSE), so otherwise the
  middleware would 403 every MCP request before the runner could enforce
  read-only at the tool-call level.
- Tighten is_endpoint_read_only to GET only, matching the read_only_hint
  that create_endpoint_annotations actually emits.
- Add unit test for check_read_only_for_route covering GET/HEAD/OPTIONS,
  mutating methods, and run paths.

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

* chore: bump ee-repo-ref to read-only-trigger-toggle

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

* fix(frontend): make read-only toggle discreet in both modes

Match the MCP-mode treatment in standard mode: text-tertiary, 2xs, shared
"Read-only" label. The tooltip switches per mode so the explanation still
fits the context.

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

* fix(frontend): gate read-only toggle behind Limit token permissions

The read-only toggle now only shows when the user has limited the token's
scopes (standard mode) or in MCP mode (which always picks an MCP scope).
Turning the limit off also resets read-only so it doesn't silently stick.

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

* feat(frontend): hide incompatible MCP tools when read-only is on

When the read-only toggle is on in MCP mode:
- Endpoint badges and the custom-mode endpoint MultiSelect filter to GET.
- Already-selected non-GET endpoints are pruned from the scope.
- The scripts/flows preview is replaced with a note explaining they're
  hidden (the runner already rejects script/flow runs for read-only).

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

* fix(frontend): place read-only toggle at top of limited scope area

The previous gate required at least one scope to be picked before the
read-only toggle appeared, which made it look missing while the user was
still building their scope list. Move the toggle inside ScopesPicker:
- Standard mode: sits directly under the "Limit token permissions" toggle
  whenever Limit is on, before the scope selector.
- MCP mode: sits at the top of the MCP scope block.

readOnly is now $bindable on ScopesPicker so CreateToken still owns the
value. The auto-reset on un-limit moves into ScopesPicker too.

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

* fix(frontend): nest read-only toggle inside the scope list card

Place the read-only toggle at the top of the scope list (between the
Selected Scopes summary and the bordered domain list) via a new optional
topSlot snippet on ScopeSelector. Keeps ScopeSelector decoupled from
read-only specifics; ScopesPicker fills the slot.

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

* chore: update ee-repo-ref to 9bc8160be50b3e57a60daf4e1b71c389a6e02b8a

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

Previous ee-repo-ref: f53d26e6685dfd60bfa67686fbd7358169cfd130

New ee-repo-ref: 9bc8160be50b3e57a60daf4e1b71c389a6e02b8a

Automated by sync-ee-ref workflow.

* fix: address CI review for read-only token flag

- P1 (Codex): narrow the MCP middleware exemption from "any /api/mcp/*"
  to just the streamable HTTP transport endpoints
  (/api/mcp/gateway, /api/mcp/w/{ws}/{mcp,sse,list_tools}). Without this,
  a read-only token could POST /api/mcp/gateway/oauth/server/approve and
  mint a follow-on non-read-only MCP token via the OAuth code/token
  exchange.
- P2 (Claude/cubic): fix test comment/assertion mismatch — the run-path
  assertion now exercises GET (which is what the RUN_PATH_ACTIONS
  elevation comment describes) in addition to POST. Add a regression
  assertion for /api/mcp/gateway/oauth/server/approve.
- P2 (cubic): short-circuit script/flow/hub-script/resource fetches in
  MCP list_tools when read_only is on — they would only be discarded
  below, so skipping the DB and resource fan-out is pure win.
- P2 (cubic): when scopes are pre-supplied via the CreateToken prop, the
  ScopesPicker isn't rendered, which previously hid the read-only
  toggle entirely. Render it next to the pre-supplied scopes display.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-05-13 15:26:21 +00:00
windmill-internal-app[bot]andwindmill-internal-app[bot] 110bef0a6e fix: Allow devops role to use all_workspaces runs filter in admins workspace (#9153)
Co-authored-by: windmill-internal-app[bot] <1429786+windmill-internal-app[bot]@users.noreply.github.com>
2026-05-13 15:12:11 +00:00
Ruben Fiszel c5092069cb fix: align script path existence check with deploy logic; hide Delete for non-admin (#9152)
- exists_script_by_path now filters archived = false, matching the
  conflict check in create_script_internal. Previously the frontend
  blocked creating a new script at a path occupied only by archived
  scripts, even though renaming to that same path was allowed.
- Hide the Delete entry in the script details "..." menu unless the
  user is admin. The backend delete_script_by_hash already requires
  admin, so non-admins would always see an error after clicking.
2026-05-13 15:05:25 +00:00
Ruben FiszelandClaude Opus 4.7 dd19e52a84 perf(dynselect): only retrigger when helper args actually change (#9148)
* perf(dynselect): only retrigger when helper-script args actually change

Parse the inline helper's signature with the existing WASM parser and
restrict the form-arg diff to keys the helper actually consumes. Typing
into unrelated fields no longer queues a dynselect job every second.
Falls back to the previous full-args comparison when the helper is
deployed or parsing fails.

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

* fix(dynselect): avoid double helper-script fetch on mount

usePromise defaults to loadInit=true, so refresh() ran before the
JobLoader child was bound (firing a no-op pending promise) and the
$effect then fired a second refresh once the bind:this resolved.
Disable loadInit so the effect owns the single first call.

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

* refactor(dynselect): use parser directly instead of inferArgs

inferArgs mutates a Schema object we never use and goes through a
shared cache; when fed an empty schema for non-main entrypoints the
caller cannot reliably read back the resulting properties. Add
parseEntrypointArgs that just runs the parser and returns the
parameter name Set (or undefined when unknown / unsupported / has
rest args / function not found). DynamicInput uses that and keeps
the previous params in flight while the next parse is computing.

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

* feat(dynselect): support deployed helpers in smart retrigger

Add getHelperEntrypointArgs which dispatches on HelperScript.source:
inline parses immediately; deployed fetches the script (or the flow's
inline dyn-select code) once and caches per (workspace, kind, path,
entrypoint). Without this the /scripts/get/* run view fell back to
the full-args comparison and still retriggered on unrelated fields.

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

* fix(dynselect): zero-arg helpers report empty deps, not unknown

Codex review flagged that a valid zero-parameter entrypoint was being
treated as "couldn't determine signature" and falling back to the
full-args comparison. Distinguish "function found with no params" from
"function not found" via the parser's auto_kind field — only the
latter sets it, so empty args + auto_kind=null means a real zero-arg
helper and we return an empty Set (no retrigger on unrelated fields).

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 14:58:35 +00:00
centdix d243e0cde8 align global flow tool arguments (#9146) 2026-05-13 12:38:49 +00:00
Guilhem d0f23cc523 feat(frontend): unified EditorHeader with file picker for flow/script/app editors (#9047)
* feat: add EditableInput component

* feat: add EditorHeader for flow editor with file picker entry point

* feat: WorkspaceItemPicker for editor header navigation

* feat: clickable breadcrumb in EditorHeader, scoped picker keyboard nav

* fix: reload flow on URL change and reset highlight in search mode

* feat: editor header layout polish and trigger removal

* feat: apply EditorHeader to script, app, and raw app editors

* fix: show generated initial path for new apps in EditorHeader

* fix: align EditorHeader new-app path with draft drawer's Path component

* fix: read page.params.path in loadApp to reload on URL change

* fix: remount AppEditor when navigating between apps

* fix: clear app/files on URL change so editor remounts with fresh data

* fix: route picker selections to /apps/edit or /apps_raw/edit based on raw_app

* fix: drop Save button from path popover; defer rename to deploy

* refactor: drop pathPopoverContent snippet, bind newEditedPath directly

* refactor: dedupe editor header plumbing (editPathFor, userPathPrefix, breadcrumb snippet)

* fix: freeze breadcrumb during path edit so popover doesn't drift

* fix: drop spinner from path dependency-check; render nothing when no usages

* fix: swallow 404 in checkFlowOnBehalfOf so renaming a flow doesn't toast

* Revert "fix: swallow 404 in checkFlowOnBehalfOf so renaming a flow doesn't toast"

This reverts commit 82dec462ae.

* refactor: drop moveRenameManager dep from EditorHeader; pass onBehalfOfEmail as prop

* refactor: replace breadcrumb-snapshot effect with open/close setter

* refactor: drop unused dirtyPath state from EditorHeader

* fix: surface Path validation error in pen popover

* fix: decouple Path validation error from hideFullPath toggle

* refactor: use InputError for path validation message (slide transition)

* fix: re-derive Path meta from external path changes (sibling sync)

* docs: note Path's meta could be replaced with function-form bindings

* fix: 'Exit & see details' uses deployed path, not live store

* fix: undo/redo shortcut uses shiftKey instead of fragile case-match

* fix: type errors and keep edit pen visible while popover is open

* chore: remove unused meltComponents/Accordion wrapper

* fix: focus search input on picker open via popover openFocus selector

* fix: refocus picker search input on every popover open

* fix: pre-seed picker loaded state from cache so accordion opens at the right place

* fix: breadcrumb and picker track savedPath, not draft-renamed live path

* fix: inject current draft item into picker so breadcrumb scope isn't empty

* docs: add component-level and prop-level docs to EditableInput

* feat: warn that a deploy is needed when path is edited on a saved item

* feat: show same path-change-needs-deploy message in flow/script settings

* fix(flows): persist draft-renamed path through reload and dirty check

* fix: include path in unsaved-changes diff so renames trigger the modal

* feat: nested folders in picker tree and breadcrumb

* fix: per-segment popover state so switching breadcrumbs closes the previous one

* refactor: replace accordion picker with drill-through picker

* refactor(picker): review fixes, drill polish, and breadcrumb collapse

* fix(picker): review fixes — banned bindable, drop sibling-sync, load races, mouse highlight

* fix(picker): smooth-scroll highlighted row into view on open

* fix(picker): second-pass review fixes — load races, cache invalidation, breadcrumb/picker a11y, raw_app routing

* fix(RowIcon): apply size prop to resource_type and fallback divs

* feat(picker): add cross-kind 'All' root; deeper breadcrumb segments open there

* fix(picker,editor): third-pass review — search loading state, pen autofocus, allow empty summary, a11y

* fix(picker,editor): fourth-pass review — own check, flowbuilder arrows, editableinput double-save, customui.path gate, invalidate races

* fix(editor,picker): codex review — fresh URL state per load, granular whitelabel topBar gates

* fix(flows): clear localStorage in auto-reload to break URL-state loop
2026-05-12 14:33:21 +00:00
Ruben Fiszelandrubenfiszel c6346aabe0 chore(main): release 1.700.2 (#9117)
* chore(main): release 1.700.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-12 12:32:07 +00:00
Ruben Fiszel 0bb77a9bd6 route result and args downloads through downloadViaClient (#9122)
* fix(frontend): route result and args downloads through downloadViaClient

* refactor(frontend): reuse argsApiPath in WINDMILL_TOO_BIG branch
2026-05-12 11:48:42 +00:00
Ruben FiszelandClaude Opus 4.7 07a4cb6872 branch download UI on shouldDownloadViaClient instead of onclick interception (#9118)
* fix(frontend): branch download UI on shouldDownloadViaClient instead of intercepting in onclick

When OpenAPI.TOKEN is set, several download links rendered an `<a href>`
to the API and relied on an `onclick` handler to call `e.preventDefault()`
and route the request through `downloadViaClient`. This is fragile in
embedded contexts (e.g. the whitelabel React SDK) where Svelte's hydrated
event listener may not intercept the click in time, so the browser
follows the unauthenticated `href` straight to the API.

Mirror the drawer pattern already used in `LogViewer` and
`FlowStatusViewerInner`: render a `<button>` calling `downloadViaClient`
when `shouldDownloadViaClient()` is true, and fall back to the plain
`<a href download>` otherwise. Affects the LogViewer top bar, the large-
result download in DisplayResult, the inline S3 link in ObjectViewer,
the CSV link in ParqetCsvTableRenderer, and FileDownload.

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

* fix(frontend): treat custom HEADERS / basic auth as token equivalents in shouldDownloadViaClient

Customers wiring the SDK with cookie-bypass auth via custom request
headers (e.g. `OpenAPI.HEADERS = getAuthHeaders()` returning a Bearer
header) had `shouldDownloadViaClient()` return false because it only
checked `OpenAPI.TOKEN`. The plain `<a href download>` branch then
followed the link without those headers, so authenticated downloads
silently degraded to the cookie path (or failed when there is no cookie).

Widen the check to any non-cookie auth: TOKEN, HEADERS, or USERNAME
(basic auth). Route `downloadViaClient` through the generated client's
`getHeaders` so all configured auth schemes are applied consistently
instead of hand-building an Authorization header for TOKEN only.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 10:42:05 +00:00
centdixandClaude Opus 4.5 110384580e refactor: add global ai chat mode with workspace-item draft tools (#9056)
* docs: add global ai mode plan

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

* feat: add global ai draft mode

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

* fix: scope global ai mode to scripts and flows

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

* refactor: simplify global ai workspace item shape

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

* refactor: split global ai write tool into per-type tools

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

* feat: add global ai schedule and trigger workspace item tools

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

* feat: add dev-only /global_drafts route to inspect ai draft store

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

* feat: add edit_script and patch_flow_json global ai tools

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

* feat: add deploy_workspace_item global ai tool with confirmation

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

* feat: emit open-resource action card after deploy_workspace_item

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

* feat: add delete_workspace_item global ai tool with confirmation

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

* chore(system_prompts): emit RESOURCES_BASE and resource/variable zod schemas

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

* feat: add global ai resource and variable workspace item tools

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

* fix: search_resource_types uses listResourceType to avoid embedding feature dep

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

* Revert "fix: search_resource_types uses listResourceType to avoid embedding feature dep"

This reverts commit 6d1d19514a.

* feat: emit open-resource action card for variable and resource deploys

* feat: add global ai raw app workspace item tools

* feat: split raw-app prompt into chat-only authoring and cli prefix

* feat: add init_app global ai tool to scaffold raw apps from templates

* fix: pass write_flow value as JSON string for gemini compat

* refactor: hoist countExactMatches and applyExactReplace to chat/shared

* refactor: extract editableFlowJson module shared with global mode

* fix(global): preserve flow schema and groups across draft and deploy

* feat: extract inline scripts from flow reads and patches in global mode

* refactor: add findAndReplace helper for match-validated text patches

* refactor: extract getInlineRunnableContent helper for app file tools

* refactor: extract assertNotGeneratedAppFile guard for /wmill.d.ts

* feat: gate global ai mode behind localStorage flag for dev rollout

* chore: bump svelte to ^5.55.5 in raw app template (sync with main)

* fix: isolate global ai draft rollout

* fix: preserve global ai deploy metadata

* fix: harden global ai draft tools

* chore: remove global ai plan doc

* fix: align raw app prompt guidance

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-12 09:42:07 +00:00
Ruben Fiszelandrubenfiszel 411ca47ffd chore(main): release 1.700.1 (#9114)
* chore(main): release 1.700.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-11 23:23:08 +00:00
Ruben Fiszelandrubenfiszel b972fabab4 chore(main): release 1.700.0 (#9092)
* chore(main): release 1.700.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-05-11 22:37:58 +00:00
Ruben Fiszel ac3c155541 fix: mask oauth client secret in instance settings (#9112)
* feat: mask oauth client secret in instance settings

* fix: address ci review - migrate nextcloud + use Password small prop

* fix: associate client secret labels with input via for/id
2026-05-11 22:30:15 +00:00
9c6cd8c852 offline (URL-bound) license keys (#9089)
* [ee] feat(license): offline (URL-bound) license keys

Offline keys are a 4-segment variant for air-gapped customers — no
phone-home, embedded seat/CU caps, locked to the instance's base_url.
Existing 3-segment online keys are unchanged.

Companion PRs:
- windmill-labs/windmill-ee-private (full design + EE impl)
- windmill-labs/windmill-customer-service (issuance + portal)
- windmill-labs/windmill-cf-worker-keygen (signing)

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

* [ee] refactor(license): bind offline keys via instance hash; simpler CU enforcement

- /settings/license_status now surfaces an `instance_hash` superadmins share
  with support when requesting an offline key
- OfflineMetadata: `hash` replaces `base_url`; OfflineCapStatus reports
  `current_cu` (last 2min) and drops the grace-period fields
- verify_license_key now takes a db so EE can recheck the hash
- InstanceSetting.svelte: hash copy-block + simpler status panel
- Bump ee-repo-ref

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

* [ee] chore(license): bump ee-repo-ref

Pulls in the current_cu clamp + prod public key restoration.

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

* [ee] refactor(license): split instance_hash endpoint; minimal cap UI; restore workers expiry toast

- `instance_hash` is no longer part of /settings/license_status responses; it
  lives at GET /settings/instance_hash (super-admin only) so it isn't re-emitted
  on every status poll. The UI doesn't show it — admins fetch it explicitly when
  requesting a key from support.
- InstanceSetting offline cap UI is now two compact green/red status lines
  (Seats X.X/Y and CUs X.X/Y) placed above the action buttons, matching the
  existing "Latest key renewal" badge style. The block-panel is gone.
- "Latest key renewal" line and the "Renew key" button are now hidden when an
  offline key is loaded (renewal is server-disabled for offline keys).
- Restore parseLicenseKey + checkLicenseExpiration toast on /workers
  (works for both 3- and 4-segment keys).

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

* [ee] chore(license): bump ee-repo-ref

Pulls in the plain-SHA256 instance hash + stats_ee revert.

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

* [ee] chore(license): bump ee-repo-ref

Picks up the alert wording change.

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

* [ee] chore(license): bump ee-repo-ref

Picks up the instance_uid cache so the periodic verify_license_key cycle
no longer hits global_settings.

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

* [ee] refactor(license): rename /settings/license_status → /offline_license_status

The endpoint was only used by the offline-license UI; the other fields it
returned (license_key_id, license_key_valid, kind, offline metadata) were
unused. Rename to clarify scope and flatten the response — it now returns
just the OfflineCapStatus (or null when no offline license is loaded).

Frontend uses `offlineCapStatus != null` as the "is offline" check.

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

* [ee] fix(ci): regenerate sqlx cache for the inline worker_ping query

After reverting unused stats_ee helpers (fetch_worker_pings*), the
inline `sqlx::query_as!(WorkerPingRecord, ...)` in get_stats_payload
lost its cache entry — CI's check_ee_full + cargo_test were failing
under SQLX_OFFLINE=true with E0282 type-inference errors.

Re-running update_sqlx.sh regenerates the cache file under its
current hash and prunes a couple of stale entries.

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

* [ee] fix(license): address cubic-bot review

- get_offline_license_status: propagate enforce_offline_caps errors as 500
  instead of swallowing into a "no offline license" (Option::None) response
- canonical_base_url: rewrite the doc to match the actual fallback behavior
  (lowercase + trailing-slash strip on URL parse failure); the original
  cross-service contract is gone since the customer-service no longer
  canonicalizes (treats the instance hash as opaque)
- check_seat_cap_for_new_user: take an email and short-circuit when the
  email is already in `usr ∪ workspace_invite` so net-zero invite upserts
  and invite→user transitions aren't spuriously blocked at cap. Mirrors
  the dedup rule the count itself uses.
- Bump ee-repo-ref to pull in the EE-side change

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

* [ee] chore(license): bump ee-repo-ref

Picks up the exact-delta seat-cap check (replaces the simple existence
short-circuit). Regenerates the new sqlx cache for the bool_and query.

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

* [ee] fix(license): propagate get_instance_hash errors; bump ee-repo-ref

- get_instance_hash: replace `.ok().flatten()` with map_err+? so DB errors
  during instance_uid lookup surface as 500 instead of silently returning
  `{"instance_hash": null}` (same pattern get_offline_license_status already uses)
- Bump ee-repo-ref to pull in the enforce_offline_caps cached-state preservation

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

* chore: update ee-repo-ref to c6cd1afe2d9e04809b30751cd1687b28a65e62b1

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

Previous ee-repo-ref: a6d91016ae0d43c46604313aecae3aa9c778c8e0

New ee-repo-ref: c6cd1afe2d9e04809b30751cd1687b28a65e62b1

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <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>
2026-05-11 22:09:21 +00:00