Commit Graph
2071 Commits
Author SHA1 Message Date
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>
2026-09-04 22:47:28 +02:00
Ruben Fiszelandrubenfiszel 38fc0d3a12 chore(main): release 1.803.0 (#10952)
* chore(main): release 1.803.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-09-03 13:08:33 +02:00
hugocasaandClaude Opus 5 17ba521c35 fix: record supplied script lock hashes so importers can skip relocking (#10915)
* fix: record supplied script lock hashes so importers can skip relocking

Creating a script with a caller-supplied lock — a CLI push, a git-sync deploy,
any create carrying a lockfile — stored the lock on `script` but never wrote the
matching `lock_hash(workspace_id, path, hash_script(lock))` row. Only
worker-generated locks did.

`try_skip_relock` treats a missing hash for an imported script as changed, so no
importer of such a script could ever satisfy the skip predicate: every deploy of
it relocked every importer, forever.

The create transaction now records the hash for any lock it accepts, including
the empty one a codebase or a language with no lock generation carries — the
worker writes `hash_script("")` there, and a path going from a real lock to an
empty one has to stop matching what its importers recorded. Only a lock left to
a dependency job is skipped, because that job writes it.

A workspace clone now carries `lock_hash` too, without which every
dependency-map snapshot the clone later recorded held NULL and nothing in it
could ever skip. `dependency_map.imported_lockfile_hash` is deliberately not
copied: it records what an importer resolved against when it was last locked,
the clone runs READ COMMITTED, and a relock landing in the source between the
scripts being cloned and that statement would attach a hash the cloned
importer's lock was never resolved against — a hash older than the cloned
scripts costs one relock, a newer one skips a relock that was needed.

Lock generation is untouched, as is everything a relock does once it runs. The
only behavior that moves is which relocks are skipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138oct9a6SLEZvFyCQgHRBx

* fix: narrow to the create-path lock hash

Drop the workspace-clone copy of lock_hash. It sits outside the reported
bug, and its double join over `script` can emit a path twice where two
versions are live, which the unique key on (workspace_id, path) then
rejects, failing the whole fork.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138oct9a6SLEZvFyCQgHRBx

* fix: restore the workspace-clone lock hash copy, guarded against fanout

A path can hold two live versions, and both joins match on path alone, so
the select can emit it four times against a primary key that admits one.
Every such row carries the single hash the path has, so ON CONFLICT DO
NOTHING settles it rather than aborting the fork.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138oct9a6SLEZvFyCQgHRBx

* fix: hash a clone's own locks rather than copying the source's rows

A source row is only as current as the last write to it, and a supplied
lock deployed before this was recorded leaves one naming a lock the path
no longer holds. Copying that into a fork hands an importer a hash it
never resolved against; hashing what the clone holds cannot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138oct9a6SLEZvFyCQgHRBx

* test: pin the lock hash written on a no-op push

Removing that write leaves the assertion with no row, which is the state
a script deployed before this shipped would stay in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138oct9a6SLEZvFyCQgHRBx

* refactor: share one lock hash writer between the create and clone paths

Both wrote the same upsert with different SQL. The existing writers fold
theirs into the statement that writes the lock itself, which is what keeps
the two consistent; these two have nothing to fold it into, so they take a
shared one instead. The clone walks its pages by path rather than listing
them first, dropping a query with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138oct9a6SLEZvFyCQgHRBx

* fix: stream a clone's locks rather than reading them in pages

script.lock is unbounded, so a page of them is bounded only by how many
it holds. Hashing each as it arrives keeps one in memory at a time and
lets the clone site collapse to a single call.

Also states on both writers that they check no access to the workspace
they write, which their callers are the ones to have established.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138oct9a6SLEZvFyCQgHRBx

* fix: make the lock hash writer safe to repeat and free when unchanged

A path given twice in one call would have Postgres reject the whole
statement, so the last hash for each wins. And recording a hash a path
already has cut a row version for nothing on every unchanged sync, which
is the mode the no-op push runs in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138oct9a6SLEZvFyCQgHRBx

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 19:20:49 +02:00
Ruben Fiszelandrubenfiszel 74c1813f98 chore(main): release 1.801.0 (#10921)
* chore(main): release 1.801.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-09-02 01:01:01 +02:00
Ruben Fiszelandrubenfiszel 870f67121d chore(main): release 1.800.1 (#10910)
* chore(main): release 1.800.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-09-01 11:34:32 +02:00
Ruben Fiszelandrubenfiszel 412eb90c0d chore(main): release 1.800.0 (#10888)
* chore(main): release 1.800.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-31 20:29:23 +02:00
Ruben Fiszelandwindmill-internal-app[bot] 2fb790338d upgrade argon2 to 0.6 and migrate the password hashing API (#10902)
* fix: upgrade argon2 to 0.6 and migrate the password hashing API

* test: pin that an unparseable stored hash reads as a failed login

* chore: update ee-repo-ref to 58738c39ac41d57917bbd9400318704763d997f7

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

Previous ee-repo-ref: 02a89fc4d27e49a494112fa91a8812e3ee4fb8a6

New ee-repo-ref: 58738c39ac41d57917bbd9400318704763d997f7

Automated by sync-ee-ref workflow.

---------

Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-08-31 08:48:27 +02:00
Ruben FiszelandClaude Opus 5 419d3adb6c chore: bump tantivy to 0.27 and pin argon2 to 0.5 (#10890)
* chore: bump tantivy to 0.27 and pin argon2 to 0.5

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

* chore: pin tantivy to the merged fork main head

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-29 11:16:48 +02:00
7c1a785f75 feat: serve service log retrieval from a columnar parquet store (#10886)
* feat: always write service log files as json so they index structured

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

* feat: serve service log retrieval from a columnar parquet store

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

* feat: shrink the service log index to the per-host count it still serves

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

* fix: reclaim the superseded service log index on upgrade

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

* fix: address review findings in the service log store

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

* chore: update ee-repo-ref to ad9e899dfd2ee4e3d18ecf06d016f821968c5a83

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

Previous ee-repo-ref: 6ad4064f9d58d83612b42b4ec870384994d64bcb

New ee-repo-ref: ad9e899dfd2ee4e3d18ecf06d016f821968c5a83

Automated by sync-ee-ref workflow.

* fix: address review nits on the service log store

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

---------

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-08-29 09:51:59 +02:00
Ruben Fiszelandrubenfiszel 7a0c81d722 chore(main): release 1.799.0 (#10874)
* chore(main): release 1.799.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-28 17:26:18 +02:00
Ruben Fiszelandrubenfiszel 90b40fffc3 chore(main): release 1.798.1 (#10870)
* chore(main): release 1.798.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-27 12:00:45 +02:00
Ruben Fiszelandrubenfiszel 2302e58c24 chore(main): release 1.798.0 (#10868)
* chore(main): release 1.798.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-27 11:07:15 +02:00
Ruben Fiszelandrubenfiszel 52ca19e9ae chore(main): release 1.797.0 (#10848)
* chore(main): release 1.797.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-27 10:15:23 +02:00
Ruben Fiszelandrubenfiszel 0f3d884c6f chore(main): release 1.796.0 (#10810)
* chore(main): release 1.796.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-24 22:42:33 +02:00
Ruben FiszelandClaude Opus 5 8dbd12ecc1 fix: patch sqlx so a cancelled BEGIN cannot poison a pooled connection (#10823)
* fix: patch sqlx so a cancelled BEGIN cannot poison a pooled connection

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

* test: drop the migration run and fixed sleep from the sqlx patch guard

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

* test: ignore the sqlx patch guard by default and point at it from where sqlx is changed

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 22:29:44 +02:00
Ruben Fiszelandrubenfiszel 74af4ed939 chore(main): release 1.795.0 (#10807)
* chore(main): release 1.795.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-22 12:11:36 +02:00
Ruben Fiszelandrubenfiszel 1a506b8f22 chore(main): release 1.794.1 (#10801)
* chore(main): release 1.794.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-21 13:45:56 +00:00
Ruben Fiszelandrubenfiszel 55b6279058 chore(main): release 1.794.0 (#10782)
* chore(main): release 1.794.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-21 12:27:44 +02:00
8e508ea01a feat: support application default credentials for gcp pub/sub triggers (#10778)
* feat: support application default credentials for gcp pub/sub triggers

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

* fix: address review findings on gcp application default credentials

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

* fix: address review nits on gcp application default credentials

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

* fix: key the gcp credential-mode permission off the loaded mode

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

* fix: gate enabling an ADC gcp trigger on workspace admin

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

* fix: lock the gcp trigger row while authorizing a mode change

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

* fix: skip admin-only gcp listing when the caller cannot use those credentials

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

* chore: update ee-repo-ref to 54bf630681000c8ed87a7067e357118e015123b1

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

Previous ee-repo-ref: 91d0e228a0ad226625278b400c64f96a61404a10

New ee-repo-ref: 54bf630681000c8ed87a7067e357118e015123b1

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-08-21 10:41:14 +02:00
Ruben Fiszelandrubenfiszel 2439a610be chore(main): release 1.793.0 (#10764)
* chore(main): release 1.793.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-20 22:18:01 +02:00
5099f405d4 feat: make the Git Repo Viewer work with GitHub App repositories (#10765)
* fix: resolve the head commit of GitHub App repos in the git repo viewer

`get_git_commit_hash` ran `git ls-remote` against the raw resource URL.
A GitHub-App-backed repository stores a tokenless URL, so the probe failed
with "could not read Username" and the viewer never got past its first
step. Resolve the head over the GitHub REST API with a server-side
installation token instead, reusing the lookup the auto-pull poller
already uses for app repos. Non-app repositories keep the ls-remote path.

Also picks up the EE-side allowlist fix that lets the clone hub script
request an installation token.

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

* chore: update ee-repo-ref to 63c67e2a2db198af26a0334f5be14af7d9987eb1

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

Previous ee-repo-ref: 2a260961fa0a9bb5631c17e2f718cb8efb4f9aa2

New ee-repo-ref: 63c67e2a2db198af26a0334f5be14af7d9987eb1

Automated by sync-ee-ref workflow.

* fix: honour the app-repo head lookup's not-app-backed result

`get_app_repo_head_for_autopull` documents `Ok(None)` as "this repo is not
app-backed, use the ls-remote path", which is what the other two callers do.
Fall through to `ls-remote` on `None` instead of turning it into a 500, and
drop the handler's own `is_github_app` read now that the callee's answer is
honoured.

Also bumps ee-repo-ref to pick up route-safe ref handling in that lookup.

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

* feat: serve GitHub App repositories as an archive instead of a token

The viewer's clone script asked the server for an installation token and put
it in the clone URL. That token is installation-wide and carries the App's
full permissions, so minting one requires a workspace admin, and the viewer
was therefore admin-only for app-backed repositories.

The server now streams a tarball of the commit instead, authorized by read
access to the git_repository resource, so no GitHub credential reaches the
job.

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

* feat: run delegate_to_git_repo playbooks from GitHub App repositories

An Ansible job's runnable_path is the user's own script, which no entry in
the git-sync script allowlist can match, so `delegate_to_git_repo` could
never obtain a token for an app-backed repo. It also gave up entirely on
agent workers, whose connection has no database to mint one from.

A playbook run only reads a working tree: the clone is followed by one
rev-parse for a log line, and nothing after that touches git. So take the
same archive route the viewer uses, extracting the commit's tarball into the
job's repository directory. No GitHub credential reaches the worker, and
agent workers work because the route is HTTP.

Archive entries are joined onto the target by hand so a crafted archive
cannot write outside the job directory.

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

* fix: drop the now-immutable secret_url binding

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

* feat: point the repo viewer at the archive-based clone script

hub/28905 reads app-backed repositories through the server's archive route
instead of minting an installation token, which the backend in this release
no longer grants it.

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

* fix: stream repository archives to disk rather than into memory

The archive download went through `AuthedClient::get`, whose client caps a
request at 20 seconds and whose response was then buffered whole. A
repository is arbitrarily large, so that cut off slow downloads and put every
job on the worker at risk of running the process out of memory.

Add `get_streaming`, the read counterpart to the streaming upload path, and
write the response out chunk by chunk.

Extraction now creates each entry's parent directory: a tar carries directory
entries only by convention, and the traversal guard now has tests, one of
which caught the missing parent.

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

* fix: require admin to read an app-backed repository

A `git_repository` resource names the repository rather than holding a
credential for it, so read access to one authorizes nothing: anyone who can
write a resource path can point one at any repository the GitHub App
installation reaches, then read their own resource. The head lookup now
requires admin for app-backed repos, matching the archive route and the
repository picker, which already limits itself to workspaces where the
caller is an admin.

Repos that aren't app-backed are untouched and stay open to any reader.

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

* docs: describe the repo viewer's hub script as it stands

The file read as a patch waiting to be applied, against a hub version two
releases stale. Describe what the published script does, including the
archive route app-backed repositories now take.

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

* fix: run the archive fetch under the job poller, off the job directory

Three defects in the delegate path's fetch:

The download and extraction ran outside the job poller that the git clone
paths go through, so a cancelled or timed-out run kept streaming and
extracting an arbitrarily large repository while holding the worker. There is
no wall-clock bound on the download itself, by design, which is exactly why
it needs the poller.

The archive was written to a fixed name inside the job directory, where
`create_file_resources` has already laid down the run's own files at paths
the playbook chooses. A run naming a file `repo_archive.tar.gz` had it
truncated and then deleted. It goes to a per-job temp path now.

Link entries were unpacked with their target unchecked. `Entry::unpack`
writes the link verbatim, so a link out of the tree plus a later entry
descending through it writes wherever it points. Targets now face the same
containment check as entry paths.

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

* fix: keep repo symlinks, refuse only writes that go through them

The link check rejected any target containing `..`, which is ordinary in a
repository — `docs/x -> ../README.md` resolves inside the tree, and a git
checkout keeps it. Rejecting it failed the whole extraction for repositories
the clone path handles, and app-backed repos have no clone path to fall back
to.

Targets are preserved as git preserves them. What would let one escape is a
later entry written at or underneath the link, so that is what is refused.

Extraction also polls an abort flag now: a `spawn_blocking` task outlives the
join handle its caller drops, so a cancelled job left it unpacking in the
background.

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

* fix: refuse hard links in a repository archive

Leaving link targets verbatim is right for symlinks — git checks them out
that way, and an escape needs a second entry descending through the link,
which is refused. A hard link is not like that: unpacking one creates it
against a target resolved there and then, so an escaping target is useful on
its own.

No git tree can express a hard link, so an archive carrying one did not come
from a repository. Refuse it.

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

* chore: update ee-repo-ref to 21f79bbbd39ae89665d1a89738630978616aa309

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

* chore: update ee-repo-ref to 37695a769b25d16b34107eedc1076793a8b388c8

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

Previous ee-repo-ref: 21f79bbbd39ae89665d1a89738630978616aa309

New ee-repo-ref: 37695a769b25d16b34107eedc1076793a8b388c8

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-08-20 22:05:24 +02:00
Ruben Fiszelandrubenfiszel a7637aca31 chore(main): release 1.792.2 (#10753)
* chore(main): release 1.792.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-19 14:15:59 +02:00
Ruben Fiszelandrubenfiszel 9f517d5a40 chore(main): release 1.792.1 (#10750)
* chore(main): release 1.792.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-18 17:10:42 +02:00
Ruben Fiszelandrubenfiszel 8efede55d6 chore(main): release 1.792.0 (#10745)
* chore(main): release 1.792.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-18 12:32:35 +02:00
Ruben Fiszelandrubenfiszel ce71756c89 chore(main): release 1.791.0 (#10718)
* chore(main): release 1.791.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-18 01:55:42 +02:00
Ruben Fiszelandrubenfiszel 010d67e07f chore(main): release 1.790.1 (#10712)
* chore(main): release 1.790.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-17 11:08:47 +02:00
Ruben Fiszelandrubenfiszel 944ad1083a chore(main): release 1.790.0 (#10699)
* chore(main): release 1.790.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-15 14:54:31 +02:00
hugocasaandClaude Opus 5 98bacab907 refactor: combine the per-minute counters onto one shared helper (#10687)
* refactor: combine the per-minute counters onto one shared helper

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

* fix: keep dashmap in windmill-store for the azure devops token cache

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

* refactor: name the sweep counter for what it counts

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-14 18:45:20 +02:00
Ruben Fiszelandrubenfiszel 80a18ec284 chore(main): release 1.789.0 (#10670)
* chore(main): release 1.789.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-13 13:29:52 +02:00
Ruben Fiszelandrubenfiszel b39860235c chore(main): release 1.788.0 (#10664)
* chore(main): release 1.788.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-12 21:17:47 +02:00
Ruben Fiszelandrubenfiszel 2ac3e64fe2 chore(main): release 1.787.0 (#10657)
* chore(main): release 1.787.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-12 13:27:21 +02:00
Ruben Fiszelandrubenfiszel 20953a0c67 chore(main): release 1.786.1 (#10652)
* chore(main): release 1.786.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-12 09:40:03 +02:00
Ruben Fiszelandrubenfiszel 45a6e4932a chore(main): release 1.786.0 (#10649)
* chore(main): release 1.786.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-12 02:22:18 +02:00
Ruben Fiszelandrubenfiszel a65a184a80 chore(main): release 1.785.0 (#10626)
* chore(main): release 1.785.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-11 18:26:31 +00:00
Ruben Fiszel 3394546657 feat(npm-proxy): keep package files on disk and in the object store (#10638)
* docs: design for where the npm proxy keeps cached registry content

* feat(npm-proxy): keep package files on disk and in the object store

* fix(npm-proxy): degrade when the cache is unwritable, stream and bound it

* fix(npm-proxy): keep the happy path off the heap and isolate pull scratch

* fix(npm-proxy): bound the upload, verify pulled trees, keep oversized manifests

* fix(npm-proxy): protect live scratch, bound uploads by parts, refuse traversals

* fix: let the blocking unpack own the scratch it writes into

* fix: replace a cache directory that is not a package instead of deferring to it

* fix: evict by moving a package off the live path, not by deleting it in place

* fix: leave a package the sweep cannot move rather than deleting it in place

* fix: take one registry snapshot through a cache miss

* fix: stamp a pulled package as used so the sweep does not evict it first
2026-08-11 16:40:53 +00:00
Ruben Fiszel a8816b896d feat(ata): prefer the npm proxy when the instance configures a registry (#10632)
* feat(ata): prefer the npm proxy when the instance configures a registry

* fix(npm-proxy): cap tarball extraction and stop pinning a failed config probe

* fix(npm-proxy): keep large packages cacheable by using a single shard

* fix(npm-proxy): cache the archive so a large package is served, not refused

* fix(npm-proxy): read archives off the runtime, keeping only what types need

* fix(npm-proxy): charge a retained entry for what it allocates, not its bytes

* fix(npm-proxy): size retention for real packages and read the manifest back

* fix(npm-proxy): charge path bytes and pin the manifest read-back

* fix(npm-proxy): stop retaining past the budget instead of refusing the package
2026-08-11 12:31:04 +00:00
Ruben Fiszel ceacc17014 fix(raw-apps): respect the instance .npmrc in the raw app editor (#10629)
* feat(raw-apps): route in-browser npm installs through the npm proxy

* fix(npm-proxy): follow npm range semantics and cache packuments

* fix(npm-proxy): bound the packument cache by bytes and stream tarballs

* fix(npm-proxy): keep a v-prefixed pin exact and read the tarball once

* chore(raw-apps): bump the ui_builder pin to the npm-proxy installer
2026-08-11 12:30:40 +02:00
Ruben Fiszelandrubenfiszel cf3ddaa3cc chore(main): release 1.784.0 (#10603)
* chore(main): release 1.784.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-10 22:56:55 +02:00
hugocasaandClaude Opus 5 c09de594b6 feat: version resource values with history, diff and restore (#10596)
* feat: version resource values with history, diff and restore

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

* fix: record resource versions in a trigger so direct writes are covered

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

* fix: show the selected version's value and tighten history write access

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

* perf: gate resource version recording in trigger WHEN clauses

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

* feat: clear a resource's past versions, and address review nits

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

* fix: restore the displayed version and keep author attribution on pooled writes

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

* fix: scope history to the selected workspace and gate clearing on ownership

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

* fix: gate restore on write access and clearing on the signed-in workspace

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

* refactor(frontend): share the version-history row between script and resource drawers

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

* perf: trim resource version history in the monitor sweep, not on write

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

* fix(frontend): match the script versions drawer shell for resource history

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

* perf(frontend): highlight version values instead of mounting monaco

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

* fix(frontend): match the script drawer's code preview presentation

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

* fix: rank version trim in one windowed pass instead of a correlated delete

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

* refactor(frontend): treat the newest version as current by position

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

* perf: gate the resource version trim to an hourly sweep

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

* fix: unnest the version row action and correct the trim cadence docs

* perf: cap the history listing and use sets for reference lookup

* feat: warn when a resource is written more than 60 times a minute

* fix: lower the resource write advisory to 20 per minute

* fix: discard stale history loads and never diff against an unread value

* fix: correct the write advisory boundary and document the eviction lock

* fix: read history and the live value from one snapshot

* refactor: read the drawer's diff baseline from versions, not the live resource

* fix: open the history drawer with no version selected

* fix: disarm the clear confirmation and clear the pane when the selection moves

* fix: explain the missing diff and drop a guard that can no longer fire

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 21:32:18 +02:00
Ruben Fiszelandrubenfiszel 099efa358a chore(main): release 1.783.0 (#10578)
* chore(main): release 1.783.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-07 12:41:05 +02:00
Ruben Fiszelandrubenfiszel d592fb75eb chore(main): release 1.782.0 (#10566)
* chore(main): release 1.782.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-06 12:55:48 +02:00
Ruben Fiszelandrubenfiszel c03bd34be9 chore(main): release 1.781.3 (#10563)
* chore(main): release 1.781.3

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-06 10:02:27 +02:00
Ruben Fiszelandrubenfiszel 74737d16dd chore(main): release 1.781.2 (#10561)
* chore(main): release 1.781.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-06 09:53:18 +02:00
Ruben Fiszelandrubenfiszel c7ea530e1f chore(main): release 1.781.1 (#10556)
* chore(main): release 1.781.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-06 02:17:57 +00:00
Ruben Fiszelandrubenfiszel 9cf307f3ad chore(main): release 1.781.0 (#10528)
* chore(main): release 1.781.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-06 00:04:25 +02:00
Ruben Fiszelandwindmill-internal-app[bot] 4fe4fac358 feat(mcp): serve the 2026-07-28 spec alongside the legacy protocol (#10535)
* feat(mcp): serve the 2026-07-28 spec alongside the legacy protocol

* fix(mcp): keep oauth discovery strict and preserve request limits

* fix(mcp): allow the protocol's own headers through CORS

* fix(mcp): expose the auth challenge to browser clients

* chore: update ee-repo-ref to c1665a881b61616f96ffe7702b44840905304660

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

Previous ee-repo-ref: bc1c001e3e386342415dfb8ac31c6b97f6629320

New ee-repo-ref: c1665a881b61616f96ffe7702b44840905304660

Automated by sync-ee-ref workflow.

---------

Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-08-05 13:52:09 +02:00
Ruben Fiszelandrubenfiszel 055a9c2690 chore(main): release 1.780.0 (#10527)
* chore(main): release 1.780.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-05 00:37:06 +02:00
Ruben Fiszelandrubenfiszel 59072a1273 chore(main): release 1.779.0 (#10496)
* chore(main): release 1.779.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-04 20:45:57 +02:00
Ruben Fiszelandrubenfiszel 4c4d6c98bf chore(main): release 1.778.0 (#10469)
* chore(main): release 1.778.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-08-04 01:49:00 +02:00
386e115daa feat: lazily expand s3 explorer folders one level at a time (#10420)
* feat: wire paged object storage listing module

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

* feat: document list_stored_files_paged endpoint in openapi

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

* feat: lazily expand s3 explorer folders one level at a time

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

* chore: pin ee-repo-ref to the paged listing branch

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

* fix: share object_store credential resolution and surface listing errors

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

* Chevron is cool

* page size 5000

* feat: make the load more row full-width, secondary and chevron-led

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

* fix: render newly loaded flat pages inside already-expanded folders

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

* fix: address review findings in the lazy s3 explorer

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

* fix: address review nits in the lazy s3 explorer

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

* chore: bump ee-repo-ref after merging main

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

* fix: document ambient credential contract and constrain max_keys schema

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

* fix: treat an exhausted page token as exhausted, not as a continuation

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

* chore: bump ee-repo-ref for canonical prefix validation

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

* chore: bump ee-repo-ref for prefix scoping and opaque cursors

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

* fix: invalidate a folder's in-flight load when deleting from it

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

* fix: discard a stale folder page after its level is invalidated

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

* chore: bump ee-repo-ref for bounded local listing

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

* fix: label folders whose final path segment is empty

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

* feat: search files by any part of their path, not just folder prefix

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

* feat: search files by path prefix instead of a full-bucket scan

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

* fix: guard stale search responses and describe prefix search accurately

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

* chore: bump ee-repo-ref for the search prefix fallback fix

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

* chore: regenerate the served openapi specs

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

* chore: bump ee-repo-ref for the search cursor fallback fix

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

* chore: bump ee-repo-ref for the bounded search scan

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

* fix: surface a failed flat listing instead of spinning forever

The flat branch of loadFiles was awaited without a catch, and loadFlatFiles
clears its loading flags only on the success tail. Every caller reaches it
un-awaited, so a rejected listing left the drawer on "Loading content" with
nothing reported. Routing the filter box through this arm made it reachable
per keystroke rather than once per open.

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

* fix: give back the flat cursor when a page fails to load

"Load more" advanced `page` before requesting it, so a failed page left the
cursor pointing at a `listMarkers` slot that was never filled. The retry sent
no marker at all and silently replayed the first page, and the
`listMarkers.length == page` guard kept it there until the listing was reset.

Only reachable now that a failed page is retryable rather than a permanent
spinner.

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

* fix: scope the flat cursor rollback to its own listing

The rollback matched on the page number alone, so a page that failed after a
filter or storage change could roll back the *replacement* listing once it had
reached the same number, stranding its cursor. Tie it to the generation the
request was issued under.

The delete replay loop had the mirrored problem: it re-drove `page` by hand and
carried on past a failed page, leaving `page` ahead of `listMarkers` for good.

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

* fix: skip the delete replay when the fresh listing itself failed

clearAndLoadFiles dropped the result it already computes, so a failed
post-delete listing still ran the replay loop: each page advanced `page` with
an empty `listMarkers`, which never recovers because the marker-length guard
only pushes when the two agree. Every later "Load more" then replayed page one.

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

* fix: stop a superseded lazy load from writing into the search that replaced it

loadFolderPage resolves rather than throwing once its generation is stale, so a
filter change that switches the picker to the flat listing mid-flight left the
lazy branch free to expand a preselected file into the search's results and to
clear the search's loading flags. Guard both on the generation it started under,
as the flat branch already does.

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

* fix: check the listing generation throughout the reveal walk

Revealing a preselected key is a chain of round trips, so checking once at entry
left the rest of the walk free to keep loading after a filter change had already
switched the picker to the search — under the replacement generation, so the
per-level guards inside loadFolderPage saw nothing wrong.

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

* fix: let a late metadata failure clear only its own preview

The handler blanked fileMetadata and filePreview without checking that its
request still owned the pane, so selecting a second file while the first was
still loading meant the first's rejection wiped the second's preview.

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

* fix: key preview ownership on the request, not the selected key

Comparing the selected key let an older request speak for a newer one when both
targeted the same key, which a storage switch does, and made a request whose
selection had moved to something with no metadata return early with the spinner
still up — the case the handler exists to prevent.

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

* fix: clear the preview when the previewed file is deleted

The lazy branch refetches only the affected level and returns, so it never
reached the reset that the flat refresh gets from clearAndLoadFiles. The pane
renders from fileMetadata rather than from the selection, leaving the deleted
file previewed with working download, move and delete actions.

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

* fix: retire the in-flight preview load when its file is deleted

Clearing the pane was not enough: a metadata response computed before the DELETE
landed still repopulated it, restoring the deleted file's preview and its
download, move and delete actions. Deleting now retires the owning request, and
the success and preview writes honour that the same way the failure path does.

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

* fix: clear the preview loading flag when the delete retires its request

Retiring the in-flight metadata load left nobody to report its outcome, so in
lazy mode the pane sat on "Loading..." instead of falling back to the empty
state. The delete owns the flag once it has retired the request.

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

* chore: drop the regenerated openapi deref artifacts

They are generated files that CI only syntax-validates, never checks against
openapi.yaml, and the committed copies already differ from the spec they derive
from by ~9.7k lines. Regenerating here imported that pre-existing drift into a
feature diff, burying ~800 lines of actual change under ~17k lines of other
changes' staleness. Regenerating them is its own chore.

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

* docs: state the flat cursor invariant once, where the cursor lives

It was spelled out at four sites, which is what AGENTS.md asks not to do. The
rule now sits on the declaration it constrains and the guards reference it.

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

* nit ui

* fix: add the paged listing to the served openapi json

openapi_json() embeds openapi-deref.json via include_str!, and the Docker build
regenerates only the yaml artifact, so the json is served exactly as committed —
leaving the new operation out of the Scalar API reference.

Spliced in the operation and the two schemas it references rather than
regenerating, which would have re-imported ~7k lines of pre-existing drift
between the committed artifact and the spec it derives from.

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

* chore: bump ee-repo-ref for the filesystem symlink boundary

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

* chore: update ee-repo-ref to 0373b4bfdaf8dd51533552e2e4de63ceb3c18b4d

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

Previous ee-repo-ref: eb1a765bb9b29e0c94a6e4942c304934fa15406e

New ee-repo-ref: 0373b4bfdaf8dd51533552e2e4de63ceb3c18b4d

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>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-08-04 01:41:06 +02:00