mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-29 00:03:09 +00:00
8a8442ec73a0ca8904303615ae0d803e5b2d59ac
92
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c6a93a9b56 |
feat: chat with a saved agent from a raw app through an agent runnable (#11921)
* feat(chat-sdk): chat through a raw app's backend runnable Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(chat-sdk): finish a lost stream and wait out a stopped turn in streamChatTurn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(chat-sdk): show the answer when a stream is lost before a tool call Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(chat-sdk): send attachments through the raw app runnable Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(chat-sdk): point sandboxed attachments at the runnable section Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: agent runnables for raw apps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: build agent runnables without the parquet feature, cache the agent check query Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: address review nits on the agent picker and the CLI schema doc Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: run an agent runnable once when it is given no memory_id Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: accept previous_messages on agent runs, read-checking the files it quotes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: refuse an anonymous agent turn while one with the same memory still runs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: show the agent's settings in the raw-app runnable panel, size its button like the row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: offer an agent runnable memory_id or previous_messages after the agent's memory Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: take previous_messages in a memory-off agent's run form, type agent attachments as s3object Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: file an anonymous agent turn as a conversation, so its memory is collected and its turns serialized Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: own anonymous agent conversations under a fixed name that fits created_by Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: own anonymous agent conversations as anonymous and keep them out of conversation lists Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: point file_chat_turn at the anonymous conversation owner Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: title the runnable picker after what it lists, in sentence case Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: start a chat with local history listing its stored conversations Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: chat through a raw app's agent runnable with { wmill, runnable } Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: key an agent runnable chat's local history by its app as well Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: address review findings on agent runnables Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: offer memory_id to an agent runnable over an older auto memory Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: drop inherited static inputs from an agent runnable, show the memory-off note only when it is off Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
718aad7396 |
feat(cli): sync an app's custom path as a workspace-specific file (#11786)
* fix(cli): keep a raw app's custom_path on sync pull The pull rendered raw_app.yaml without custom_path, so every pull removed the line and every push --dry-run listed the file as modified, while the deployed app still had it and push still sent it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): send custom_path on app update only when it changed The backend requires admin for any update carrying custom_path, so the value a pull now writes into raw_app.yaml made every non-admin push of that app fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(cli): sync an app's custom path as a workspace-specific file Unless app routes are workspace-prefixed, a custom path is unique across the instance, so a value carried in the app file every workspace shares can never be promoted. Sync now renders it as <app>.<workspace>.custom_path.yaml next to the app folder, always workspace-specific. A push applies only the target workspace's file and leaves the deployed custom path alone without one; a checkout that still has custom_path in its app file converges on push, and the next pull moves it out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(cli): drop the custom_path rationale repeated from changedCustomPath Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): apply a custom path pushed with its raw app, and converge a cleared one The raw-app bundle collapse kept one change per group and dropped the custom-path file grouped with it, so a push editing both deployed only the app. App files and their custom-path file now group under the app path in both folder layouts, and the collapse keeps the custom-path change. A cleared custom path (custom_path: '') has no file in the export, so the push diff listed it as added forever; an empty value with nothing deployed is now in sync. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): never read a file inside a flow or app folder as workspace-specific The workspace-name segment of the workspace-specific patterns spans '/', so a raw-app asset such as settings.prod.custom_path.json was taken for a workspace's file and dropped from the pull. Like fileset children, files inside a flow or app folder are content of that item, whatever their name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): recognize a custom-path file only beside its app isCustomPathFile excluded app and flow folders but still matched a fileset child such as data.fileset/settings.custom_path.json, so a push dropped edits to it and a pull renamed it. A custom-path file is now identified by where it sits: its name is <app>[.<workspace>].custom_path.<ext> and no part of its directory is an item's folder. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
526da60da9 |
feat: let raw app backend runnables import each other (#11777)
* fix: iterate workspace picker nav items without spreading a NodeList Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: let raw app backend runnables import each other Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: preview only imported sibling runnables and reserve the main id Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: resolve a module's workspace imports from the entrypoint's folder Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: scope run-mode app scripts to their app and key bundles on module imports Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: clone app_version_lite into forks with remapped app_script ids Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: update the run-mode raw_code comment for app-scoped ids Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: run module-bearing app scripts only from the deployed version Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: run deployed inline code only through the deployed version's rows Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: in-workspace app viewers run through the deployed rows Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: let the app embed token read the app's lite value Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: pass sibling modules to the agent-worker Python preview resolver Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: list the lite route in the app embed scope comment Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: update ee-repo-ref to 455f98540fb042d4f624dcec681dab88b2c8df22 This commit updates the EE repository reference after PR #883 was merged in windmill-ee-private. Previous ee-repo-ref: 927d3592a6b2127ffe16fb14eb47f5bd66afc026 New ee-repo-ref: 455f98540fb042d4f624dcec681dab88b2c8df22 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
813c080d46 |
feat: sandbox new low-code and raw apps by default (#11760)
* feat: sandbox new low-code and raw apps by default Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: navigate the top page from plain links in a sandboxed low-code app Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: allow clipboard and fullscreen in sandboxed raw-app frames Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: leave non-http links to the browser in the sandboxed app frame Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: let a link's own click handlers run before relaying it out of the frame Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: read link attributes so SVG anchors relay correctly Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: tidy the app deploy drawer to the brand guidelines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: show enabled frontend api scopes as badges, rename runs-as section Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep frontend api access collapsed by default, badges next to its title Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: lead the run-on-behalf-of section with the user picker Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: explain publisher execution and WM_END_USER_EMAIL in the run-on-behalf-of tooltip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: shorten the run-on-behalf-of tooltip, mention viewer data access for raw apps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: tell the AI what breaks in a sandboxed raw app and that turning it off is a security risk Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: warn in the deploy drawer when an app is not isolated Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: drop the sandbox toggle help line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: say when to turn sandbox isolation off in the toggle tooltip Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: show who a non-deployer's app runs as, read-only Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: show a new app runs as the deployer, gray read-only user line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: read-only on-behalf-of display as an opt-in selector prop Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: show a folder's default run-as user on a new app instead of the deployer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: deploy an app under a group folder default without a mismatched email Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * revert: leave a new app's run-as user unselected, as on main Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: warn in the app deploy drawer when a deploy changes the run-as user Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: snapshot the deployed policy so later edits don't change the saved app Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c5e6f67d53 |
feat: give full-code app previews the deployed app's window.ctx (#11763)
* feat: give full-code app previews the deployed app's window.ctx * chore: pin the UI Builder build that sets window.ctx in the preview * fix: hold the editor preview until the viewer belongs to the app's workspace * fix: let Rebuild retry a failed viewer lookup in the editor preview |
||
|
|
b7b3306195 |
feat: read data as the job's identity, viewer is opt-in per runnable (#11744)
* feat: connect a data table as the job's own identity unless the runnable opts into its viewer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: key cached results by the data table mode and keep the flag across ai edits Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: hash the cache key's mode and viewer as fixed fields so no argument name can forge them Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: update ee-repo-ref to 2f74548ad1ec50c8e1faf17e42d5648160e833f1 This commit updates the EE repository reference after PR #878 was merged in windmill-ee-private. Previous ee-repo-ref: 4ad768a777fff9f1ecc86a2803bc27d80f8242d6 New ee-repo-ref: 2f74548ad1ec50c8e1faf17e42d5648160e833f1 Automated by sync-ee-ref workflow. * feat: rename the flag to viewer_data_access and apply it to object storage permission rules Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: describe viewer_data_access as covering object storage rules too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: update ee-repo-ref to 0ffb633473c5465513576afc6f54d18f93c7f1e1 This commit updates the EE repository reference after PR #879 was merged in windmill-ee-private. Previous ee-repo-ref: e9e06a9eb94168f46b378276b01fa0117dc7d8ed New ee-repo-ref: 0ffb633473c5465513576afc6f54d18f93c7f1e1 Automated by sync-ee-ref workflow. * feat: show the viewer data access control as an icon button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
2c6de9d896 |
fix: keep the app editor's parent_version out of deployed apps (#11719)
* fix: keep the app editor's parent_version out of deployed apps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: drop parent_version when deploying an app draft Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
36ea2da0bf |
warn when a raw app sql viewer-identity input is not a ctx field (#11704)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
26afeecbd5 |
feat(cli): declare app sandbox and frontend api scopes in app yaml (#11703)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
54eeb451e4 |
refactor: remove vue as a full-code app framework (#11690)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
818ddd5d31 |
feat: default new raw apps to react 19 and ask for the data setup (#11586)
* feat: default new raw apps to react 19 and ask for the data setup Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: say what app new --schema writes and soften the already-set-up wording Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: resolve bare init_app table names in the app schema, fix --schema help Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
ede4103b00 |
feat: share AI guidance with the CLI skills and lint flow groups (#11397)
* feat: lint AI agent tool names and flow groups in wmill lint * refactor: assemble chat and CLI AI guidance from one topic table * feat: share flow groups, reuse and pipeline guidance with the CLI skills * feat: share raw app, data table and secret guidance between chat and CLI * docs: document the shared AI guidance source for contributors * fix: keep wmill lint running on flows with malformed collections * fix: reject skill descriptions that are not plain YAML text * fix: tighten fence typos, script base scope and app prompt order * fix: skip tool name checks on agent steps linked to a saved agent * fix: catch any misspelled prompt fence and soften the tool name claim * fix: align cli eval harness with the files and steps wmill init adds * fix: drop cli eval checks that expect unrequested deploy commands * fix: list ansible as mainless and c# Main in script base guidance |
||
|
|
e1e3692fbc |
feat: data table roles in the DB manager and raw apps (#11139)
* feat(datatables): put a data table's connection under Postgres roles A data table backed by the instance database resolved to exactly one Postgres connection, `custom_instance_user`, for everyone who could reach it at all. There was no way to say this job reads, that one writes, this one never sees the salaries table. A data table role is now a real Postgres login on the cluster, defined once for the instance by a superadmin and named exactly as they named it. A script that declares `-- role analytics` connects as `analytics`, and Postgres decides what it may touch — grants are ordinary SQL. Windmill answers only "may this caller ask for this role", from the tenant lists on the data table entry: `u/alice`, `g/analysts`, `f/finance` or `*`. A data table with no `permissions` block behaves exactly as before. Everything that opens a connection on someone's behalf goes through one chokepoint, `get_datatable_resource_from_db`, which takes the identity explicitly and fails closed when there is none. The role logs in as itself — never `SET ROLE`, which a script could `RESET ROLE` its way out of. A fork's data table entry becomes a pointer at the workspace that governs it rather than a copy of it. The settings clone used to hand a fork a byte-identical entry naming the parent's database, which a fork admin could edit to grant themselves `admin` there; a pointer has nothing local to edit, and its tenants are evaluated as a member of the governing workspace, by email. `permissions` is stripped from the workspace export and ignored on import: tenants name principals of one workspace, and a settings push is not where an access decision should be made. Operations that see the whole database whatever the roles grant stay with the governing workspace's admins: editing the roles, a migration that declares none, and opening a replication stream for a Postgres trigger or capture. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): gate the paths that reach a whole database as admin Auditing what still resolved through the unchecked resolver turned up three that act for a caller and hand back the admin connection: `resolve_pg_source_checked` (behind schema export, the full-schema read, database creation, import and the forked-database drop), the connection test, and the schema snapshot a fork clone takes of its parent. On a data table under roles each let any workspace member — or a fork admin who is nobody in the governing workspace — read or copy the whole database whatever its roles grant. All three now require admin reach on the governing workspace. A dump taken under a restricted role would be a silently truncated copy rather than an error, so refusing is the only right answer for the copy paths. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): confine roles to the instance database, and stop a fork reaching the parent's bookkeeping A data table role is a login on Windmill's own Postgres. Nothing stopped a workspace admin putting a *resource-backed* data table under roles, at which point the executor dialled the host that resource names — one the admin chose — with the role's real cluster password, and `CONNECT` is granted to every registered instance database. Both ends now refuse: the permissions endpoint rejects the save, and the chokepoint refuses to substitute credentials on a non-instance entry rather than trusting the record it read. Two more places reached the governing database without answering to it. The initial-migration generator returned a `pg_dump` of the whole schema to any member. And the migration rename/delete cascade followed a fork's pointer into the parent, so a fork admin renaming or removing their own local entry relabelled or wiped the parent's `_wm_migrations` — after which the parent re-runs every migration from zero. The remote half is now skipped when the entry resolves into another workspace, which is also just correct: a fork renaming what it calls a data table changes nothing about the data table. Also: revoking a tenant now bounces the replication streams of every workspace holding an entry that resolves here, not only the governing one, so a fork's trigger stops rather than living on inside its open connection; the instance role catalog and the governing workspace's tenant lists are no longer returned to someone who cannot edit them; and the tenant rename dedup collapses non-adjacent duplicates, per role rather than once any role changed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): fail loudly where a role or a pointer can be left half-recorded Three ways the feature could end up in a state nobody could see or undo. Creating a role writes the cluster first and the catalog second, but the catalog write was an `UPDATE` that matched nothing when the instance Postgres settings row was absent — leaving a live login with a password nobody recorded: invisible to the catalog, un-recreatable because the name is taken, and un-deletable because there is no entry to delete. It now errors, so the operation is retryable once the row is restored. Deleting a workspace only nulls the fork lineage; the data table entries pointing at it are left resolving to nothing. Sweeping them is not an option — turning a pointer back into a copy would hand each fork the database outright — so the delete now names the data tables it stranded, and resolving one says which workspace is missing rather than reporting a data table this workspace never had. `InstanceDatatableRole` derived `Debug` while holding a Postgres password; it is now hand-written so `{:?}` on the catalog cannot put a live credential in a log line. Adds the two branches the reviews found unpinned: a caller who is not a member of the governing workspace at all, and `NoIdentity` — the compatibility path for an agent worker that predates this and sends no job id. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): unbreak two operator messages and two comments that described other code The two strings this branch added for states an operator hits once — the catalog write that matched nothing, and the delete that stranded a pointer — were collapsed from their multi-line form with the indentation left in, so both rendered with a fourteen-space gap mid-sentence. `list_datatables` claimed to report a chain it cannot follow and then dropped it; it does drop it, and the comment now says why that is the right place to stay quiet. The non-superadmin check in `edit_datatable_config` was introduced as also covering references, which it does not and need not: `reference` is overwritten from the stored entry for every caller before the check runs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): serialize role catalog mutations, and state each helper's authorization contract The catalog is one JSON document, so create, rename, enable and delete are all read-modify-write. Two concurrent creates read the same snapshot, both succeed in the cluster, and the second write drops the first — leaving a live Postgres login with a password nobody recorded, which is the exact state the delete path exists to prevent. Every mutation now runs in one transaction holding an advisory lock across the read, the cluster DDL and the write, so a lost update cannot happen and a failure rolls the whole thing back. The DDL helpers take that transaction rather than the pool, which is what makes the lock cover them. Their statements moved off `sqlx::raw_sql`: the simple protocol is only needed for genuinely multi-statement SQL, and its future is not `Send`, which an axum handler holding the transaction requires. Each of these is one statement anyway. The new cross-crate surface now says what callers must do. `read_role_catalog` returns plaintext credentials; `create`/`rename`/`set_login`/`drop_instance_role` and `converge_connect_grants` mutate cluster-wide state; `read_datatable_entry` reads a workspace's raw config. All of them are superadmin-gated by their current handlers, but nothing said so at the definition, which is where the next caller looks. Also: the roles table reloads after a failed login toggle instead of leaving it claiming a flip that did not land; the rename affordance is the design-system `Button`, not a raw one; and `resolve_datatable_pg_as_caller` drops a `role` parameter no caller ever filled — browsing resolves as the data table's default until the database manager grows a picker. Why role passwords stay a plain `String` while the instance user's password beside them is a `StringOrSecretRef`, asked three times across reviews: that one is a secret ref because an operator supplies it and may want it from their own backend, while these are minted here and never entered by anyone, so there is nothing for a ref to point at. Encrypting generated secrets at rest is a separate change that would take the replication password with it. Now said at the field. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): give the role catalog its own row, out of reach of the config machinery Putting it inside `custom_instance_pg_databases` was the wrong call, and it cost two ways. The catalog serializes a generated Postgres password per role, and that row is the operator-facing instance config, so the passwords reached `get_instance_config` and its YAML editor — a live cluster credential in a response body, a UI field and any log of either. Worse in the other direction: `to_settings_map` strips the catalog, so a full-row upsert of that key writes the row back without it and the catalog is gone, while the cluster keeps every login it described. `custom_instance_replication_pwd` is the precedent and says exactly why — a generated secret, written only by the server, never operator-authored, hidden so the config machinery cannot read, rewrite or drop it. The catalog is the same thing, so it now has the same shape: `datatable_roles`, in `HIDDEN_SETTINGS`, `PROTECTED_SETTINGS` and the agent-worker denylist. No redaction to keep in step with three code paths, and no way for a neighbouring write to take it out. Two races on the same shared documents. `edit_datatable_config` read the stored data tables outside its transaction and then wrote the whole `datatable` document, so a permissions save committing in between was silently rolled back; it now reads under `FOR UPDATE`. And `set_datatable_permissions` validated role ids against the catalog before opening its transaction, so a deletion in between let it write a deleted role back — including as the default, which every later job then fails on; it now holds the catalog lock and the settings row across validation and write. Completes the authorization contracts the previous commit claimed but did not finish: `read_datatable_entry` (which it named and missed), `resolve_governing_datatable`, whose whole job is to answer for a workspace the caller may not belong to, and `converge_connect_grants_with`, which had not inherited its wrapper's. Also the generic Python SDK reference: `_format_py_params` learned the bare `*` last time, but `extract_py_functions` is a second formatter and still rendered `datatable(name, role)`, so code written from that page passed a keyword-only argument positionally. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): make the concurrency test pin the handlers, and the contracts describe what is enforced The concurrency test reimplemented the read-modify-write inline, so deleting the lock from all three handlers left it green — it pinned Postgres, not the code it was written for. It now drives `create_datatable_role` twice concurrently and asserts the catalog kept both names. Checked the way the last one should have been: removing the lock from the handler makes it fail with "wmtest_a_… is a live cluster login the catalog forgot". The contracts added last commit were stricter than this PR's own callers, which is worse than none — the next reader sees a rule already broken and learns to ignore it. `read_role_catalog` said superadmin-only while two of its four callers are open to any workspace member, and `converge_connect_grants` said superadmin while `set_datatable_permissions` reaches it as a workspace admin. Both were fine on substance: the rule that actually holds is about the credential never reaching a response, log, audit record or export, not about who may call. They now say that. `read_datatable_entry` gets the same treatment rather than the one the earlier message claimed for it: it is the primitive every resolution goes through, so it is deliberately open, and what must not escape is `permissions` — it names the governing workspace's users, groups and folders. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): close the last ways a role or a pointer can be left pointing at nothing The raw settings readers hand back whatever is in the row, so moving the catalog into its own `global_settings` key protected the config machinery and left `GET /settings/global/datatable_roles` and the settings listing returning every live password. Both now filter that one key. The neighbouring `custom_instance_replication_pwd` has the same shape and is not touched here: it predates this and widening the fix to it is a decision about an operator workflow, not a consequence of this change. Three ways a save could leave something resolving to nothing: A permissioned data table could be moved to a PostgreSQL resource. The block was carried across as a server-owned field, the runtime refuses roles on a resource-backed table, so the save succeeded and every job afterwards failed. Refused instead — turning roles off first is one step, and it keeps discarding an access decision something somebody chose. Renaming a governing data table left every fork pointing at the old name: the data table disappears from their pickers and their jobs stop, with nothing in the renaming workspace to suggest why. The rename now follows into the pointers in the same transaction. Deleting one cannot be followed the same way, so it is reported instead — the response names what it stranded, the way deleting a workspace does, and the fork's own error already says which workspace is gone. Also: `ensure_instance_db_grant_options_unchecked` claimed superadmin while the permissions handler reaches it as a workspace admin (the same class fixed last commit, one instance missed); the role entry kept an `instance_config_schema` derive it no longer needs; `write_role_catalog` was the one writer of that table not stamping `updated_at`; and the concurrency test dropped its roles only on success — a failing run is exactly the one that creates them without recording them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * refactor(datatables): put the role catalog in its own table, not in global_settings Five findings across three rounds were all the same choice. A set of live Postgres credentials was living in `global_settings`, which has generic read, list, write, config-export and CLI round-trip paths that know nothing about what they carry: the passwords reached the instance config and its YAML editor, a full-row upsert of a neighbouring key erased the catalog, `GET /settings/global/{key}` and the settings listing returned them raw, and this round the redaction that fixed the last two turned `wmill instance push` into something that wipes every password — a fix breaking the assumption the previous fix made. `POST /settings/global/datatable_roles` could also empty it outside the lock. The approved plan offered a table or `global_settings`, so this is the other option it already allowed rather than a new design. `datatable_role` is a table: no generic settings path can read it, list it, export it, write it or round-trip it, so none of the five needs a guard. The redaction, the hidden/protected/agent-denylist entries and the JSON document all go with it. One row per role also removes the read-modify-write the concurrency work was about: two concurrent creates are two inserts, and the unique index on `name` is what settles a collision. The advisory lock stays for the one window rows do not cover — `CREATE ROLE` is invisible to another transaction until commit, so without it both creates pass their `pg_roles` check. Also from this round: rename mappings are checked against the configuration they claim to describe, since fork pointers are rewritten from them — a caller could otherwise submit `main -> missing` against an unchanged config and repoint every fork of `main` at a name nothing has, and `A -> B` plus `B -> C` moved what pointed at `A` all the way to `C`. And the warning naming forks a delete stranded reached the response but not the screen: both the data table settings save and the workspace delete now show it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): validate a rename against the save it describes, and re-check under the locks Three from the round, all about deciding on state that could already have moved. A permission save resolved the data table and checked it was instance-backed before taking any lock, then wrote under one. A config save committing in between could move the table onto a PostgreSQL resource — recreating exactly what the transition guard refuses — or rename it, in which case the write targeted a key that no longer existed and reported success having changed nothing. It now re-resolves and re-checks on the locked state. Rename validation checked that the source existed before and the target existed after, which still accepts `main -> decoy` against a save that keeps both: every fork of `main` then follows onto a different data table, silently, because it keeps resolving. The rule is now the actual old-to-new key transition — a source may only survive if another rename took its name, and a target may only pre-exist if another rename freed it. That also stops two sources sharing one target, and it admits a swap, which the previous guard refused: `datatables` is keyed by name, so a swap cannot be done one save at a time, and refusing it was a regression against main. The pointer cascade now runs in two passes through a temporary name, the way the migration cascade one layer down already handles the same shape, so `A -> B` with `B -> C` moves each pointer once from what it named before the save. The tenant mutators say what they are for: they write an access decision for any workspace named, with an arbitrary mutation, and exist for the transaction that frees or renames a principal. Editing a decision on purpose belongs in the permissions endpoint. Carried in the same change: the stranded-fork list is a field rather than a phrase to grep out of a success string; the pointer cascade matches with `EXISTS` instead of a `LIKE` over the whole document, so a workspace whose pointers name something else is not rewritten to a byte-identical value under an exclusive lock; and `InstanceDatatableRole` drops the serde derives left over from the JSON document, one of which would emit `pwd`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): cascade on the leave route that is used, gate migrations before the admin connection, and drop a role atomically The tenant cascade on leaving went onto `/users/leave`. The UI and the generated client call `/workspaces/leave` — a different handler in a different crate with the same name — which deleted the membership and left `u/<username>` in the tenant lists. Leaving and rejoining therefore restored the access the leave was supposed to end, and a later account taking the username would have inherited it. The regression test drives the route the client actually calls; without the fix it fails with "leaving kept the tenant". The migration endpoints authorized too late. `run_datatable_migrations` opened the data table's admin connection, created `_wm_migrations` and read it before reaching the per-migration role check — so with nothing pending, nothing was checked at all. Rollback returned before its check when nothing was applied, and the status endpoint had none. All three now ask, before any connection is opened, whether the caller can reach the data table as any role at all; which role a given migration runs as is still decided per migration, and by the executor after that. Deleting a role committed the cluster drop and the catalog row, then swept the tenant lists in separate transactions. A sweep failing part-way left workspaces naming a role nothing can connect as, while the retry answered `NotFound` because the catalog entry was already gone. The sweep now runs in the same transaction, so the drop, the row and every tenant list commit together. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): refuse to copy a data table that is under roles pg_dump carries no roles and the import runs with --no-privileges, so a copied data table arrives owned by the admin connection with no GRANT for any role. The settings clone brings `permissions` across, so the fork's tenants pass Windmill's check, connect as the role they were given, and are denied by Postgres on everything: an entry that reads as configured and answers nothing. Refuse the copy — in the import endpoint before any data moves, and in the fork path the CLI takes. Replaying the source's owners and ACLs into the clone is what lifts this, and is a change of its own. Dropping `permissions` from the copy instead would be the unsafe half, since the copy holds the parent's rows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): refuse the clone's database too, not only its data A clone is two endpoints: `create_pg_database` then `import_pg_database`. Only the second refused a data table under roles, so a fork asking to clone one created and registered an empty `wm_fork_…` instance database and then failed — and nothing collects it, since `drop_forked_datatable_databases` only drops entries carrying `forked_from` and no entry names this one. Refuse in both, so the clone stops before a database exists. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * nit worker error msg * fix pg_dump stuck on version 17 on nix * fix(datatables): refuse a malformed role annotation instead of ignoring it `-- Role operator`, `-- role operator;` and `-- role operator -- why` all failed the annotation parser's exact-match rule, so the query fell through to the data table's default role and ran, silently, under a login the author did not choose. Naming a role exists precisely to not do that. A leading comment whose first word is `role` is now an annotation attempt: the keyword matches case-insensitively, one trailing `;` is tolerated, and anything else is an error naming the line. Only callers that already know the target is a `datatable://` reference ever run this, so ordinary SQL keeps its comments. Also bumps the dev shell's postgres client to 18 — it trailed the server the dev database runs, which takes out every data table export, clone and fork-with-data. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): refuse a malformed role query string instead of ignoring it `?Role=analytics`, `?role=` and `?x=1&role=…` all fell through the reference parser's exact-match rule, so the connection resolved to the data table's default role and ran under a login the caller never asked for — the URI half of the same trap as a malformed `-- role` annotation. The key now matches case-insensitively, and anything else in the query string is an error naming it; `role` is the only parameter a reference takes. Callers that only need the entry keep a lenient `datatable_ref_name`, since they never act on the role. The DuckDB `ATTACH` parser propagates it rather than attaching under the default. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR * fix(datatables): carry the role annotation into the row_to_json retry The retry rebuilds its SQL from `pruneComments(code)`, so the leading comment block never reached the second attempt — and with it the `-- role <name>` line that decides which login the query runs as. The retry connected as the data table's default role instead, so a query the first attempt was denied could succeed on the second, reported as "recovered with the row_to_json fix". Carry the leading comment block over. The retry itself is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * chore(datatables): don't mount the roles UI until the ACL editor lands Enforcement ships first. The permissions drawer is what turns roles on, and the catalog section is what creates them — both are only useful once there is a way to grant a role the privileges it needs, which arrives with the ACL editor. Left mounted they would offer a feature whose other half does not exist. The two components are complete and reviewed; only their call sites here are commented out, with a note pointing the follow-up PRs at them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): honour `-- role: x`, and fix the DuckDB attach test Two review findings, both real. `attach_datatable_parses_name_and_role` never compiled: `parse_attach_datatable` returns `Result<Option<_>>` now and one call site kept a single `unwrap`. Its `?Role=analytics` case also asserted a refusal, contradicting the parser in the same commit, which matches the key case-insensitively. Replaced with the cases that are genuinely malformed, and a positive one for the cased key. `-- role: analytics` fell through to the default role — the silent fallback the strict parser exists to remove, for the spelling most likely to be typed. The keyword now accepts an optional colon, attached or spaced, while a word that merely starts with it (`rolebased`) is still not an attempt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): clone a fork's pointer instead of failing after the copy Forking a fork with cloning left an orphan database. The preflight resolves the pointer and sees the governing entry, so both endpoints ran and filled the new database; `apply_forked_datatable` then refused the inherited pointer and rolled the fork back, stranding a registered `wm_fork_*` that no entry names and whose name blocks the retry. Refusing earlier would have been the smaller change, but forking a fork and cloning worked before pointers existed, so it would trade an orphan for a regression. Resolve what the pointer names and write the terminal entry the clone needs: the whole `database` object rather than a patch of its `resource_path`, since a pointer has none, and `reference` removed with it. Also accepts `-- role=x` and `-- Role = x`, two more spellings that fell through to the default role. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): refuse to roll back the catalog while roles exist The down migration dropped the table and left every role behind: live Postgres logins whose passwords only that table carried, so after a revert Windmill could neither use, disable nor delete them, and re-applying could not recreate them because the names were taken. Cleaning up here is not possible either — dropping a role means reassigning what it owns in every instance database, and a migration runs in one — so it now refuses while the catalog is non-empty and says to delete the roles through instance settings, which does the cluster work. Also enforces the instance-only invariant the resolved-pointer clone relies on rather than only asserting it in a comment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * refactor(datatables): settle clonability in one place, before anything is created A clone is three stages a workspace apart — `create_pg_database`, then `import_pg_database`, then `apply_forked_datatable` inside the fork transaction. Only the third can roll back, and `CREATE DATABASE` is not transactional, so any refusal that lives there strands a registered `wm_fork_*` that no entry names and whose name blocks the retry. That orphan has now been fixed three times, most recently reintroduced by a guard added one commit ago. Patching each new refusal into the first endpoint is not the fix; having two places that can refuse is. `ensure_datatable_is_clonable` now answers every reason a copy can be refused and returns what it resolved, and the stage that writes the entry only does the work. Also takes an ACCESS EXCLUSIVE lock before the rollback guard counts, so a role created concurrently cannot slip between the check and the drop. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjfMkJyKzodxkobqGZ6Lqb * fix(datatables): let a retried clone reclaim its own leftover database A clone creates its target database one request before it copies into it, and the fork that would name it is written a request after that. Any failure in between — a pg_dump error, a bad restore, a dropped connection, the source's roles changing mid-flow — left a registered `wm_fork_*` that no entry names, and every retry then failed on its name. This predates data table roles. `create_pg_database` now reclaims such a leftover before creating: only a `wm_fork_*` database Windmill registered as a data table database and that no data table or ducklake entry names, in any workspace, archived ones included. The drop never terminates connections, so a clone still copying into it makes the reclaim fail instead of being cut off. It is limited to callers who administer the source — reaching it is not enough, since on a data table without roles every member reaches it — and anyone else gets the refusal an existing database always got. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Revert "fix(datatables): let a retried clone reclaim its own leftover database" This reverts commit |
||
|
|
0af7675588 |
fix: keep an app's deployed policy on wmill push (#11049)
* fix: keep an app's deployed policy on wmill push Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: keep a first push's file-stated app policy Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: deploy a file-stated viewer app as viewer, not publisher Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: never put a repo-stated run identity on the wire Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: send the deployed run identity only when the push may claim it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: let a file-stated execution mode win in both directions Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * refactor: drop the app-file execution mode helper with no caller Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * feat: warn before a raw-app push takes over the run-as user Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: keep an app's run-as user when a push only deletes one of its files Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * refactor: settle an app's ownership check before any content parsing Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: share one rule for which raw-app files a push sends Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: stop tracking raw-app files no push ever sends Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * test: bundle for real instead of stubbing the module for every suite Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * docs: record why a module mock cannot be undone by afterAll Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * fix: keep tracking a runnable whose file shares a bundle-excluded name Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c * test: pin both halves of the backend runnable rule Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X47gNFqf1SsA67zTm71f8c --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
5f3f99ba69 |
fix(cli): keep permissioned_as on single-item push, as sync push does (#11000)
* 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 |
||
|
|
fce635d3c4 |
feat: guest app execution mode, a role that takes no seat (#10929)
* feat: guest app execution mode, a fourth role that takes no seat Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: make the guest grant a server-minted label, not a declarable scope Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * chore: pin ee-repo-ref to the guest session companion branch Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: close the relabel hole, guest embed tokens, read-path switch, custom-path entry Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest tokens are not rescopable and guest embed tokens keep the sentinel Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest-derived tokens share one constraint set; gate sign-in on guest discovery Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: the label alone governs a guest; refuse guests with accounts; unserialize discovery Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest discovery fails closed; SAML aborts if the guest cookie write fails Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * refactor: enforce the guest switch once at the auth door; sign-in for a guest of another app Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest app-mode decided once at the on-behalf resolver; clear a stale guest session before offering another app's sign-in Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: a guest may use anonymous apps; await the stale-session logout; trim comments Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: a guest's path confinement waits for the app's mode, so anonymous apps stay open to it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest target survives http (Lax cookie), rides SAML RelayState; tell account holders on arrival * fix: a guest uses an anonymous app as itself; S3 uploads confined by app mode * fix: a guest upload needs an app policy; a missing app does not skip the confinement * fix: guests are gated on the Enterprise plan server-side; pin ee-repo-ref * fix: the guest plan gate fails closed on non-enterprise builds; settings report the effective switch * fix: guest controls read the plan, not the key; gate the guest tests on the features they need * docs: tighten the guest session invariant comments * feat: 100 free guests per 30 days, then a quarter seat each on Enterprise and a hard cap elsewhere; superadmin guest list; refusals reach the page Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: the cap is exact, an account ends a guest session at the door, popups close, and guest mode survives the CLI round trip Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * feat: a superadmin switch over guests for the whole instance; the pre-existing-user flag keeps its meaning Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: drop the dead guest-access helper, name the instance setting once, guests tab states, CE save order Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: a guest app path is refused at the mint if it could widen the scope; the instance toggle waits for its reload Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guests stop at the launched-by-me job grant; canonical app paths at the mint and discovery; the toggle ends on the stored value Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: only the scope grammar's own characters bar an app path from guests, refused at deploy as well as at the mint Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: the deploy-time guest path guard checks the destination of a rename and refuses a leading slash Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: a workspace rename keeps the guest switch; the rename guard reads the deployed mode under the row lock Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * fix: guest_activity follows a workspace rename and goes with a workspace delete Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * chore: pin ee-repo-ref to the state-bound guest target Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * chore: pin ee-repo-ref; the guest cookie is never cleared by a callback Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * docs: the workspace-scoped guest_activity delete moves an instance-wide count; assert the mint records the guest Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * test: the seeded allowance is a day old, so only the mint can write today's guest_activity row Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BayTppRCstWX6qTf3LMco5 * chore: update ee-repo-ref to 1a10132e4f3cb442c7d0c2cf6e5d92d150bf6e07 This commit updates the EE repository reference after PR #769 was merged in windmill-ee-private. Previous ee-repo-ref: 32841072aa396bff91d30bd91854fa348cb3c439 New ee-repo-ref: 1a10132e4f3cb442c7d0c2cf6e5d92d150bf6e07 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
337154b830 |
fix: connect to dev server instead of localhost (#10912)
* 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> |
||
|
|
b8bf539c3f |
fix(cli): keep svelte component styles in the raw-app bundle (#10838)
* 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> |
||
|
|
2748d019f5 | fix(cli): load the app's ESM svelte compiler, not its CJS one (#10622) | ||
|
|
81ba9611eb |
feat: deploy a raw app from its sources, bundling them on a worker (#10500)
* feat: deploy a raw app from its sources, bundling them on a worker * refactor: bundle raw app sources with the wmill CLI instead of a second bundler * fix: address review findings on the raw app source deploy * fix: bound bundle decompression, drop the npm dependency on slim workers * fix: stop minting jobs:run for the source deploy, share the decode budget * feat: let an MCP token grant the scopes its selected tools require * fix: carry a caller-held extra scope through the MCP proxy * fix: confine the run scope to the proxied request instead of the token * fix: mint the run scope only for a token that names the tool * fix: require write access before compiling, and state the grant where it is granted * fix: let the database decide write access instead of restating its policies * fix: answer a write denial with 403, not 401 |
||
|
|
2105540cca |
feat: add session recording to wmill app dev (#10457)
* feat: add session recording to wmill app dev * fix: harden dev recorder shell, bundle staleness guard and save route * fix: keep dev-server recordings out of the raw app sync diff * style: drop em dashes from new cli comments * fix: tighten dev recorder save route origin, naming and io * test: pin that only the root recordings folder is skipped * fix: survive an oversized recording upload and match paths on windows * fix: keep the app at the root and settle runnables stranded by a reload * fix: make the recorder bundle hash stable on a crlf checkout * docs: state the preflight-free content type the origin check guards * test: build the sync-skip fixture with the platform separator * docs: align the origin-guard test comment with the code * chore: mark generated .gen.ts files as generated |
||
|
|
38b6099b4c |
fix: apply default workspace dependencies to raw app runnables (#10427)
* fix: apply default workspace dependencies to raw app runnables Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test: state the tree-path constraint in the raw app deps regression test Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: honor defaultTs when loading raw app runnables for lock generation Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: resolve defaultTs from wmill.yaml at every raw app runnable read Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: thread defaultTs from command entry instead of re-reading the config Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: give pushObj an options object for its optional arguments Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: reattach the pushObj JSDoc after the options-object refactor Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
9c37b0217c |
fix(cli): compile runes in .svelte.ts / .svelte.js modules (#10400)
* fix(cli): compile runes in .svelte.ts / .svelte.js modules The svelte plugin only ran on `/\.svelte$/`, so a rune module like `lib.svelte.ts` was bundled as plain TypeScript: the types were stripped and `$state(0)` survived as a call to an undefined global, blowing up at runtime with "ReferenceError: $state is not defined". Route those files through `compileModule`. It parses with plain acorn and chokes on TypeScript, so types come off first via esbuild's transform — which is what vite-plugin-svelte gets for free by running after Vite's own esbuild transform. `wmill app dev` picks this up too; watch mode builds its plugin list with the same `createFrameworkPlugins`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore: pin ui_builder to 1ffb28e Picks up the matching rune-module fix in the in-editor builder (windmill-labs/windmill-code-ui-builder#24), so `.svelte.ts` modules compile in the editor as well as through the CLI. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(cli): compile raw apps with the app's own svelte compiler Svelte 5.52.0 moved delegated event handlers off `element.__click` onto a Symbol-keyed map. A raw app supplies its own Svelte *runtime* via package.json, but `import("svelte/compiler")` resolves against the CLI, whose own svelte floats independently — so the two can land on opposite sides of that change and the app builds, renders, and has every onclick/oninput silently dead. Resolve the compiler from the app's node_modules instead, so compiler and runtime are the same install by construction, and raise the CLI's own floor past the break for the fallback path. Also pin ui_builder to 013bf67, which carries the matching fix for the in-editor builder (windmill-labs/windmill-code-ui-builder#25), and move the Svelte raw-app template onto the same range. Those two go together: the new builder rejects a runtime that sits on the far side of the ABI break from its compiler. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
9713e6074d |
fix: resolve svelte/style export conditions in raw-app CLI bundler (#10294)
The `wmill app dev`/`app bundle` esbuild config never set custom export conditions, so it only used esbuild's browser-platform defaults (browser/module/import/default). Packages that gate their entry points behind other conditions failed to resolve: - tailwindcss v4 exposes its CSS entry only under `style` (`@import "tailwindcss"` -> ./index.css) - flowbite-svelte exposes its entry only under `svelte` (-> raw .svelte) Enable the needed conditions, split by scope: - `style` + `module` are global (DEFAULT_BUILD_OPTIONS): `style` benefits any app (Tailwind, CSS libs), and `module` must be re-added because esbuild drops its auto-included `module` default once any custom condition is set. - `svelte` is gated per-app via conditionsFor(frameworks.svelte). It points at raw .svelte sources that only compile with the Svelte plugin (itself loaded only for Svelte apps), so enabling it globally would make a Svelte-dual-published import in a plain app hard-fail with no .svelte loader. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
86d1d160f0 |
fix(cli): fall back to esbuild-wasm on native host/binary mismatch (#9629)
* fix(cli): fall back to esbuild-wasm on native host/binary mismatch Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): guard tarball extraction, extend esbuild-wasm fallback to script bundling Address CI review: prevent tar-slip in esbuild-wasm package extraction, route codebase/script and inline-rawscript bundling through getEsbuild() too, and move the loader to utils. Add a unit test for the tar-slip guard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): make esbuild-wasm fallback concurrency-safe Address CI review (P1): memoize getEsbuild() on an in-flight promise so concurrent first callers (parallel wmill sync push) share one probe/download instead of racing, and give each extraction a unique temp dir so concurrent extractions can't clobber each other. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
b0c3b01d31 |
fix(cli): preserve user drafts on sync push and permissioned-as (#9381)
CLI deploys (sync push, set-permissioned-as) went through the same create/update endpoints as a UI "deploy from draft", which delete the draft at that path. That silently wiped teammates' in-progress drafts on every push. Add a transient skip_draft_deletion deploy flag (mirroring deployment_message) that the CLI sets; the backend then skips the DELETE FROM draft for scripts, flows, and apps. UI deploys are unchanged. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
2a780ad87a |
feat: resolve relative imports from local content in script/flow preview (#9233)
* feat: thread temp_script_refs into preview jobs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: resolve python preview relative imports from temp script refs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: use local relative imports in wmill script preview Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: use local relative imports in wmill flow preview Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: add temp_script_refs to Preview and FlowPreview openapi schemas Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: pass temp_script_refs to bun lockfile gen for no-lock preview Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: route script preview through shared buildPreviewTempScriptRefs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: resolve local relative imports in wmill app dev inline scripts Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address cubic review — bundle cache key, preview-mode gate, error masking Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * perf: skip dep-tree build when previewed script has no relative imports; narrow old-backend classifier Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address review issues (preview-only gate, bundle preview, app dev cwd) Three P1s flagged in repeated codex/pi reviews on PR #9233: - Gate _TEMP_SCRIPT_REFS extraction on JobKind::Preview (bun + python executors) and propagation in worker_flow on JobKind::FlowPreview. job.args includes caller-controlled request args, so honoring this key on deployed runs would let a caller swap import resolution to local content uploaded via /raw_temp. - run_bundle_preview_script now injects temp_script_refs into PushArgs.extra, mirroring run_preview_script — closes the silent data drop for the bundle preview path. - wmill app dev chdirs to the wmill.yaml root before buildPreviewTempScriptRefs and restores after, so the `cd <app>__raw_app && wmill app dev` invocation (cwd is the raw_app folder, no app_folder arg) still walks sibling workspace scripts like f/lib.ts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(ee): bump ee-repo-ref to 5b347d6 (handle_python_deps arity fix) Picks up the EE arity fix so cargo_test + check_ee_full compile cleanly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(ee): bump ee-repo-ref to 52e273d (agent-workers bundle path arity fix) Picks up windmill-ee-private 52e273d which adds the missing &None arg to compute_bundle_local_and_remote_path in windmill-api-agent-workers/src/ee.rs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(ee): bump ee-repo-ref to 2d6ffd3 (EE main merged in) Previous bump pinned an older EE commit, missing the audit-log object-store export module (EE PR #579, commit ec3cd35) and other EE main updates. The CE backend's `crate::ee_oss::anchor_audit_logs_s3_checkpoint_env_var` and `export_audit_logs_to_object_store` references need the new EE definitions. Merged origin/main into the EE branch and pinned the merge commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to b0c87b1272c25dca4aa9148c87fb024a9d9ef322 This commit updates the EE repository reference after PR #583 was merged in windmill-ee-private. Previous ee-repo-ref: 2d6ffd32c99bd93e79cf78675cb89499a81b17e1 New ee-repo-ref: b0c87b1272c25dca4aa9148c87fb024a9d9ef322 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> |
||
|
|
5e909b2b4f |
feat(git-sync): sync extra_perms for flows/scripts/apps (#9162)
* feat(git-sync): sync extra_perms for flows/scripts/apps * fix(git-sync): hash extra_perms, fix script no-op + up-to-date checks * refactor(git-sync): route extra_perms through /acls/* instead of update endpoints * fix(git-sync): dispatch raw_app perm changes via DeployedObject::RawApp * fix(git-sync): wire applyExtraPermsDiff into pushRawApp + per-change logs * feat(git-sync): opt-in tarball perms, no-op when yaml omits, audit logs, validation * fix(git-sync): replace remaining bool literal in EE-only trigger export call * fix(git-sync): raw_app /acls/* hits app table; refetch after create * fix(git-sync): drop unnecessary post-deploy refetch (folder perms not merged) * fix(git-sync): raw_app /acls/get; reject malformed local extra_perms * audit: distinct raw_apps prefix so dashboards can split raw_app ACL events |
||
|
|
43b18006f3 |
feat(cli): auto-infer args for wmill app push (#9091)
Run `wmill app push` from inside an app folder (e.g. `f/foo/my_app.app/`) with no args. The local path defaults to CWD, and the remote path is derived from CWD relative to `wmill.yaml`, with `.app`/`.raw_app`/ `__app`/`__raw_app` suffixes stripped. Either, both, or neither positional argument can be passed. Also resolves `file_path` against the user's original CWD before `resolveWorkspace` may chdir to the wmill.yaml root, so a relative `file_path` argument is interpreted from where the user invoked the command (previously it could resolve against the wrong directory). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
4b4aa0e303 |
fix(cli): bump svelte version in wmill app new template (#9084)
* fix(cli): bump svelte version in `wmill app new` template
The svelte5 template pinned `svelte` to `5.45.2`, but the Svelte
compiler bundled in `wmill app dev` emits `$.delegated('click', ...)`
calls. The `delegated` export was added later, so 5.45.2 doesn't have
it — esbuild warns `Import "delegated" will always be undefined`,
replaces the call with `void 0`, and the page crashes at first
event-handler bind (white screen).
Bump to `^5.55.5` so the compiler and runtime stay in sync.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(frontend): bump svelte version in raw_apps UI template
Mirror the CLI fix: the UI's `Add raw app` flow scaffolds a
package.json with `svelte: "5.45.2"`. That works today only because
the bundled rolldown worker also pins 5.45.2 — when the worker is
upgraded past 5.51.1, the compiler will emit `$.delegated()` and the
runtime won't have it, producing the same white-page crash that hit
the CLI.
5.55.5 still exports `event` (used by the current bundled compiler),
so this is forward-compatible: it works with the 5.45.2 compiler now
and won't break when the worker is upgraded.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
d6476862b3 |
fix(cli): forward HEADERS env var on every backend fetch call (#9075)
Several `fetch()` callers in the CLI bypassed `OpenAPI.HEADERS` and skipped the `HEADERS` env var, causing requests to fail behind auth gateways like Cloudflare Access (same shape as #6421): - `pushScript()` `/scripts/create` and `/scripts/create_snapshot` — regressed in #8936 when the call switched from `wmill.createScript()` (SDK) to a raw `fetch` for the `skip_if_noop` query param. - Script preview `/jobs/run/preview_bundle`. - App dev `/jobs_u/getupdate_sse` SSE stream. - `wmill docs` `/api/inkeep`. All four now spread `getHeaders()` and call `detectAuthGatewayChallenge()` so a Cloudflare/SSO challenge surfaces a clear error instead of an opaque JSON parse failure. Adds `test/headers_env_var.test.ts`: spins up an auth-gateway proxy that 403s requests missing `CF-Access-Client-Id` / `CF-Access-Client-Secret` and otherwise reverse-proxies to the test backend, then runs `wmill sync push` of a fresh script through the proxy. Negative case (no `HEADERS` env) verifies the proxy actually gates; positive case asserts every request including `/scripts/create` reaches the backend with the headers attached. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
8c67e5fdb7 | fix(cli): stable auto-numbered inline-script names in app pull (#9071) | ||
|
|
6df79a4572 | fix: scope dev server CSS reset to a layer so Tailwind utilities win (#9069) | ||
|
|
628ab5692e |
fix(cli): detect upstream auth-gateway HTML responses and add poll heartbeat (#9065)
* fix(cli): detect upstream auth-gateway HTML responses and add poll heartbeat * fix(cli): guard tar fallback, tighten cheap-path, case-insensitive ct, add tests |
||
|
|
0b959b8ec6 |
feat(cli): wmill-lock.yaml auto-fill + --rehash-only + path-prefix dedup (#8978)
* fix(cli): canonical lockfile hashes + lock upgrade migration to v3 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): use __app_hash subpath in rehash missing-entry check Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): run sync pull lockfile auto-fill regardless of changes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: regenerate system prompts for new lock and rehash-only commands Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): address review feedback on lock upgrade Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): drop v3 marker; always run fallback; fail-fast on unknown lockfile version Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): drop yaml-round-trip legacy hash variant; recover via --rehash-only Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): include legacy hash in script push staleness warning check Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * revert(cli): drop canonical hash formula; keep raw-bytes hashing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * perf(cli): reuse change-tracker map for sync pull lockfile auto-fill Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): address review feedback on rehash-only Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(cli): pin lockfile hash + yaml format and cover regression cases Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(cli): byte-stable snapshot tests for flow.yaml format Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(cli): add app and script-metadata yaml snapshot fixtures Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): address claude review on rehash-only Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(cli): factorize script-path to remote-path derivation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): address claude + cubic review (dry-run mutation, rehash short-circuit) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(cli): make rehash a subcommand and factorize fs walks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): normalize line endings in yaml snapshot tests for windows ci Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): address review feedback on rehash + auto-fill - Flat-layout scripts now clearGlobalLock before rehash write so legacy ./-prefixed duplicates get cleaned up (matches flow/app behavior). - Add MalformedLockfileError; sync pull auto-fill re-throws it alongside UnknownLockVersionError instead of silently warning + continuing. - Document the legacy step-removal false-negative in isFlowDirectlyStale / isAppDirectlyStale and the categorizeLocalFiles ignore-filter invariant. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
de0b6b1528 |
feat: workspace-shared ui/ folder reusable across raw apps (#8974)
* feat: add workspace-shared ui/ folder reusable across raw apps Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: add shared ui/ drawer in raw app editor sidebar Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: forward workspace shared ui/ to raw app editor iframe Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * all * all --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
eebe24d8b0 |
feat(cli): wmill dev with per-flow proxy and responsive Dev UI (#8529)
* feat(cli): add `wmill flow dev` subcommand with per-flow reverse proxy and launch.json Also generates .claude/launch.json for existing flow folders during `wmill init`. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: responsive dev layout and hide splitter for single-pane views Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: clamp flow graph height between minHeight and maxHeight Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(cli): enhance app new with Claude Desktop integration and better defaults - Add .claude/launch.json to generated app scaffold for Claude Code preview support - Add "Open in Claude Desktop?" prompt that creates a CLI session and opens it in Claude Desktop Code mode via the claude://resume deep link - Improve default CSS template with body background, system fonts, and padding Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): handle both .flow and __flow suffixes in wmill dev The flow detection in loadPaths only checked the configured suffix (dotted or non-dotted), so users with nonDottedPaths=true who had .flow folders (or vice versa) would see inline script edits treated as standalone script changes instead of flow changes. Now checks both suffix forms everywhere: type classification, folder path extraction, path stripping, and loadWmPath lookup. Also adds raw_app launch.json generation to init and sync pull. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(cli): update generated skills with dev workflow and preview commands Update cli-commands, write-flow, and raw-app skills to document the new local dev workflow (wmill dev --path, --proxy-port, .claude/launch.json). Add wmill script preview and wmill flow preview to all script/flow skills so agents know how to test without deploying. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): include path in dev URL and use open.default for browser - Append &path= to the printed/opened URL when --path is specified - Use open.default(url) instead of open.openApp for more reliable browser opening Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(cli): add Claude CLI/Desktop detection hints in wmill flow new Show contextual instructions for previewing flows based on available tools. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: regenerate auto-generated CLI skills for new dev flags Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): handle mixed flow suffixes in dev file watcher The ignore() function uses isFlowPath() which only checks the configured suffix (__flow or .flow), causing files in the other variant to be silently ignored. Bypass the ignore check for any file inside a flow folder and force flow type detection regardless of suffix configuration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(cli): drop default proxy in flow folders, open browser, add --no-browser Manual `wmill dev` in a flow folder should not implicitly enable the reverse proxy. Both proxy and legacy modes now open the browser; the new --no-browser flag opts out. Claude Code launch.json templates pass --no-browser so the IDE preview doesn't fight a system browser window. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(cli): gate dev broadcasts by --path and push currentLastEdit on connect When --path (or auto-detected flow path) is set, drop file events for any other path so the dev page stays locked to the requested resource and currentLastEdit can never reflect an unrelated edit. The connection handler proactively pushes currentLastEdit so the page renders without waiting for the first file change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(frontend): prefer WebSocket for flow round-trip when wmill dev is connected updateFlow used isInIframe priority, which routed Claude Code's iframe preview through postMessage (no listener) and silently dropped flow edits. Flip the priority: when the wmill dev WebSocket is open, use it (covers standalone tabs and Claude Code's preview); fall back to postMessage only when no WS is connected (the VS Code extension's iframe URL has no `local=true`, so it never opens one). Also stop assigning lastSent before a channel actually accepted the message, so a CONNECTING WS doesn't silently swallow the first change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(dev): url is source of truth for path; add workspace file picker Drops the server-side --path gate added in |
||
|
|
2f58a31d00 |
fix(cli): preserve case in raw-app runnable filenames (#8940)
* fix(cli): preserve case in raw-app runnable filenames The path assigner lowercased filesystem-safe names, so a raw-app runnable id like CamelCaseTSRunnable produced a YAML metadata file keeping the original case but a code file lowercased to camelcasetsrunnable.ts. On the next push, loadRunnablesFromBackend paired the two by case-sensitive name match, failed, and registered the lowercase code file as a separate empty runnable — surfacing as duplicate runnables in the app editor. Stop lowercasing in sanitizeForFilesystem and dedupe path assigners case-insensitively so case-only collisions still get a counter on case-insensitive filesystems. Also match content/lock files and the processed-id set case-insensitively in loadRunnablesFromBackend so repos already pulled by the buggy CLI can recover on the next push without re-pulling. Fixes #8939 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(cli): extract readSiblingLock helper, drop test #ref comments Address review: - Both call sites in loadRunnablesFromBackend now use the same case-insensitive lock-file lookup, so a partial-legacy repo with a mixed-case code file and lowercase lock (or vice versa) works in the orphan-code branch too, not just the YAML branch. - Remove `Regression for #8939 …` comments from the new tests; CLAUDE.md bans referencing the current task/issue from source comments. Test names already describe the behavior under test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(cli): update assigner-path assertions for case preservation Three tests in inline_scripts_failure_preprocessor_unit.test.ts asserted that the assigner produced lowercased filenames (get_users_data, step_b) from mixed-case summaries — that was the buggy lowercasing behavior. With case preserved end-to-end, the assigner now returns Get_Users_Data and Step_B. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
99bc96d0b2 |
feat: auto-strip UTF-8 BOM when reading local files in CLI (#8911)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
aaf3a19747 |
feat: async dep endpoints and queue-position logs in cli (#8895)
* feat: async dep endpoints and queue-position logs in cli Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: share logQueueStatus between dev.ts and job_polling.ts Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: continue polling on transient errors in job_polling.ts Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
12c08cc95c |
fix: populate wmill.d.ts schemas in wmill app dev (#8882)
* fix: populate wmill.d.ts schemas in wmill app dev Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: seed inferred schemas at wmill app dev startup Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
625d23fc85 |
fix: make sync pull produce consistent wmill-lock.yaml hashes (#8854)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
60211c1d19 |
feat: folder default_permissioned_as rules for ownership defaults on deploy (#8801)
* feat: add folder default_permissioned_as rules for ownership defaults on deploy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove unnecessary auth guard on default_permissioned_as — rules are advisory only Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: regenerate system prompts with new CLI commands Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address CI review findings — TOCTOU, race condition, email validation, type coercion Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add sqlx offline cache for test queries (fixes cargo_test CI) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address remaining review findings — incomplete request bodies, dead code, redundant import Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address remaining review findings — full script fields, reactive stores, catch-all validation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: app/schedule/trigger set-permissioned-as fetch remote first to avoid data loss Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: app set-permissioned-as avoid creating redundant app version Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: compact user/group toggle + select for folder default_permissioned_as rules Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: collapse default_permissioned_as section by default in folder editor Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: include default_permissioned_as in FolderFile CLI type for YAML round-trip Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: process folder.meta changes before items in push to apply new rules immediately Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: clone default_permissioned_as on fork/rename + add full lifecycle tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add no-op guarantee test — folder without rules behaves like before Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: rename cliBehavior to syncBehavior — more accurate scope Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
edfe074e98 |
fix: use runnable key for file naming in generate-metadata to prevent duplicate scripts in raw apps (#8740)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
b960598431 |
fix: hide deprecated cli metadata commands (#8699)
* fix: hide deprecated cli metadata commands Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: simplify generate-metadata guidance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
7485a5db04 |
remove dead legacyBehaviour param from metadata functions (#8695)
The legacyBehaviour parameter on generateFlowLockInternal, generateAppLocksInternal, and generateScriptMetadataInternal was never passed as true — the tree parameter alone determines the code path. Replace `!legacyBehaviour && tree` with just `tree` and remove the param from all call sites. getRawWorkspaceDependencies keeps its legacyBehaviour param since it has a real effect there. Also adds 6 integration tests covering generate-metadata lockfile generation and idempotency for scripts, flows, and apps. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
78ac28b4e0 |
fix(cli): address review — createBundle appDir, shared arg validation (#8587)
* fix(cli): address review — createBundle appDir, shared validateRequiredArgs, warn on fetch failure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(cli): add coverage for exit codes, arg validation, variable add, job logs, push --message Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): fix test — create script with required schema, relax push --message assertion Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
f40cdaf434 |
fix(cli): app push crash, lint path, push --message, run validation, history timestamps (#8585)
* fix(cli): app push crash, lint entry point, push --message, run arg validation, history timestamps Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): update sqlx cache and fix second history query missing created_at Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore(cli): regenerate system prompts after new CLI options Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
501a4ff2a9 |
fix: Improve CLI developer experience: error handling, sync workflow, JSON output, workspace forks (#8578)
* fix(cli): address 28 DX friction points across CLI commands Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(cli): regenerate system prompts after help text updates Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): address PR review feedback Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): update removeType tests to match lenient behavior Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): address CE/EE sync friction and improve JSON output Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): revert instance config masking to avoid breaking push flow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): mask instance secrets by default with interactive prompt Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(cli): regenerate system prompts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): use stderr for errors, optimize skipped-files scan, rename --auto to --auto-metadata Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(cli): improve workspace fork lifecycle — delete-fork fallback, list-forks, --workspace override Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): update fork merge instructions to reference all merge methods Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): clarify skipped-files warning comment re DynFSElement traversal Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
9643006f1e |
feat(cli): better stale scripts detection #3 (#8480)
* fix Signed-off-by: pyranota <pyra@duck.com> * reduce tests Signed-off-by: pyranota <pyra@duck.com> * update Signed-off-by: pyranota <pyra@duck.com> * fix Signed-off-by: pyranota <pyra@duck.com> * update Signed-off-by: pyranota <pyra@duck.com> * WIP: stash changes after merge with origin/main * Delete backend/parsers/windmill-parser-wasm/Cargo.lock * reset cargo.toml * feat(cli): integrate dependency tree into generate-metadata command - Add isDirectlyStale field to DependencyNode for staleness tracking - Update addScript to accept itemType, folder, isRawApp, isDirectlyStale - Update propagateStaleness to use isDirectlyStale field instead of parameter - Handlers now determine staleness and pass it to tree.addScript - generate-metadata calls propagateStaleness() and populates staleItems from tree - Pass legacyBehaviour=false and tree to handlers during generation phase 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(cli): store originalPath in tree for correct handler invocation Scripts need the path with extension to be passed to the handler. Added originalPath field to DependencyNode to track this. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix parsers Signed-off-by: pyranota <pyra@duck.com> * rever sqlx removal * update sqlx * feat: make py-imports parser WASM-compatible and add as separate WASM package Gate heavy deps (sqlx, windmill-common, async-recursion, toml, pep440_rs, tracing) behind cfg(not(wasm32)). Make parse_code_for_imports, parse_relative_imports, NImport, and ImportPin public. Remove duplicate import_parser from parser-py (reset to origin/main). Add py-imports-parser feature to windmill-parser-wasm and py-imports target to build.nu. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * safer return * update * fix: CLI metadata fixes - folder filter, staleness detection, WASM py-imports setup - Fix lazy_static cfg gating for WASM compatibility (split into separate blocks) - Fix folder argument filter to match specific file paths (not just directories) - Fix staleness detection to use checkHash with conf (includes module hashes) - Convert relative_imports_skip tests from Deno to bun APIs - Add windmill-parser-wasm-py-imports to CLI and build-npm dependencies - Relax module stale test to not require per-module change detail in output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: restore temp_script_refs parameter in parse_python_imports Re-adds the temp_script_refs parameter that was lost when resetting py-imports crate to origin/main. This enables resolving relative imports from not-yet-deployed scripts during CLI lock generation. * fixes * extend testsuit * update ee repo ref * fix: diff endpoint bytea cast, upload only mismatched scripts - Add POST /scripts/raw_temp/diff endpoint to batch-compare local content hashes against deployed versions using Postgres sha256() - Use convert_to(content, 'UTF8') instead of content::bytea to avoid failure on scripts containing backslash sequences (e.g. \n) - CLI now diffs all scripts against deployed, uploads only mismatched ones - propagateStaleness no longer deletes non-stale nodes (needed for diff) - Suppress verbose log.info messages during metadata generation - Add E2E tests for locally modified and unpushed helper scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * rework * sqlx * fixes * add index * expand tests * fix flows * archive script before executing * disable tests for ci * skip Python-dependent E2E tests on CI Tests requiring the python backend feature are skipped when CI_MINIMAL_FEATURES=true since CI builds with zip-only features. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: make flow fixture lock optional and reset nonDottedPaths after tests Flow fixtures no longer emit an empty lock file by default. The lockContent parameter controls whether a lock: "!inline ..." line appears in flow.yaml. This prevents flows from appearing "up-to-date" when they should be processed by generate-metadata. Also adds afterAll to reset setNonDottedPaths(false) so global state doesn't leak between test files when run together. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * debug: add error logging in withTestBackend to diagnose CI failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * debug: add --bail 1 to CI test runner to show full error on first failure Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * debug: include CLI stdout/stderr in assertion message for workspace deps test Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: set WMDEBUG_FORCE_V0_WORKSPACE_DEPENDENCIES in test backend The workspace deps feature requires workers to report their version, but in test/CI there are no separate workers (standalone mode). The version check fails because workers haven't had time to ping yet. Setting this env var bypasses the version check. Also reverts --bail 1 from CI workflow now that the root cause is fixed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * debug: add --bail 1 to Windows CI and assertion messages for Windows failure diagnosis Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: replace TEMP_SCRIPT_REFS_PLACEHOLDER in bun builder tests The loader.bun.js now includes a TEMP_SCRIPT_REFS_PLACEHOLDER that must be replaced before execution. The builder tests were missing this replacement, causing all 6 bun_builder_tests to fail. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use cdirFwd in Windows loader filterLoad regex Raw cdir (with backslashes) interpolated into RegExp causes \r to become carriage return and \w to become word-char, so filterLoad never matches main.ts. This prevents replaceRelativeImports from running, leaving bare relative imports like "./script_b" in the bundled output, which scanImports then misparses as package ".". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Windows filterLoad regex + graceful fallback for old backends - Fix filterLoad in loader.bun.windows.js to match both native backslash and forward-slash paths from Bun's resolver by escaping cdir for regex - Wrap uploadScripts in try/catch so generate-metadata degrades gracefully when the backend lacks /raw_temp endpoints (locks use deployed versions) - Add TODO for missing TEMP_SCRIPT_REFS support in Windows loader Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * debug: add loader/builder debug logging for Windows CI diagnosis Temporary console.log statements to understand: - What path Bun passes to onLoad for main.ts - Whether filterLoad regex matches - Whether replaceRelativeImports fires - What the bundled output contains - What imports scanImports extracts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: trigger CI for cli path Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: trigger CI via workflow file change Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add TEMP_SCRIPT_REFS to Windows loader, use .ts extensions in test imports - Add TEMP_SCRIPT_REFS_PLACEHOLDER support to loader.bun.windows.js (mirrors loader.bun.js) so CLI lock generation can resolve imports from locally-modified scripts on Windows - Use .ts extensions in all test relative imports to work around the Windows filterLoad regex bug (replaceRelativeImports doesn't fire on Windows, so extensionless imports fail) - Remove unused uploadSucceeded variable Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Remove debug logging from loader_builder.bun.js Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Remove windmill-parser-wasm-py-imports from frontend package.json This dependency is only needed by the CLI, not the frontend. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * debug: add temp_script_refs logging for Windows CI investigation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: remove --bail 1 from Windows CLI tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: normalize backslashes in folder filter treePath lookup (Windows) On Windows, item.path (originalPath) uses backslashes but tree keys use forward slashes. The isRelevant filter's touchesFolder call passed the unnormalized path to traverseTransitive, which couldn't find the node. This caused cross-folder importers to be excluded from generate-metadata when a folder argument was specified. Also removes debug logging from previous commit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Update cli-tests.yml * fix: normalize backslashes in strict-folder-boundaries warning message (Windows) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: update ee-repo-ref to fe8f0d1d7448464c98474d994e6492c0a45e8e38 This commit updates the EE repository reference after PR #467 was merged in windmill-ee-private. Previous ee-repo-ref: 03e6eaf950776c96b9581848a583af9ad735be60 New ee-repo-ref: fe8f0d1d7448464c98474d994e6492c0a45e8e38 Automated by sync-ee-ref workflow. * revert cli-tests.yml --------- Signed-off-by: pyranota <pyra@duck.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |