* fix: re-enforce per-path token scope on store rename, delete and interpolation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: enforce token scope on workspace export and resume-url minting
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: enforce per-item and runnable scope on trigger create paths
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: enforce app write scope before persistence and on rename
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: enforce scope containment on mcp oauth approval
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: scope mcp endpoint-proxy jwt to the proxied route
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: treat resource-linked variables and resources as covered by resource scope
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: only require variables:read for plaintext-secret workspace export
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: handle singlestepflow resume, reject empty mcp grant, scope var-skipped tarball
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop empty/unknown `type` values (Windmill emits `type: ""` for untyped fields) and infer `type: array` for nodes carrying `items`, so generated MCP tool schemas validate against JSON Schema draft 2020-12. Anthropic's tool registration rejected the whole tool list otherwise.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(mcp): resolve MCP resource token via caller RLS + SSRF-guard url
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(mcp): clone user_db for oauth2 refresh and drop advisory ids from comments
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(mcp): disable redirects on MCP client to prevent SSRF bypass
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* 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>
* refactor: replace SELECT * with explicit column lists
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: update sqlx offline query cache
* chore: update sqlx offline query cache
* chore: update sqlx offline query cache with EE support
* chore: update sqlx offline query cache, no deletions
* chore: update sqlx offline query cache after rebase
* fix: correct column names in explicit script query lists
- concurrency_limit → concurrent_limit (matches DB column name)
- runnable_settings → runnable_settings_handle (matches DB column name)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: add missing delete_after_secs column to script queries
Also add integration test covering all explicit-column export queries.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add workspace export integration test covering all explicit-column queries
Covers tarball_workspace (folder, script, resource, resource_type, variable,
schedule, usr, group_) and the mcp_oauth_client SELECT query from windmill-mcp.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add tarball export integration test covering all explicit-column queries
Single test creates one of each entity type and exercises every runtime-checked
explicit-column query in tarball_workspace. Uses archive_type=tar to avoid
zip feature-gate in CI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: fix stale verification step and CI contradiction in update-sqlx skill
- Regenerate current_files.txt after EE cache restoration so step 4 reports accurate diff
- Scope "Never use SQLX_OFFLINE=true" to local prepare (CI legitimately uses it)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: remove Co-Authored-By from commit skill template
* refactor: extract SCRIPT_COLUMNS const to single source of truth
Replaces 5 duplicated 44-column lists with a shared const in windmill-types.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: extract load helpers from reload_setting family
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: convert atomic primitive globals to AtomicBool/AtomicI64
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: convert CRITICAL_*/HUB_API_SECRET/INSTANCE_EVENTS_WEBHOOK/JWT_SECRET to ArcSwap
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: pin ee-repo-ref to arcswap-refactor EE branch commit
* refactor: convert BASE_URL/HUB_BASE_URL/MIN_VERSION/LICENSE_KEY*/LICENSE_KEY_ID to ArcSwap
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: convert worker hot-path globals to ArcSwap (WORKER_CONFIG et al)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: pin ee-repo-ref to combined arcswap-urls+worker EE commit
* chore: update ee-repo-ref to d8be8f88cb8898c8f6b27421989d53528223815d
This commit updates the EE repository reference after PR #532 was merged in windmill-ee-private.
Previous ee-repo-ref: c375aaaac9ec0fc0480993627d0defc8054c31a4
New ee-repo-ref: d8be8f88cb8898c8f6b27421989d53528223815d
Automated by sync-ee-ref workflow.
* fix: cleanup unused imports + fix 2 missed WORKER_CONFIG readers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to ce0f8fbbbde09c4a858312d2d8716d224e99042c
This commit updates the EE repository reference after PR #534 was merged in windmill-ee-private.
Previous ee-repo-ref: 450b601b5aba0ca0b2045f4b5071aa8701b4bfb7
New ee-repo-ref: ce0f8fbbbde09c4a858312d2d8716d224e99042c
Automated by sync-ee-ref workflow.
* fix: secret_backend_integration test — BASE_URL.write().await → .store()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: convert APP_WORKSPACED_ROUTE to AtomicBool for symmetry with HTTP_ROUTE_WORKSPACED_ROUTE
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to e587df8 (post-#535 merge)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix: add SSRF protection to SAML and MCP OAuth endpoints
- Add shared SSRF URL validation utility (windmill-common/ssrf.rs) that blocks private/loopback/link-local IPs and validates DNS resolution
- Move test_metadata to authed service requiring superadmin access
- Strip response body from SAML metadata parsing errors
- Add SSRF blocklist to MCP OAuth discover, start, and client registration endpoints
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref.txt for SSRF fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref.txt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to 563877bf1c8b4184f638bab51be89b1c0aec6dad
This commit updates the EE repository reference after PR #471 was merged in windmill-ee-private.
Previous ee-repo-ref: a600fe1807ea267f87a57360f4b48bf917776723
New ee-repo-ref: 563877bf1c8b4184f638bab51be89b1c0aec6dad
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* feat: MCP server readiness for Anthropic integrations directory
- Add CORS layer to MCP streamable HTTP endpoint for browser clients
- Add tool result truncation (25K token limit) to prevent oversized responses
- Add HEAD method support on OAuth authorize endpoint
- Skip workspace selection redirect during MCP OAuth flow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address PR #8438 review feedback
- Add DELETE to CORS allowed methods (MCP spec requires DELETE for session termination)
- Add CORS layer to deprecated /sse endpoint for completeness
- Remove redundant .head() on OAuth authorize (axum auto-handles HEAD via GET)
- Fix comment: "chars/token" → "bytes/token" since len() returns bytes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: replace _TRUNC with hash-based MCP tool names (50 char limit)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: reduce MCP tool name limit from 50 to 40 chars
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: use path prefix filtering instead of separate DB query for hashed name resolution
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: remove long path warning from MCP token creation (hashing handles long names)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: unify tool prefix parsing and fix extract_path_prefix_from_hashed for Hs- names
- Replace `is_hashed_name` + `parse_hashed_name` with unified `parse_tool_prefix`
that returns `(type_str, is_hub, is_hashed)` in one call
- Fix `extract_path_prefix_from_hashed` to dynamically determine prefix length
(3 for `Hs-`, 2 for `S-`/`F-`) instead of hardcoding index 2
- Simplify `reverse_transform` to reuse `parse_tool_prefix`
- Add tests for invalid prefixes and `Hs-` prefix handling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: escape LIKE wildcards in MCP hashed name path prefix query
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: respect favorites scope in hashed tool name resolution
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: deduplicate MCP tool name resolution and rename get_path_or_id
- Extract `unescape_path` helper in transform.rs to deduplicate the
3-step placeholder unescape logic
- Extract `find_matching_path` helper in runner.rs to deduplicate
script/flow candidate matching via ToolableItem trait
- Remove verbose tracing::info! logs from hashed tool resolution hot path
- Fix doc comment referencing nonexistent `is_hashed_name` function
- Rename `get_path_or_id` to `get_transformed_path` for clarity
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update stale doc comments to reflect MAX_PATH_LENGTH=40
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* add endpoints
* feat: add MCP tools for script/flow/app CRUD and run endpoints with field filtering
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: convert enum arrays to description text in MCP tool schemas
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: auto-detect and rename conflicting parameter names across MCP tool schemas
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use two-pass approach in convert_enums_to_descriptions to preserve dict ordering
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add MCP instructions to createScript, runScriptByPath, and runFlowByPath
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add query param exclusion for MCP tools, slim down run endpoints
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: preserve additional top-level keys in allOf schema flattening
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: replace x-mcp-tool-exclude-query-params with x-mcp-tool-include-query-params
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: replace empty {} schemas with valid JSON Schema draft 2020-12 equivalents
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: revert openapi value:{} changes, sanitize empty schemas in generator instead
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
* refactor: extract windmill-api into 4 subcrates (api-auth, store, api-sse, api-jobs)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: eliminate refresh_token OnceLock bridge in windmill-store
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: eliminate FromRequestParts OnceLock bridge in windmill-api-auth
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: wire subcrates into workspace and clean up unused re-exports
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve cargo check --all-features errors in subcrate wiring
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* sqlx
* all
* chore: update ee-repo-ref for warning fixes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: extract windmill-trigger crate and expand windmill-api-jobs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: extract windmill-trigger-kafka crate from windmill-api
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: extract windmill-trigger-postgres crate from windmill-api
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: extract windmill-trigger-websocket and windmill-trigger-mqtt crates
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: extract windmill-trigger-nats, sqs, gcp, and email crates
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: extract windmill-trigger-http crate from windmill-api
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: move token creation and permission helpers to windmill-api-auth
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: extract windmill-native-triggers crate from windmill-api
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* sqlx
* all
* refactor: extract windmill-api-embeddings crate and fix CI warnings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: resolve type mismatch in oauth2_oss and remaining warnings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use correct HTTP_CLIENT config in embeddings crate (30s timeout, cert override)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* all
* fix: gate oauth_refresh_ee on oauth2 feature to fix warnings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* all
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Renamed deprecated type aliases following rmcp library update:
- CallToolRequestParam → CallToolRequestParams
- InitializeRequestParam → InitializeRequestParams
- PaginatedRequestParam → PaginatedRequestParams
Also added required `meta` field to ClientInfo and CallToolRequestParams.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>