* feat: add per-route CORS origin allowlist for HTTP triggers
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: fail closed on cold router cache and invalid origin input
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: resolve CORS route from the decoded path like the request handler
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat: add instance-wide default allowed origins for HTTP routes
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: let non-superadmins read the default allowed origins setting
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat: badge the advanced section when a route's origins are restricted
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: state inherited origins on the control and use one hint row
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: trim the origins tooltip and relabel the toggle when a default exists
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: keep the origins format hint visible until an entry is wrong
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: state the at-least-one requirement in the origins hint
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: import the origins validator in the trigger-http tests
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: make an empty allowlist deny rather than fall back to the default
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: address review nits on origin validation and the CORS editor
* fix: derive the origins error from the stored list and tighten host validation
* fix: parse real IPv6 hosts and refuse a newly emptied allowlist
* refactor: make origin validation advisory except for null and non-ascii
* feat: let an empty allowlist be saved as deny every origin
* docs: document the empty allowlist as deny every origin
* fix: bound allowlists, reject commas, and decide cors after the handler
* chore: revert unrelated rustfmt churn in windmill-common tests
* chore: revert unrelated rustfmt churn in windmill-common
* chore: drop the route types the cors restructure replaced
* fix: take the stricter cors decision from before and after the handler
* fix: strip runnable cors headers when the routers are unavailable
* docs: document the allowlist bounds in the openapi schema
* fix: let an unavailable cors read defer to one that resolved
* refactor: carry the resolved cors policy from the handler to the middleware
* docs: describe why an unavailable read fails closed on the paths that reach it
* fix: validate the default origins on the declarative settings path
* test: keep the webhook doc comment with the test it describes
* fix: warn on impossible schemes and ports, and validate the instance setting
* feat: treat an empty allowlist as unset at both levels
* perf: decode the cors path only when the fallback needs it
* docs: document the empty allowlist as unset in the api schema
* docs: describe an empty allowlist as unset in the frontend comments
* docs: say what a null allowlist resolves to, not what it meant before the default existed
* docs: state what the validator refuses and why methods stay broad
* feat: exempt static asset routes from the origin allowlist
* fix: hide the origin control for every static target, not just websites
* fix: exempt only static websites, not single-file static assets
* fix: warn on an unclosed ipv6 host in the origins advisory
* fix: require assets present, not just the static website flag
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* refactor: make the app policy's principal the authority for its identity
* fix: align the app backfill with the sibling migration and audit the uncached address
* chore: refresh the sqlx cache after rebasing onto the merged base
* fix: resolve the app execution address uncached, it decides the job's authorization
* chore: cache the EE queries at the ref this branch pins
* chore: cache the EE queries at the ref this branch pins
* fix: derive the app draft's on-behalf-of address on read
* chore: cache the query the draft derivation test added
* fix: derive the app identity on the draft-table and version reads too
* docs: state the draft resolver's authorization contract
* fix: resolve a draft's principal against workspace membership only
* chore: cache the membership lookup the draft resolver added
* fix: drop an unresolvable draft's address instead of leaving it stale
* perf: evict the address cache on change so app dispatch can read it
* fix: evict on superadmin role changes, not only address changes
* refactor: make the app policy's address optional instead of derived on read
* fix: follow an external superadmin's rename into the apps that name them
* docs: state the removal gate once, and correctly
* refactor: drop the app-policy version constant that gated nothing
* docs: drop the last reference to the removed constant
* perf: read the address cache everywhere now that eviction reaches every replica
* fix: keep persisted addresses off the cache the poller evicts asynchronously
* docs: state where the cached address is accepted and where it is not
* docs: keep the cache rule in one place and drop the stale premise
* docs: sort the two lookups by how long a wrong answer lives
* fix: resolve the schedule address uncached where it is written to the row
* docs: name the release this actually ships in
* perf: evict a superadmin's key per workspace instead of the whole cache
* fix: evict every alias a superadmin principal can be spelled as
* docs: describe the trigger as it is
* docs: cover the round-tripped read in the cache rule
* docs: record why a stale dispatch address cannot escalate
* fix: validate a dispatch address against the principal's live binding
* fix: carry the validated address through to the job row and token
* fix: record the validated address on the job row, not the one handed in
* test: run the substep tag check as the non-superadmin it means to test
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* fix: rewrite a stored app address that disagrees with its principal
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* docs: record the accepted staleness window of the cached dispatch address
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* fix: record the validated address on the job's audit row
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* docs: record the accepted rename race of pre-transaction identity resolution
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* docs: separate the app's stored address from the derived one in the resolver doc
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* docs: describe the job identity fast path the push comments skipped
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* fix: backfill a legacy group-prefixed username as the group it names
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* fix: resolve a schedule edit's identity before opening its transaction
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* fix: never resolve a disabled member to a same-named superadmin
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* docs: state what the email-change notify buys, and rewrap two comment lines
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* fix: keep a group's runnables when offboarding a legacy group-prefixed member
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* fix: read the app author from the stored address, as execution does
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* docs: record the rename race's full consequence as a known, accepted limitation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
* docs: record the keep-target group address case as a known, accepted limitation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat: let a native trigger be disabled without deleting it
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: show and control the native trigger pause outside the flow editor
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: create a native trigger already paused instead of pausing it after
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs: correct the native trigger enabled comments for create-time init
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat: recognize `// volume:` mounts in PHP scripts
Volume annotations were parsed for every language but PHP, so a PHP script
could not mount a workspace volume. Two things stood in the way: PHP had no
entry in the comment-prefix maps, and a PHP script opens with `<?php`, which
ends the leading comment block the parsers scan before any annotation is read.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3FR7iS9nRhpFt615cnuQ7
* fix: tolerate a PHP opener that carries code, drop the inert CLI hunk
The open-tag skip matched `<?php` exactly, so `<?php declare(strict_types=1);`
still ended the leading comment block and every annotation below it was silently
ignored. Match the tag as a case-insensitive prefix and skip the whole line.
The CLI local-graph hunk could never fire: PHP has no wasm asset parser, so
`fallbackParse` handles it, and its own header scan stops at `<?php` — the script
is dropped as a non-pipeline-member before any volume asset is read. Making only
the CLI PHP-aware would also put the local graph out of parity with the deployed
one, whose `parse_pipeline_annotations` stops there too.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3FR7iS9nRhpFt615cnuQ7
* docs: correct the CLI mirror comment, state the own-line annotation rule
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3FR7iS9nRhpFt615cnuQ7
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(cli): keep permissioned_as on single-item push, as sync push does
* fix(cli): resolve syncBehavior from the target workspace, not the branch alone
* refactor(cli): share the workspace-name resolution between sync and single-item push
* test(cli): import the moved workspace-name helper from its new home
* docs: teach agents to pass a resource as $res:<path> in run arguments
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk
* docs: extend run-argument rule to in-editor chats, fix run-as wording
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk
* docs: tighten resource run-argument rule after review
- Drop the false rationale that "$var:" only works inside a resource value
from the write_variable description and its runtime rejection message; keep
the rule (a variable cannot reference itself).
- MCP resource-argument description: the title fallback renders "No title",
so say the title is only a label rather than that it can be empty. Guard the
real-newline fix with asserts in the existing enrichment test.
- Eval: assert the full "$res:f/evals/global/github_main" value as one prefix
so a wrong path with a right prefix fails.
- resources.md: narrow "a trigger's payload" to its configured static args.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk
* docs: scope the run-argument rule to global chat, add an exact eval matcher
The ai_evals A/B on the two in-editor modes showed no effect: script mode
sonnet 5/5 both with and without the description, flow mode sonnet 5/5 and
haiku 5/5 on the baseline alone. A flow's input schema already carries
`format: resource-<type>`, so those modes have a signal global mode does not
give. Revert both files to keep the tool schemas free of a description that
buys nothing per iteration; global mode keeps it, where haiku goes 0/5 -> 5/5.
Add `stringEqualsAnyOf` to toolCallArgs and use it for the resource reference:
nothing in the eval resolves the value, so a prefix match accepted a near-miss
path like `$res:f/evals/global/github_main_backup`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk
* docs: address cubic review — CLI wording, mock resource getter
- `-d --data` help on all four run/preview commands: give $res: and $var:
their own clauses instead of a parenthetical that read as if a resource
were a kind of variable.
- Mock backend: `getBenchmarkResource` now resolves AI-provider seeds as well
as plain ones, so it agrees with `existsResource` and `listResource` — both
report either kind, and a case that listed a resource and then read it by
path got a row it could not fetch.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjRARL7JA7xm772iJP4mJk
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: connect to dev server instead of localhost
* fix: derive WebSocket scheme from location.protocol
Mirror the protocol-aware pattern used by initSqlWebSocket in dev.ts
so the WebSocket connects over wss:// when the dev server is reached
through an HTTPS proxy/tunnel, avoiding mixed-content blocking.
* refactor: drop now-unused port parameter of wmillTsDev
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HsfdN82yP88qyQ3h8Lwv2v
---------
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat(ai-chat): make reusable skills ai_skill resources you select per workspace
* chore: pin the ee ref to the skill telemetry counters
* fix: address review findings on skill authoring, import and migration
* fix: enforce skill selection in read_skill and stop imports clobbering resources
* feat: carry format_extension from the hub into synced resource types
* fix: let an edit set or clear a resource type's format_extension
* fix: regenerate the sqlx cache and close the review round findings
* fix: close the round-2 findings on folder ACLs, cached sync and truncation
* refactor: make the skills migration non-destructive and use design-system inputs
* fix: close the round-4 findings on folder owners, startup sync and truncation
* fix: clear obsolete extensions, guard folder owners, and report skipped skills
* fix: honor explicit-null extensions and report same-type migration conflicts
* fix: scope skill actions to the committed workspace and paginate the listing
* fix: keep the drawer scoped to the live workspace and surface truncation
* fix: discard a skills refresh for a workspace the chat has left
* chore: update ee-repo-ref to 6efe7a73c745c2e1377a34498523c00d89010a3d
This commit updates the EE repository reference after PR #764 was merged in windmill-ee-private.
Previous ee-repo-ref: 55998c142bc72edd08532748af1974b16035658d
New ee-repo-ref: 6efe7a73c745c2e1377a34498523c00d89010a3d
Automated by sync-ee-ref workflow.
---------
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix: keep a local dbt descriptor under sync pull --keep-deleted
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0174o6mGTWoanipUgf5zNcVL
* fix: keep an added-shaped dbt descriptor removal under --keep-deleted too
A stateful pull compares `.wmill`, not the working tree, so a descriptor
missing from that map still arrives as `added` while a real file with the
project's warehouse and run arguments sits on disk. Counting only `edited`
left that file deletable, and silently: the flag logged nothing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0174o6mGTWoanipUgf5zNcVL
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: strip the script/ prefix from trigger error handler paths
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: strip the script/ prefix when collecting trigger handler refs
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: relocate prefixed trigger error handlers on project retarget
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: reject a prefixed error_handler_path on triggers instead of resolving it
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: describe error_handler_path as a bare script path in the api schema
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* fix(cli): keep svelte component styles in the raw-app bundle
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test: fold svelte style guard into the plugin test file
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: record the editor-parity constraint on the svelte css option
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(cli): pin esbuild's service cwd before any test file chdirs
esbuild's node API captures process.cwd() when its module is first
imported and spawns its service with that cwd on every (re)start.
createBundle stops the service after each bundle, so the cwd is reused
across the whole run.
Several test files chdir into a temp dir and delete it afterwards. The
first one to bundle therefore pinned the service to a directory that
stopped existing, and the next test to reach esbuild died with
The service was stopped: ENOENT: no such file or directory,
posix_spawn '.../@esbuild/linux-x64/bin/esbuild'
The binary is present; ENOENT is posix_spawn rejecting the missing cwd.
Which file tripped it depended on bun's readdir order, so renaming an
unrelated test file was enough to surface it. Importing esbuild from the
preload pins the service to a cwd that outlives the run, independent of
file ordering.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G88YF3sZFnJZUvTLVjqhZc
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
* fix: keep raw-app files within their app folder on sync pull
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: validate raw-app file keys as stored, closing nul and duplicate-field bypasses
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: guard raw-app runnable ids too and fail closed on unparseable value
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: strip only a leading slash on raw-app file keys to match backend
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: strip only a leading slash on raw-app file keys to match backend
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>