Commit Graph
14725 Commits
Author SHA1 Message Date
Diego ImbertandClaude Opus 5 94c68736f6 fix(datatables): serialize roles going on with a stream starting
Turning roles on looked for enabled triggers and live captures once,
without a lock anything starting a stream also took. A trigger enabled in
that window could have its listener connect before roles committed, and a
healthy listener never checks again. Both transitions now serialize on one
advisory lock: roles going on hold it exclusive while they look, and
trigger create, edit and enable, and capture setup and ping hold it shared
while they commit. Either the look sees the stream, or the listener
connects after roles are committed and refuses.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 11:59:27 +02:00
Diego ImbertandClaude Opus 5 b3942017f9 fix(datatables): disable a data table role before deleting it
Deleting a role reassigns and drops what it owns in each registered
database on its own connection, and each of those passes commits as it
goes. A database failing part-way left the role enabled in the catalog and
able to log in, but already stripped in the databases reached before it.
The role is now disabled in its own commit first, so a failed delete
leaves a disabled role to retry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 11:34:51 +02:00
Diego ImbertandClaude Opus 5 8407166307 Merge branch 'main' into datatable-roles-redesign
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 11:04:56 +02:00
AlexRV12andClaude Opus 5 172d6c275b feat: run a flow test through the chat's argument form (#11069)
* feat: run a flow test through the chat's argument form

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MxWRaAbciaeRxam5gPzaaV

* fix: resolve the flow editor to run when the form is submitted

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MxWRaAbciaeRxam5gPzaaV

* refactor: trim the flow run form's duplication and narration

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MxWRaAbciaeRxam5gPzaaV

* fix: label test_run_flow in the bypassed-tools tooltip

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MxWRaAbciaeRxam5gPzaaV

* fix: show the flow icon on a flow's run form in the preview panel

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MxWRaAbciaeRxam5gPzaaV

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 08:53:39 +00:00
hugocasaandClaude Opus 5 57f8b0826a fix: keep pinned import versions of imported scripts in bun lockfiles (#11082)
* fix: keep pinned import versions of imported scripts in bun lockfiles

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

* test: guard pinned imports through an unlocked multi-file bun run

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 08:48:02 +00:00
Diego ImbertandClaude Opus 5 24129c6649 fix(datatables): refuse a Postgres trigger on a data table under roles when it is saved
Creating or editing a trigger that points at a data table under roles was
accepted, and its listener then retried the refused connection every 30
seconds forever. The save is now refused, and a trigger that reaches such a
data table anyway (re-enabled, or cloned into a fork) is disabled by its
listener with the reason, as a missing replication slot is.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 10:45:55 +02:00
Ruben FiszelandClaude Opus 5 f8f7c0009f fix: serve instance env settings at the documented /settings/local path (#11075)
Claude-Session: https://claude.ai/code/session_01RbLzVfFDZ9pjBGHSzCSrNZ

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 08:42:29 +00:00
Diego ImbertandClaude Opus 5 2365e18caf refactor(datatables): keep Postgres triggers and data table roles apart
A replication stream reads every row of every table whatever the data table's
roles grant, and its listener checks access only when it connects. Rather than
chase every way access can change and bounce the streams each one affects, a
data table now carries one or the other:

- a Postgres trigger or capture cannot be created on, or connect to, a data
  table under roles;
- roles cannot be turned on while an enabled trigger or a live capture reads
  the data table, its own or a fork's through its pointer. The refusal names
  each one to disable.

This removes the stream bounces on roles edits and on data table and workspace
deletion, and the trigger gate that admitted admins. The fork schema baseline
fix from the same review round is kept.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 10:35:36 +02:00
fa53099e2b fix: let admins and background sync reach private git hosts (#11084)
* fix: let admins and background sync reach private git hosts

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Hb4vHnVrCMqe8ZtNtzFSs

* chore: point ee-repo-ref at the private git host change

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Hb4vHnVrCMqe8ZtNtzFSs

* fix: treat any admin token as admin and pin git probe transports

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Hb4vHnVrCMqe8ZtNtzFSs

* fix: pin git probe transports with a test and say what the caller check skips

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Hb4vHnVrCMqe8ZtNtzFSs

* chore: update ee-repo-ref to eccad9f68bd7246cc81acb82bdb6c08fc6013f45

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

Previous ee-repo-ref: 45ed1331a82dc15e6bdf15fd63517227f9160e21

New ee-repo-ref: eccad9f68bd7246cc81acb82bdb6c08fc6013f45

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>
2026-09-11 08:30:38 +00:00
Ruben FiszelandClaude Opus 5 e6d4f44a61 fix: show symlinked files in the git repo viewer (#11081)
* docs: describe symlink handling in the repo viewer's hub script

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPgYLu8Eiq58Bv2ev2YRYN

* docs: describe the symlink budget in the repo viewer's hub script

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPgYLu8Eiq58Bv2ev2YRYN

* docs: link the repo viewer script's hub page and soften the skip-log claim

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPgYLu8Eiq58Bv2ev2YRYN

* docs: charge the symlink budget before a link is resolved

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPgYLu8Eiq58Bv2ev2YRYN

* fix: point the git repo viewer at the symlink-following clone script

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPgYLu8Eiq58Bv2ev2YRYN

* docs: note that a new pin doesn't refresh commits already uploaded

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPgYLu8Eiq58Bv2ev2YRYN

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 09:25:24 +02:00
Ruben FiszelandClaude Opus 5 b156778da2 fix: support gzip and zstd compression for OTLP export over gRPC (#11077)
Claude-Session: https://claude.ai/code/session_01RbLzVfFDZ9pjBGHSzCSrNZ

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 08:01:54 +02:00
f915ed6a46 fix: attach TLS to gRPC OTLP exporters for https endpoints (#11078)
* fix: attach TLS to gRPC OTLP exporters for https endpoints

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbLzVfFDZ9pjBGHSzCSrNZ

* chore: bump ee-repo-ref for the gRPC TLS resolution test

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbLzVfFDZ9pjBGHSzCSrNZ

* chore: update ee-repo-ref to afd59490e2ca3c375d64cf4a91041763c7de4766

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

Previous ee-repo-ref: b6dd68beb144ecf1b978172396ff8c8bb27ae0c2

New ee-repo-ref: afd59490e2ca3c375d64cf4a91041763c7de4766

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>
2026-09-11 08:01:26 +02:00
Ruben Fiszelandrubenfiszel 7915540f66 chore(main): release 1.809.0 (#11045)
* chore(main): release 1.809.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
v1.809.0
2026-09-10 22:57:04 +02:00
Ruben FiszelandClaude Opus 5 a9b0d871a4 surface OTEL env vars in the settings page and startup log (#11074)
* feat: surface OTEL env vars in the settings page and startup log

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbLzVfFDZ9pjBGHSzCSrNZ

* chore: log OTEL compression and per-signal timeouts in the startup config

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbLzVfFDZ9pjBGHSzCSrNZ

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 22:54:54 +02:00
Ruben FiszelandClaude Opus 5 8ecbd339ee fix: skip the deploy PR when the git sync push committed nothing (#11076)
Claude-Session: https://claude.ai/code/session_01WVDyzszjbvSssMN6HpnZZw

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 22:45:34 +02:00
Ruben FiszelandClaude Opus 5 d87f089288 feat: tuck other users' spaces into a collapsible home tree row (#11073)
* feat: group other users' spaces under a collapsible row in the home tree

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013eAE5cpKPdtH9DNJm5TjcH

* fix: page the other users group on its own and use a design-system toggle

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013eAE5cpKPdtH9DNJm5TjcH

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:57:50 +00:00
63cb46d7bb feat: add a minimal skin for the approval page and slack/teams (#11061)
* feat: add an approval skin to the approval page and slack/teams messages

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* chore: point ee-repo-ref at the teams approval skin commit

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* fix: resolve the approval skin from the step awaiting approval

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* fix: shorten the slack approval message to fit the button value limit

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* fix: rename skins to detailed/minimal and keep long slack messages

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* feat: title the minimal approval page from the step and flow summaries

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* feat: let wait_for_approval set the description approvers see

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* fix: keep a finished workflow's approval description, still gated

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* fix: keep a login-required approval locked after the run moves on

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* feat: hide the windmill version on the approval page

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KK2Ye4PizykReZVuMEm3m9

* chore: update ee-repo-ref to e92abc9d1fba3ba898640df0cfeb0af8a50849b4

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

Previous ee-repo-ref: bf1766ff49458f62d3f11746f1a06893ae3c2325

New ee-repo-ref: e92abc9d1fba3ba898640df0cfeb0af8a50849b4

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>
2026-09-10 18:50:09 +00:00
Ruben FiszelandClaude Opus 5 e62bfdcd8c fix: give every table a primary key so the db can be logically replicated (#11036)
* fix: give every table a primary key so the db can be logically replicated

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017WS9iNfYQiLJNuBnxysBzi

* fix: tighten replicability guard and trim migration comments

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017WS9iNfYQiLJNuBnxysBzi

* fix: split deployment_metadata into its own primary-key migration

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017WS9iNfYQiLJNuBnxysBzi

* docs: correct the partial-index predicate note after the deployment_metadata split

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017WS9iNfYQiLJNuBnxysBzi

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:42:24 +00:00
Tristan TRandClaude Opus 5 8bd144ccb1 keep crawlers off the login page (#11057)
* fix(frontend): keep crawlers off the login page

Every page on the hub links to /user/login with itself in `rd`, so a crawler
sees one login URL per hub page — 4,311 of them in Search Console, all
rendering this same form and flagged as duplicates without a canonical. Nothing
about a login page belongs in an index, on any instance.

Mark the page noindex, as public_run already is, and ship a robots.txt that
keeps crawlers out of /user/ and /api/. The frontend is embedded as static
assets with an index.html fallback, which is why /robots.txt answered with the
app shell until now; a real file in static/ is served as itself.

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

* fix(frontend): let crawlers fetch the login page so the noindex is seen

robots.txt disallowed /user/, which stopped a crawler fetching /user/login at
all — and a page that is never fetched never shows its noindex. The two halves
cancelled: the URLs would have moved from "duplicate" to "blocked" rather than
out of the index.

Drop the disallow, keeping /api/. And since the app is client-rendered, the
meta tag only exists after a render pass; send X-Robots-Tag on /user/* from
serve_path as well, which a crawler sees on the first fetch.

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 18:42:01 +00:00
AlexRV12andClaude Opus 5 fa73539839 fix(ai-chat): test_run_flow could test a different flow than the one asked (#11066)
* fix(ai-chat): test_run_flow could test a different flow than the one asked

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmQDoFXVPwYyEN8PfV2oL7

* fix(ai-chat): prefer the flow editor stored at the path over one renamed to it

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmQDoFXVPwYyEN8PfV2oL7

* test(ai-chat): default the flow helpers factory and trim duplicated setup

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmQDoFXVPwYyEN8PfV2oL7

* refactor(ai-chat): resolve the flow editor to run by its storage path

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmQDoFXVPwYyEN8PfV2oL7

* refactor(ai-chat): move the editor storage path context out of sessions

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmQDoFXVPwYyEN8PfV2oL7

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:41:21 +00:00
Ruben FiszelandClaude Opus 5 569adb85c1 feat: live queue status per tag and bounded queue metric charts (#11067)
* feat: live per-tag queue status and bounded charts in the queues drawer

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fYMqh7R8FnePmbYzirJXZ

* fix: drop stale chart failures and test the queue metrics series query

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fYMqh7R8FnePmbYzirJXZ

* fix: name the queue status refresh, skip overlapping polls, soften the no-worker warning

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fYMqh7R8FnePmbYzirJXZ

* feat: draw a stuck tag's queue delay exactly as it climbs (#11071)

* feat: store a stuck tag's queue delay as its head's wait start

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fYMqh7R8FnePmbYzirJXZ

* fix: keep a climb's top inside a slot and stamp held delays exactly

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fYMqh7R8FnePmbYzirJXZ

* fix: redraw a climb as soon as its head leaves, and document the lookup slack

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011fYMqh7R8FnePmbYzirJXZ

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:40:54 +00:00
Diego ImbertandClaude Opus 5 08d876aebf fix(frontend): recompute dataflow edges when selecting a step (#11070)
Claude-Session: https://claude.ai/code/session_01Vk3d9DpuPuV8C8nKSeGCqC

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:40:40 +00:00
Ruben FiszelandClaude Opus 5 f517402538 fix: bound list_jobs runtime and paginate runs on the sorted column (#11072)
* fix: bound list_jobs runtime and paginate runs on the sorted column

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRqFF6xk1A41AcF6NsTDNS

* fix: keep queue-only refresh unbounded and page runs by exact inclusive cursor

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRqFF6xk1A41AcF6NsTDNS

* fix: cap tie-widened pages at the server limit and make the list timeout configurable

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRqFF6xk1A41AcF6NsTDNS

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:39:20 +00:00
c57b18e46f fix: surface why a private or untrusted git host is unreachable (#11068)
* fix: surface why a private or untrusted git host is unreachable

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YBriXeDGzjBWjSUTgpkCxW

* test: assert the private git host refusal names ALLOW_LOCAL_GIT_REMOTES

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YBriXeDGzjBWjSUTgpkCxW

* test: pin that the url credential stays out of the refused-host error

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YBriXeDGzjBWjSUTgpkCxW

* chore: update ee-repo-ref to fe2418ff4e5630d6ad3fd85cd2c865bf51c87a2a

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

Previous ee-repo-ref: af0f3ca96f2fbcfa4bf4f8498824c52001d72c55

New ee-repo-ref: fe2418ff4e5630d6ad3fd85cd2c865bf51c87a2a

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>
2026-09-10 18:33:01 +00:00
2f88769087 feat(otel): read the OTLP metrics temporality preference (#11064)
* feat(otel): honor OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013iN8SNZQva5MfMnSM43fHq

* fix(otel): print exporter build failures that tracing would drop

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013iN8SNZQva5MfMnSM43fHq

* chore: update ee-repo-ref to a8ce9bed4b16a01a964d4c35bdc3092b89d10495

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

Previous ee-repo-ref: 7445aa186ca599c3353e041986fe46a277ba9e9f

New ee-repo-ref: a8ce9bed4b16a01a964d4c35bdc3092b89d10495

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>
2026-09-10 18:28:41 +00:00
Diego ImbertandClaude Opus 5 e295e5390f fix(datatables): keep the fork schema baseline, and bounce streams on every removal
Three fixes from review.

`edit_datatable_config` took `forked_from` wholesale from the stored entry, so
the fork schema diff's save of an advanced baseline was silently discarded and
an applied change was offered again. Whether an entry carries a clone stamp is
still carried from the store, since that is what marks its database droppable,
but the baseline inside it is now taken from the request.

The stranded-pointer warning and the stream bounce ran over the optional
`deleted_datatables` hint, which the settings-sync CLI never sends, so removing
a governing data table through `wmill` bounced nothing. Removals are now derived
from the stored configuration against the saved one.

`delete_workspace` read the pointers to bounce before its transaction, so a fork
committing a pointer during the deletion was missed. The read now happens inside
the transaction, after the workspace row is deleted: a fork's insert key-share
locks that row through its parent foreign key, so it is either seen or fails on
the missing parent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 19:15:33 +02:00
Diego ImbertandClaude Opus 5 c27ae4e0af fix(datatables): bounce the streams reading a data table when it is deleted
Deleting a governing data table, or the workspace that holds it, only collected
the fork pointers it stranded, for the warning. A Postgres trigger or capture
already streaming through one of those pointers kept the replication connection
it opened while the pointer still resolved, so it went on dispatching the
governing database's rows after the fork lost access — until its connection
happened to restart. The governing workspace's own streams on a deleted entry
did the same.

Both deletion paths now bounce the affected listeners inside their own
transaction, through the helper a permission change already uses, so a
listener that reconnects re-resolves the entry and finds it gone. The helper is
split so a caller can pass the (workspace, local name) pairs it already holds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:49:05 +02:00
Diego ImbertandClaude Opus 5 7bc4fda471 docs(datatables): record the stale clone database as a known limitation
A clone is three requests and `CREATE DATABASE` is not transactional, so a
failure after the first leaves a registered `wm_fork_*` behind, as it did
before data table roles. Accepted for this PR: it is harmless to data and goes
away once the clone is a single server-side operation.

The comment also records why the obvious fix is wrong: reclaiming the leftover
on retry, without durable clone ownership, can drop another workspace's fully
copied database between its import and its final fork request.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:28:14 +02:00
Diego ImbertandClaude Opus 5 445f18f896 Revert "fix(datatables): let a retried clone reclaim its own leftover database"
This reverts commit 7dd3275a10.

The reclaim tied the caller to the source they administer, but not to the
database it dropped. Between another workspace's import and its final fork
request, that workspace's target is full, registered, unnamed and has no open
connection, so an admin of any instance data table could name it and have it
dropped and recreated empty. The victim's fork would then commit pointing at
the empty copy. Safe reclaim needs durable clone ownership and serialization
with the request that names the database; until then the leftover stays, as it
did before this PR.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:28:13 +02:00
Diego ImbertandClaude Opus 5 7dd3275a10 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>
2026-09-10 18:06:28 +02:00
Ruben FiszelandClaude Opus 5 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>
2026-09-10 17:19:02 +02:00
GuilhemandClaude Opus 5 385086ffc2 feat: show the workspace an operator is in, and let them switch (#11059)
* feat: show the workspace an operator is in, and let them switch

Operators get a single burger button instead of the developer sidebar, so
nothing on screen named the workspace they were working in.

The button now carries the workspace colour as a disc behind the hamburger,
with the workspace name beside it — permanently on home, and on hover
elsewhere. Workspaces without a colour fall back to a neutral disc so the
button always reads as a control against the page behind it.

A "Switch workspace" submenu lists the operator's workspaces, reusing the
developer sidebar's picker: that list moved out of WorkspaceMenu into
WorkspacePickerBody so both render the same rows. "All workspaces" moved from
the operator menu into the bottom of that picker, outside its scroll area so it
stays reachable.

An operator switching workspaces lands on home, since their page access is
granted per workspace and the page they are on may not be theirs to open in the
one they switch into. Developers keep the existing stay-on-the-page behaviour,
as do pickers embedded in a page that drives its own navigation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmXFP3eaPPdZuVwVpLuYRX

* fix: decide the operator landing from positive role signals only

`operator_settings` is NULL both for a non-operator and for an operator whose
workspace never had settings written, so a `false` from `isOperatorInWorkspace`
could not stand as proof of a developer. Lead with `userStore.operator`, an
explicit flag for the workspace being left, and keep the target check only as a
confirmation. Also states the picker's expansion-seeding invariant as what the
host menu actually guarantees: a close and re-open inside its 100ms outro
resumes the same instance rather than a fresh one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmXFP3eaPPdZuVwVpLuYRX

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 16:37:28 +02:00
GuilhemandClaude Opus 5 b4be8bc535 fix(frontend): clear the flow graph selection through xyflow's store (#11056)
Selecting a step in the flow editor sometimes opened the Settings panel
instead of the step that was clicked.

SelectionManager.selectId() clears xyflow's own selection before setting
ours, and that clear was wired to clearFlowSelection(), which resets
offsetNodeCache and reassigns nodes. That hands xyflow node objects it
does not recognise, which is what makes it drop the flag — but it also
makes it re-create every node's DOM: 126 elements on a 25-node flow, on
every selection.

Graph nodes select on pointerdown. A click is dispatched on the closest
common ancestor of its pointerdown and pointerup targets, so when the
release lands in that teardown gap the browser hit-tests to the pane, the
click addresses the pane, and onpaneclick clears the selection back to the
settings sentinel.

Clear through store.unselectNodesAndEdges() instead, so no node object
changes identity and there is no gap to fall into. clearFlowSelection
keeps its two group-creation callers, which rebuild the graph anyway.


Claude-Session: https://claude.ai/code/session_01R7caEKonPr2DmvsWRR6bCK

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 16:37:10 +02:00
Ruben FiszelandClaude Opus 5 9d75929247 perf: only write queue metrics when a tag's backlog changes (#11055)
* perf: only write queue metrics when a tag's backlog changes

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vz5TLoq492nruNSCr6LARA

* fix: hold queue metric steps until the next sample and skip failed reads

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vz5TLoq492nruNSCr6LARA

* fix: keep running-count gauges on a failed backlog read and widen stale margins

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vz5TLoq492nruNSCr6LARA

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 16:09:19 +02:00
Ruben FiszelandClaude Opus 5 ab9efc897c fix: refuse cross-site GET requests that run Hub scripts (#11054)
* fix: reject cross-site GET requests on job-run endpoints

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015V51NZ7yeRzbJCsq5n4tzd

* fix: log the Referer leg of the cross-site guard and unit-test host parsing

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015V51NZ7yeRzbJCsq5n4tzd

* fix: scope the cross-site GET guard to Hub scripts

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015V51NZ7yeRzbJCsq5n4tzd

* refactor: resolve script runnables through the cross-site guard

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015V51NZ7yeRzbJCsq5n4tzd

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 13:14:37 +00:00
Ruben FiszelandClaude Opus 5 8820b9fc64 feat: report script metadata with no content file in wmill lint (#11053)
Claude-Session: https://claude.ai/code/session_01PENfHNJceAbrcUsgfFCjXN

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 09:15:44 +02:00
Diego Imbert 4600942286 Merge branch 'main' into datatable-roles-redesign 2026-09-10 08:38:22 +02:00
Diego ImbertandClaude Opus 5 2eef801dee 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
2026-09-10 08:27:29 +02:00
Diego ImbertandClaude Opus 5 f53652d46f 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
2026-09-10 08:16:58 +02:00
Diego ImbertandClaude Opus 5 4f4ecba9cc 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
2026-09-10 08:01:25 +02:00
Ruben FiszelandClaude Opus 5 9a563f6d72 perf: index the FK columns that cascade on workspace delete (#11052)
Claude-Session: https://claude.ai/code/session_01UtSL61CGQqtLc28AT2h75d

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 23:44:33 +02:00
GuilhemandClaude Opus 5 5d7eed1c02 fix: space the trailing AI settings cards (#11044)
Claude-Session: https://claude.ai/code/session_014GHiwAKGrsaPVAXDJVxhDq

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 17:37:29 +00:00
GuilhemandClaude Opus 5 e63072c216 fix(frontend): restore heading sizes in note markdown and keep group notes on id change (#11047)
* fix(frontend): restore heading sizes in note markdown and keep group notes on id change

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182GroR5mvi9ksRTMmBT7nE

* fix(frontend): scope the note cleanup deferral per note

Address local review nits: the header comment overstated the heading ramp (h3
sits at body size in the xs and sm scales), and the mid-update deferral bailed
out of cleanup for every group note rather than the one holding the unrendered
module.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182GroR5mvi9ksRTMmBT7nE

* perf(frontend): traverse modules without collecting a discarded array

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182GroR5mvi9ksRTMmBT7nE

* test(frontend): show the three markdown prose presets in the kitchen sink

The Markdown tab rendered only the default preset, so a change to the shared
heading scale could not be compared across the surfaces that use it. The chat
sample gains headings for the same reason: it is the only place the assistant
bubble renders at panel width without an AI provider.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182GroR5mvi9ksRTMmBT7nE

* refactor(frontend): validate group notes against the flow, not the render

A group note's members are module ids, so the flow's own module list decides
whether one still exists. Validating against the rendered nodes instead needed
a special case for collapsed groups, and still dropped a live module in the
pass after its id changed. Both cases are the same mistake, and checking the
source of truth removes them together with the collapsedModuleIds parameter.

Path completion keeps working off the rendered graph, since it needs the edges,
and now skips a note whose members it cannot all see rather than dropping them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182GroR5mvi9ksRTMmBT7nE

* fix(frontend): name a new note "Note", not after its internal type

The prefill lands inside the user's own note, and "Free note" / "Group note"
are the serialized type, not words anyone says about a note they just drew.
The menus that create them already say "Add note".

The heading goes to h2 as well: h3 computes to the body size in the note scale,
so the prefill's own title did not read as one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182GroR5mvi9ksRTMmBT7nE

* docs(frontend): describe what collapsedModuleIds is still for

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182GroR5mvi9ksRTMmBT7nE

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 16:51:55 +00:00
Diego ImbertandClaude Opus 5 c645537ee6 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
2026-09-09 18:41:35 +02:00
Diego Imbert c84a6fc28e Merge remote-tracking branch 'origin/main' into datatable-roles-redesign
# Conflicts:
#	backend/ee-repo-ref.txt
#	frontend/src/lib/components/InstanceSettings.svelte
2026-09-09 18:25:48 +02:00
0a40eea37a feat(otel): support standard OTEL resource attribute env vars (#10974)
* fix(otel): pick up standard OTEL_RESOURCE_ATTRIBUTES on the exported resource

The OTEL resource was built with `Resource::builder_empty()`, which runs no
resource detectors, so attributes injected through the standard
`OTEL_RESOURCE_ATTRIBUTES` env var were silently dropped. Deployments that
inject `k8s.pod.uid`, `k8s.container.name` or `service.namespace` saw none of
them reach their backend.

Use `Resource::builder()`, which seeds from the SDK's env detector. Windmill's
own attributes keep being applied on top, so per the OTel resource spec the env
var is the secondary resource and `service.name`, `service.version`,
`host.name` and `deployment.environment*` stay authoritative.

The EE change lives in windmill-ee-private; this carries the ee-repo-ref bump
and a regression test pinning both halves of the contract.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yUJaBDHPgjZPodP2u4aqR

* test(otel): clear OTEL_HOST_NAME so the resource test is hermetic

OTEL_HOST_NAME takes precedence over the hostname argument, so an ambient one
failed the host.name assertion with a message pointing at the merge logic.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yUJaBDHPgjZPodP2u4aqR

* feat(otel): honor OTEL_SERVICE_NAME and OTEL_SERVICE_VERSION

Deployments identify each pod from its own labels, e.g. through the Kubernetes
downward API, so `service.name` and `service.version` must be settable per pod.
Both were ignored: OTEL_SERVICE_NAME was read by the SDK and then overwritten,
and because the two attributes are set in code they also outrank
OTEL_RESOURCE_ATTRIBUTES, leaving no route to set them at all.

The EE change lives in windmill-ee-private; this carries the ee-repo-ref bump
and tests for the dedicated overrides.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yUJaBDHPgjZPodP2u4aqR

* fix(otel): keep service.version pinned to the build version

OTEL_SERVICE_VERSION is not an OTel env var, and service.version identifies the
build that produced the telemetry, which a deployment cannot state more
precisely than GIT_VERSION already does. A deployment that wants its own release
version in telemetry can carry it under its own key.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yUJaBDHPgjZPodP2u4aqR

* test(otel): pin OTEL_SERVICE_NAME above service.name in OTEL_RESOURCE_ATTRIBUTES

The spec ranks OTEL_SERVICE_NAME above a service.name carried in
OTEL_RESOURCE_ATTRIBUTES; that ordering was only checked by hand. The three
candidate values are distinct, so the assertions fail if either ranking breaks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yUJaBDHPgjZPodP2u4aqR

* feat(otel): honor OTEL_SERVICE_VERSION

The spec defines no OTEL_SERVICE_VERSION, but deployments set it expecting it to
work because it sits next to OTEL_SERVICE_NAME, and setting service.version in
code blocks the OTEL_RESOURCE_ATTRIBUTES route, so there is otherwise no way to
set it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yUJaBDHPgjZPodP2u4aqR

* test(otel): guard against unknown_service on a default deployment

Resource::builder seeds SdkProvidedResourceDetector, which sets service.name to
"unknown_service" when neither OTEL_SERVICE_NAME nor a service.name in
OTEL_RESOURCE_ATTRIBUTES is present. Only our own attribute keeps that out of
the exported resource, and no assertion covered the case where nothing is set
at all — which is the default deployment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yUJaBDHPgjZPodP2u4aqR

* test(otel): pin the empty-means-unset fallback for OTEL_SERVICE_VERSION

The empty case asserted the fallback for service.name and host.name but not
service.version, leaving one branch of the three-variable contract uncovered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yUJaBDHPgjZPodP2u4aqR

* chore: update ee-repo-ref to b964f0caaae57dc526c7ac9dc54d753372989f63

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

Previous ee-repo-ref: 62efa909aabdba4cb31ffabe9aae0e4909ca1e07

New ee-repo-ref: b964f0caaae57dc526c7ac9dc54d753372989f63

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>
2026-09-09 17:41:41 +02:00
Diego ImbertandClaude Opus 5 1f661f5816 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
2026-09-09 17:19:30 +02:00
Diego ImbertandClaude Opus 5 397116926f 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
2026-09-09 16:56:35 +02:00
Diego ImbertandClaude Opus 5 7b01f35c3b 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
2026-09-09 16:00:19 +02:00
Diego ImbertandClaude Opus 5 41ea76f806 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
2026-09-09 15:22:39 +02:00