Files
windmill/backend/Cargo.toml
T
Ruben FiszelandClaude Opus 5.5 054109d855 fix: create workspace forks in the background, with progress (#11406)
* fix: create a fork in the background so a proxy timeout cannot cut it

create_fork copies the whole workspace inside the request, which can run
past the route timeout of an ingress in front of Windmill (Envoy's 15s
default), and the UI then reports a failure for a fork still being made.

create_fork?background=true now returns once the request is validated and
records the copy in workspace_fork_creation, which the new
fork_creation_status endpoint reads. The wizard and AI-session forks use it.

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

* fix: drain background forks on shutdown and fork in the background from the CLI

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

* fix: settle fork polls by the fork's existence, adopt in-flight creations

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

* feat: show which part of the copy a fork being created is in

The background copy reports its phase (data tables, settings, resources,
scripts, flows, apps, drafts, triggers) through a watch channel. The heartbeat
task records it on the fork's creation row as soon as it changes, and
fork_creation_status returns it. The fork wizard shows it on its button, and
the CLI logs each step.

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

* fix: join a retried fork creation server-side, settle status by the fork's existence

A retry from the same user and parent joins the creation in flight instead
of being refused, so clients no longer match the refusal's wording, and
another requester can never adopt it. The status route reports a fork that
exists under its parent as completed, whatever its run's record says. Clients
give up on failing polls after a time window rather than a count, which a
rolling deploy can exhaust.

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

* fix: drop fork-creation joins and existence probes

A second request for a fork being created is refused again; only the
AI-session fork, whose request never varies, waits for its own earlier one.
Clients recognise a server without background forks by its synchronous
answer instead of probing for a workspace by id, which could name another
parent's fork.

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

* fix: poll a background fork by the id of its own attempt

create_fork?background=true answers with a creation id, and the status
route reads that attempt only, for the user who started it. A retry that
reuses the fork id is a new attempt, so a poller never reads another
attempt's outcome. The AI-session fork no longer adopts a creation in flight,
which it could not tell apart from someone else's.

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

* fix: record a fork's completion in its own commit, resume a session's fork after reload

The attempt is marked complete in the transaction that creates the fork, so
the status never infers completion from a workspace that may belong to
another request. An AI session keeps the creation id on its pending fork and,
after a reload mid-copy, waits for that attempt instead of requesting the
fork again.

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

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 15:26:41 +02:00

765 lines
34 KiB
TOML

[package]
name = "windmill"
version = "1.819.0"
authors.workspace = true
edition.workspace = true
[workspace]
resolver = "2"
members = [
"./windmill-ai",
"./windmill-object-store",
"./windmill-api",
"./windmill-api-scripts",
"./windmill-api-flows",
"./windmill-api-users",
"./windmill-api-workspaces",
"./windmill-api-groups",
"./windmill-api-auth",
"./windmill-api-sse",
"./windmill-api-jobs",
"./windmill-trigger",
"./windmill-trigger-kafka",
"./windmill-trigger-postgres",
"./windmill-trigger-mqtt",
"./windmill-trigger-amqp",
"./windmill-trigger-websocket",
"./windmill-trigger-email",
"./windmill-trigger-nats",
"./windmill-trigger-sqs",
"./windmill-trigger-gcp",
"./windmill-trigger-azure",
"./windmill-trigger-http",
"./windmill-native-triggers",
"./windmill-alerting",
"./windmill-api-agent-workers",
"./windmill-api-assets",
"./windmill-api-configs",
"./windmill-api-debug",
"./windmill-api-embeddings",
"./windmill-api-flow-conversations",
"./windmill-api-inputs",
"./windmill-api-npm-proxy",
"./windmill-api-openapi",
"./windmill-api-schedule",
"./windmill-api-settings",
"./windmill-api-workers",
"./windmill-store",
"./windmill-queue",
"./windmill-worker",
"./windmill-dep-map",
"./windmill-types",
"./windmill-common",
"./windmill-jseval",
"./windmill-runtime-nativets",
"./windmill-mcp",
"./windmill-audit",
"./windmill-git-sync",
"./windmill-autoscaling",
"./windmill-operator",
"./windmill-indexer",
"./windmill-macros",
"./windmill-oauth",
"./parsers/windmill-parser",
"./parsers/windmill-parser-ts",
"./parsers/windmill-parser-ts-asset",
"./parsers/windmill-parser-go",
"./parsers/windmill-parser-rust",
"./parsers/windmill-parser-csharp",
"./parsers/windmill-parser-nu",
"./parsers/windmill-parser-java",
"./parsers/windmill-parser-ruby",
"./parsers/windmill-parser-r",
"./parsers/windmill-parser-bash",
"./parsers/windmill-parser-py",
"./parsers/windmill-parser-py-asset",
"./parsers/windmill-parser-py-imports",
# Uncomment to build wasm parsers:
# "./parsers/windmill-parser-wasm",
"./parsers/windmill-parser-wac",
"./parsers/windmill-parser-sql",
"./parsers/windmill-parser-sql-asset",
"./parsers/windmill-sql-datatype-parser-wasm",
"./parsers/windmill-parser-yaml", "windmill-macros", "parsers/windmill-parser-nu",
"./windmill-worker-volumes",
"./windmill-test-utils",
"./windmill-api-integration-tests",
]
exclude = ["./windmill-duckdb-ffi-internal", "./parsers/windmill-parser-wasm"]
[workspace.package]
version = "1.819.0"
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
edition = "2021"
[[bin]]
name = "windmill"
path = "./src/main.rs"
[profile.dev]
opt-level = 0
incremental = true
split-debuginfo = "unpacked"
# Type and variable DWARF is the single largest thing in target/ and nothing in the dev loop
# reads it; backtraces only need the line tables, which this keeps. Raise to `true` when you
# actually need to inspect variables in gdb/lldb.
debug = "line-tables-only"
[profile.dev.package."*"]
debug = false
# The expression parser's fallback call chain exhausts worker stacks without optimization.
[profile.dev.package.php-parser-rs]
opt-level = 1
[profile.release]
lto = "thin"
debug = "line-tables-only"
strip = "none"
[features]
default = []
private = ["windmill-api/private", "windmill-api-agent-workers?/private", "windmill-autoscaling/private", "windmill-common/private", "windmill-dep-map/private", "windmill-object-store/private", "windmill-git-sync/private", "windmill-indexer?/private", "windmill-operator?/private", "windmill-queue/private", "windmill-worker/private", "windmill-test-utils/private"]
agent_worker_server = ["windmill-api/agent_worker_server", "dep:windmill-api-agent-workers", "windmill-test-utils/agent_worker_server"]
enterprise = ["windmill-worker/enterprise", "windmill-queue/enterprise", "windmill-api/enterprise", "windmill-api-agent-workers?/enterprise", "dep:windmill-autoscaling", "windmill-autoscaling/enterprise", "windmill-git-sync/enterprise", "windmill-common/prometheus", "windmill-common/enterprise", "windmill-object-store/enterprise", "license"]
local_reports = ["windmill-common/local_reports"]
enterprise_saml = ["windmill-api/enterprise_saml", "oauth2"]
stripe = ["windmill-api/stripe"]
benchmark = ["windmill-api/benchmark", "windmill-worker/benchmark", "windmill-queue/benchmark", "windmill-common/benchmark", "windmill-api-agent-workers?/benchmark"]
embedding = ["windmill-api/embedding"]
parquet = ["windmill-api/parquet", "windmill-common/parquet", "windmill-object-store/parquet", "windmill-worker/parquet"]
prometheus = ["windmill-common/prometheus", "windmill-api/prometheus", "windmill-worker/prometheus", "windmill-queue/prometheus", "dep:prometheus"]
flow_testing = ["windmill-worker/flow_testing"]
failpoints = ["windmill-worker/failpoints", "windmill-queue/failpoints"]
quickjs = ["windmill-worker/quickjs", "windmill-api/quickjs"]
openidconnect = ["windmill-api/openidconnect", "windmill-common/openidconnect", "windmill-object-store/openidconnect"]
cloud = ["windmill-queue/cloud", "windmill-worker/cloud", "windmill-common/cloud", "windmill-api/cloud"]
jemalloc = ["windmill-common/jemalloc", "dep:tikv-jemallocator", "dep:tikv-jemalloc-sys", "dep:tikv-jemalloc-ctl"]
# `tantivy` must stay the only feature that enables windmill-indexer: it is the only one that
# also gives it `enterprise` + `parquet`, and its EE sources gate nearly everything on that
# pair, so a bare windmill-indexer is a crate of dead code that `-D warnings` rejects. Any
# other feature wanting one of its features has to use the optional `windmill-indexer?/` form.
tantivy = ["dep:windmill-indexer", "windmill-api/tantivy", "windmill-indexer/enterprise", "windmill-indexer/parquet", "windmill-common/tantivy", "enterprise", "parquet"]
sqlx = ["windmill-worker/sqlx"]
deno_core = ["windmill-worker/deno_core", "dep:windmill-runtime-nativets", "windmill-test-utils/deno_core"]
deno_core_mac = ["deno_core", "windmill-worker/libffi_mac"]
kafka = ["windmill-api/kafka"]
kafka-gssapi = ["windmill-api/kafka-gssapi"]
nats = ["windmill-api/nats"]
otel = ["windmill-common/otel", "windmill-worker/otel"]
dind = ["windmill-worker/dind"]
websocket = ["windmill-api/websocket"]
http_trigger = ["windmill-api/http_trigger"]
postgres_trigger = ["windmill-api/postgres_trigger"]
mcp = ["windmill-ai/mcp", "windmill-api/mcp", "windmill-worker/mcp"]
bedrock = ["windmill-ai/bedrock", "windmill-api/bedrock", "windmill-worker/bedrock"]
mqtt_trigger = ["windmill-api/mqtt_trigger"]
amqp_trigger = ["windmill-api/amqp_trigger"]
native_trigger = ["windmill-api/native_trigger"]
sqs_trigger = ["windmill-api/sqs_trigger", "windmill-common/aws_auth", "windmill-api/openidconnect"]
gcp_trigger = ["windmill-api/gcp_trigger"]
azure_trigger = ["windmill-api/azure_trigger"]
smtp = ["windmill-api/smtp", "windmill-common/smtp", "windmill-queue/smtp"]
license = ["windmill-api/license", "windmill-api-settings/license"]
oauth2 = ["windmill-api/oauth2"]
zip = ["windmill-api/zip"]
static_frontend = ["windmill-api/static_frontend"]
scoped_cache = ["windmill-common/scoped_cache"]
no_auth = ["windmill-api/no_auth"]
operator = ["dep:windmill-operator"]
test_job_debouncing = []
private_registry_test = []
dev_override = ["windmill-common/dev_override"]
# Languages
python = ["windmill-worker/python", "windmill-api/python", "windmill-test-utils/python"]
rust = ["windmill-worker/rust"]
mysql = ["windmill-worker/mysql"]
oracledb = ["windmill-worker/oracledb"]
duckdb = ["windmill-worker/duckdb"]
mssql = ["windmill-worker/mssql"]
mssql-kerberos = ["windmill-worker/mssql-kerberos"] # Linux/Unix integrated auth
mssql-winauth = ["windmill-worker/mssql-winauth"] # Windows integrated auth
bigquery = ["windmill-worker/bigquery"]
snowflake = ["windmill-worker/snowflake"]
php = ["windmill-worker/php"]
csharp = ["windmill-worker/csharp"]
nu = ["windmill-worker/nu"]
java = ["windmill-worker/java"]
ruby = ["windmill-worker/ruby"]
rlang = ["windmill-worker/rlang"]
all_languages = ["python", "deno_core", "rust", "mysql", "oracledb", "duckdb", "mssql-kerberos", "bigquery", "snowflake", "csharp", "nu", "php", "java", "ruby", "rlang"]
# For windows we have another set of languages enabled
all_languages_windows = ["python", "deno_core", "rust", "mysql", "oracledb", "duckdb", "mssql-winauth", "bigquery", "snowflake", "csharp", "nu", "php", "java", "ruby", "rlang"]
# Edition meta-features: shared groups
run_inline = ["windmill-api/run_inline"]
oss_core = [
"embedding", "parquet", "openidconnect", "license",
"http_trigger", "zip", "oauth2", "postgres_trigger",
"mqtt_trigger", "amqp_trigger", "websocket", "smtp", "native_trigger",
"static_frontend", "mcp", "bedrock", "run_inline",
"quickjs"
]
ce_core = ["oss_core", "private", "operator"]
ee_core = [
"enterprise", "stripe", "prometheus", "cloud",
"kafka", "sqs_trigger", "nats", "gcp_trigger", "azure_trigger",
"jemalloc", "otel", "operator"
]
ee_server = ["enterprise_saml", "tantivy", "agent_worker_server", "local_reports"]
# Edition meta-features: CE variants
oss = ["oss_core", "all_languages", "no_auth"]
ce_rpi = ["ce_core", "all_languages"]
ce = ["ce_rpi", "jemalloc", "dind", "agent_worker_server"]
# Edition meta-features: EE variants
ee = ["ce", "ee_core", "ee_server", "kafka-gssapi"]
ee_rhel = ["ce_core", "ee_core", "kafka-gssapi", "all_languages"]
# The Windows binary is worker-only, but a non-agent worker runs windmill-api on
# localhost (main.rs run_server, `if !is_agent`) and jobs call back into it, so
# it needs every feature its own plumbing or its jobs invoke in-process; drop
# only external/server-facing surface the worker never runs.
worker_windows_core = ["private", "operator", "parquet", "quickjs", "enterprise", "prometheus", "otel", "jemalloc", "windmill-worker/mcp", "windmill-store/mcp", "windmill-worker/bedrock", "openidconnect", "run_inline", "windmill-api/instance_smtp", "oauth2"]
ee_windows = ["worker_windows_core", "all_languages_windows"]
all_sqlx_features = ["all_languages", "enterprise", "enterprise_saml", "embedding", "parquet", "prometheus", "flow_testing",
"openidconnect", "cloud", "jemalloc", "tantivy", "sqlx", "kafka", "kafka-gssapi", "nats", "otel", "dind", "websocket", "http_trigger",
"postgres_trigger", "mcp", "mqtt_trigger", "amqp_trigger", "sqs_trigger", "gcp_trigger", "azure_trigger", "smtp", "stripe",
"license", "oauth2", "zip", "static_frontend", "scoped_cache", "agent_worker_server", "bedrock", "native_trigger", "quickjs",
"windmill-git-sync/all_sqlx_features"]
[patch.crates-io]
# v0.8.6 plus one commit: `Pool::begin` is not cancel-safe on Postgres. sqlx raises the
# transaction depth its rollback-on-drop guard keys on only *after* the BEGIN round trip, so
# a cancelled caller (a disconnecting API client, a `timeout`, an aborted task) leaves the
# session in a transaction nothing will end, and the pool hands that connection out again —
# every later query on it fails with 25P02 until max_lifetime recycles it 30 minutes on.
# Reported upstream in 2022 (launchbadge/sqlx#2054), fixed for SQLite only, and still present
# in 0.9.0. Drop this the moment upstream carries the fix.
# The whole family has to move together: `sqlx-postgres` depends on `sqlx-core` by path
# inside the sqlx workspace, so patching it alone leaves two incompatible `sqlx-core`s and
# `Postgres` stops implementing the `Database` the macros expect.
# Changing any of this — a bump, a rebase of the fork, dropping these lines — still compiles
# clean, so run the guard that actually checks the behaviour is still there:
# cargo test -p windmill-common --test sqlx_begin_cancel_safe -- --ignored
sqlx = { git = "https://github.com/windmill-labs/sqlx", rev = "6bdaee94fa62a01561125646da3f99eb341f2457" }
sqlx-core = { git = "https://github.com/windmill-labs/sqlx", rev = "6bdaee94fa62a01561125646da3f99eb341f2457" }
sqlx-macros = { git = "https://github.com/windmill-labs/sqlx", rev = "6bdaee94fa62a01561125646da3f99eb341f2457" }
sqlx-macros-core = { git = "https://github.com/windmill-labs/sqlx", rev = "6bdaee94fa62a01561125646da3f99eb341f2457" }
sqlx-postgres = { git = "https://github.com/windmill-labs/sqlx", rev = "6bdaee94fa62a01561125646da3f99eb341f2457" }
sqlx-mysql = { git = "https://github.com/windmill-labs/sqlx", rev = "6bdaee94fa62a01561125646da3f99eb341f2457" }
sqlx-sqlite = { git = "https://github.com/windmill-labs/sqlx", rev = "6bdaee94fa62a01561125646da3f99eb341f2457" }
object_store = { git = "https://github.com/apache/arrow-rs-object-store", rev = "36752c975d4f29e20b57c91f81a10872dcd48ae7" }
# Use tiberius main branch for libgssapi 0.8.1 fix (https://github.com/prisma/tiberius/issues/343)
tiberius = { git = "https://github.com/prisma/tiberius", rev = "59db57960a14b422fb3a1309aa4aa47880896ff8" }
# Pin tokio-postgres / postgres-types / postgres-protocol to the
# MaterializeInc fork. windmill-trigger-postgres already pulled this
# fork in transitively for the postgres-replication crate
# (CopyBothDuplex, LogicalReplicationStream, TupleData with binary
# tuple support) which upstream rust-postgres has declined to merge
# since 2021 (PR #752 → #778, both still unmerged).
#
# MI also carries a mitigation for the
# Client::query_typed_raw / Client::prepare deadlock on result columns
# whose Oid the client doesn't know about yet (citext, custom enums /
# domains, postgis): MI's 2025-12-11 PR #33 resized the per-request
# response channel from mpsc::channel(1) → mpsc::channel(1024).
# bounded(1024) is sufficient for any realistic typeinfo deferral
# (need ~2-3 batches) but leaves a theoretical failure mode at
# >~64 MB results with a custom-Oid column. The strict-correct fix is
# mpsc::unbounded(); a follow-up PR to MI is open proposing that.
#
# The [patch.crates-io] entries below force windmill-worker's
# pg_executor (which imports `tokio_postgres::` directly from
# crates.io) onto the same fork as windmill-trigger-postgres, so the
# deadlock mitigation reaches both consumers.
#
# Upstream deadlock PRs (open, not on the critical path now that MI
# is mitigated):
# https://github.com/rust-postgres/rust-postgres/pull/1348
# https://github.com/rust-postgres/rust-postgres/pull/1349
# Reproducer: https://github.com/rubenfiszel/tokio-postgres-deadlock-repro
tokio-postgres = { git = "https://github.com/MaterializeInc/rust-postgres", rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe" }
postgres-types = { git = "https://github.com/MaterializeInc/rust-postgres", rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe" }
postgres-protocol = { git = "https://github.com/MaterializeInc/rust-postgres", rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe" }
[dependencies]
anyhow.workspace = true
tokio.workspace = true
tokio-stream.workspace = true
dotenv.workspace = true
windmill-ai = { workspace = true, default-features = false }
windmill-queue.workspace = true
windmill-common = { workspace = true, default-features = false }
windmill-object-store.workspace = true
windmill-git-sync.workspace = true
windmill-store.workspace = true
windmill-api = { workspace = true, default-features = false }
windmill-api-agent-workers = { workspace = true, optional = true }
windmill-api-scripts.workspace = true
windmill-api-settings.workspace = true
windmill-worker.workspace = true
windmill-indexer = { workspace = true, optional = true }
windmill-autoscaling = { workspace = true, optional = true }
windmill-operator = { workspace = true, optional = true }
futures.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
sqlx.workspace = true
sql-builder.workspace = true
rand.workspace = true
chrono.workspace = true
git-version.workspace = true
base64.workspace = true
sha2.workspace = true
url.workspace = true
lazy_static.workspace = true
once_cell.workspace = true
prometheus = { workspace = true, optional = true }
uuid.workspace = true
gethostname.workspace = true
serde_json.workspace = true
serde_derive.workspace = true
serde_yml.workspace = true
serde.workspace = true
windmill-runtime-nativets = { workspace = true, optional = true }
sha1 = { workspace = true, optional = true }
constant_time_eq = { workspace = true, optional = true }
rustls.workspace = true
strum.workspace = true
[target.'cfg(windows)'.dependencies]
windows-service = "0.7"
windows-sys = { version = "0.52", features = ["Win32_System_Services", "Win32_System_Console", "Win32_Foundation"] }
[target.'cfg(not(target_env = "msvc"))'.dependencies]
tikv-jemallocator = { optional = true, workspace = true }
tikv-jemalloc-sys = { optional = true, workspace = true }
tikv-jemalloc-ctl = { optional = true, workspace = true }
[dev-dependencies]
serde_json.workspace = true
reqwest.workspace = true
windmill-queue = { workspace = true, features = ["failpoints"] }
windmill-dep-map.workspace = true
windmill-test-utils.workspace = true
windmill-worker-volumes.workspace = true
windmill-types.workspace = true
opentelemetry = { workspace = true }
opentelemetry_sdk = { workspace = true }
windmill-trigger.workspace = true
serial_test = "3"
windmill-trigger-websocket.workspace = true
windmill-trigger-postgres.workspace = true
windmill-trigger-mqtt.workspace = true
windmill-trigger-kafka.workspace = true
windmill-trigger-nats.workspace = true
windmill-trigger-sqs.workspace = true
windmill-trigger-gcp.workspace = true
windmill-trigger-azure.workspace = true
windmill-api-auth.workspace = true
tower-cookies.workspace = true
windmill-api-users.workspace = true
axum.workspace = true
serde.workspace = true
windmill-api-client.workspace = true
tempfile.workspace = true
tar.workspace = true
windmill-parser-ts.workspace = true
rumqttc.workspace = true
rdkafka.workspace = true
async-nats.workspace = true
aws-sdk-sqs.workspace = true
aws-config.workspace = true
aws-credential-types.workspace = true
hmac.workspace = true
hex.workspace = true
jsonwebtoken = { workspace = true }
[workspace.dependencies]
windmill-ai = { path = "./windmill-ai", default-features = false }
windmill-api = { path = "./windmill-api", default-features = false }
windmill-queue = { path = "./windmill-queue" }
windmill-worker = { path = "./windmill-worker" }
windmill-worker-volumes = { path = "./windmill-worker-volumes" }
windmill-dep-map = { path = "./windmill-dep-map" }
windmill-types = { path = "./windmill-types" }
windmill-common = { path = "./windmill-common", default-features = false }
windmill-object-store = { path = "./windmill-object-store" }
windmill-audit = { path = "./windmill-audit" }
windmill-git-sync = { path = "./windmill-git-sync" }
windmill-autoscaling = { path = "./windmill-autoscaling" }
windmill-operator = { path = "./windmill-operator" }
windmill-indexer = {path = "./windmill-indexer"}
windmill-mcp = {path = "./windmill-mcp"}
windmill-oauth = {path = "./windmill-oauth"}
windmill-macros = {path = "./windmill-macros"}
windmill-api-auth = { path = "./windmill-api-auth" }
windmill-api-scripts = { path = "./windmill-api-scripts" }
windmill-api-flows = { path = "./windmill-api-flows" }
windmill-api-users = { path = "./windmill-api-users" }
windmill-api-workspaces = { path = "./windmill-api-workspaces" }
windmill-api-groups = { path = "./windmill-api-groups" }
windmill-api-sse = { path = "./windmill-api-sse" }
windmill-api-jobs = { path = "./windmill-api-jobs" }
windmill-trigger = { path = "./windmill-trigger" }
windmill-trigger-kafka = { path = "./windmill-trigger-kafka" }
windmill-trigger-postgres = { path = "./windmill-trigger-postgres" }
windmill-trigger-mqtt = { path = "./windmill-trigger-mqtt" }
windmill-trigger-amqp = { path = "./windmill-trigger-amqp" }
windmill-trigger-websocket = { path = "./windmill-trigger-websocket" }
windmill-trigger-email = { path = "./windmill-trigger-email" }
windmill-trigger-nats = { path = "./windmill-trigger-nats" }
windmill-trigger-sqs = { path = "./windmill-trigger-sqs" }
windmill-trigger-gcp = { path = "./windmill-trigger-gcp" }
windmill-trigger-azure = { path = "./windmill-trigger-azure" }
windmill-trigger-http = { path = "./windmill-trigger-http" }
windmill-native-triggers = { path = "./windmill-native-triggers" }
windmill-alerting = { path = "./windmill-alerting" }
windmill-api-agent-workers = { path = "./windmill-api-agent-workers" }
windmill-api-assets = { path = "./windmill-api-assets" }
windmill-api-configs = { path = "./windmill-api-configs" }
windmill-api-debug = { path = "./windmill-api-debug" }
windmill-api-embeddings = { path = "./windmill-api-embeddings" }
windmill-api-flow-conversations = { path = "./windmill-api-flow-conversations" }
windmill-api-inputs = { path = "./windmill-api-inputs" }
windmill-api-npm-proxy = { path = "./windmill-api-npm-proxy" }
windmill-api-openapi = { path = "./windmill-api-openapi" }
windmill-api-schedule = { path = "./windmill-api-schedule" }
windmill-api-settings = { path = "./windmill-api-settings" }
windmill-api-workers = { path = "./windmill-api-workers" }
windmill-store = { path = "./windmill-store" }
windmill-parser = { path = "./parsers/windmill-parser" }
windmill-parser-ts = { path = "./parsers/windmill-parser-ts" }
windmill-parser-ts-asset = { path = "./parsers/windmill-parser-ts-asset" }
windmill-parser-py = { path = "./parsers/windmill-parser-py" }
windmill-parser-py-asset = { path = "./parsers/windmill-parser-py-asset" }
windmill-parser-py-imports = { path = "./parsers/windmill-parser-py-imports" }
windmill-parser-go = { path = "./parsers/windmill-parser-go" }
windmill-parser-rust = { path = "./parsers/windmill-parser-rust" }
windmill-parser-yaml = { path = "./parsers/windmill-parser-yaml" }
windmill-parser-csharp = { path = "./parsers/windmill-parser-csharp" }
windmill-parser-java = { path = "./parsers/windmill-parser-java" }
windmill-parser-ruby = { path = "./parsers/windmill-parser-ruby" }
windmill-parser-r = { path = "./parsers/windmill-parser-r" }
windmill-parser-nu = { path = "./parsers/windmill-parser-nu" }
windmill-parser-bash = { path = "./parsers/windmill-parser-bash" }
windmill-parser-sql = { path = "./parsers/windmill-parser-sql" }
windmill-parser-sql-asset = { path = "./parsers/windmill-parser-sql-asset" }
windmill-parser-graphql = { path = "./parsers/windmill-parser-graphql" }
windmill-parser-php = { path = "./parsers/windmill-parser-php" }
windmill-parser-wac = { path = "./parsers/windmill-parser-wac" }
windmill-jseval = { path = "./windmill-jseval" }
windmill-runtime-nativets = { path = "./windmill-runtime-nativets" }
windmill-api-client = { path = "./windmill-api-client" }
windmill-test-utils = { path = "./windmill-test-utils" }
reqwest-retry = "^0"
reqwest-middleware = { version = "^0", features = ["json"] }
bitflags = "2.9.4"
memchr = "2.7.4"
axum = { version = "^0.8", features = ["multipart", "macros"] }
headers = "^0"
hyper = { version = "^1", features = ["full"] }
hyper-tls = "^0.6"
hyper-util = { version = "^0.1", features = ["client-legacy", "http1", "tokio"] }
tokio = { version = "=1.46.1", features = ["full", "tracing", "time"] }
tokio-stream = { version = "0.1.17" }
tower = "^0"
tower-http = { version = "^0.6", features = ["trace", "cors", "catch-panic"] }
tower-cookies = "^0.11"
serde = "^1"
# 1.0.151 introduced RawValue::from_string_unchecked, which the SQL executors use
# to avoid re-parsing every collected row.
serde_json = { version = "^1.0.151", features = ["preserve_order", "raw_value"] }
serde_yml = "0.0.12"
uuid = { version = "^1", features = ["serde", "v4", "js"] }
thiserror = "^2"
anyhow = "^1"
chrono = { version = "^0.4", features = ["serde"] }
chrono-tz = "^0.10.1"
derive_more = { version = "1", features = ["deref", "deref_mut"], default-features = false }
tracing = "^0"
tracing-subscriber = { version = "^0", features = ["env-filter", "json"] }
tracing-appender = "^0"
prometheus = { version = "^0", default-features = false }
cookie = { version = "0.18.0" }
phf = { version = "0.11", features = ["macros"] }
rust-embed = { version = "^6", features = ["interpolate-folder-path"] }
mime_guess = "^2"
hex = "^0"
sql-builder = "^3"
# Minor-pinned rather than the `^0` used elsewhere in this file: argon2's 0.x
# minors are API-breaking (0.6 moved `SaltString` into `phc`, put `rand_core`
# behind a feature and changed `hash_password`), so a float breaks the build.
argon2 = "0.6"
quick_cache = "^0"
rand = "^0.9.3"
rand_core = { version = "^0", features = ["std"] }
arc-swap = "1"
ed25519-dalek = { version = "2", features = ["rand_core"] }
magic-crypt = "^3"
git-version = "^0"
malachite = "=0.4.18"
malachite-bigint = "=0.2.0"
rustpython-parser = "^0"
pep440_rs = "0.7.3"
php-parser-rs = { git = "https://github.com/php-rust-tools/parser", rev = "ec4cb411dec09450946ef57920b7ffced7f6495d" }
cron = "^0"
mail-send = { version = "0.4.0", features = ["builder"], default-features=false }
urlencoding = "^2"
quick-xml = { version = "^0.37", features = ["serialize"] }
url = { version = "^2" , features = ["serde"]}
async-oauth2 = "0.5.1"
reqwest = { version = "^0.13", features = ["json", "stream", "gzip", "multipart", "query", "form"] }
# The reqwest object_store builds its HTTP clients with, for a custom `HttpConnector`.
reqwest_object_store = { package = "reqwest", version = "0.12", default-features = false, features = ["rustls-tls-native-roots"] }
eventsource-stream = "0.2.3"
time = "^0"
serde_urlencoded = "^0"
astral-tokio-tar = "^0.6.2"
tempfile = "^3"
x509-parser = "^0.16"
tokio-util = { version = "=0.7.17", features = ["io", "rt"] }
json-pointer = "^0"
itertools = "^0.14.0"
regex = "^1"
semver = "^1"
aws-sigv4 = "^1.3.4"
aws-sdk-config = "^1.94.0"
aws-sdk-rds = "^1"
async-trait = "0.1.88"
v8 = "=137.1.0" # Exact version NOTE: Do not forget to update version and hash in flake.nix
# deno_* pin set: deno v2.4.0 base, with deno_ast force-overridden to =0.51.0.
# Rationale: deno_ast 0.51.0 is the first version pulling swc_common =14.0.4,
# the first swc_common patch that dropped `pub use serde::__private as serde;`
# (the line that capped our workspace serde pin at =1.0.220). v2.4.0's other
# pins keep deno_tls at 0.196.0 which uses permissive `rustls ^0.23.11`,
# compatible with aws-sdk-bedrockruntime's `^0.23.31` requirement. deno_tls
# 0.198+ tightened that to exact `=0.23.28`, which would have made any
# meaningful deno bump resolver-impossible against aws-sdk.
deno_fetch = "0.233.0"
deno_tls = "0.196.0"
deno_console = "0.209.0"
deno_url = "0.209.0"
deno_webidl = "0.209.0"
deno_web = "0.240.0"
# Sibling release of the pinned deno_core 0.352 / deno_web 0.240 stack
# (its deps are deno_core ^0.352, deno_web ^0.240, deno_error =0.6.1). A newer
# deno_crypto would force bumping the whole deno stack.
deno_crypto = "0.223.0"
deno_io = "0.119.0"
deno_fs = "0.119.0"
deno_net = "0.201.0"
deno_core = "0.352.0"
deno_ast = { version = "=0.51.0", features = ["transpiling"] }
deno_permissions = "0.68.0"
deno_telemetry = "0.31.0"
deno_error = "=0.6.1"
rustls-pemfile = "2.2.0"
# only used with special deno_core_mac feature to prevent ffi issue on macos, requires libffi to be installed
libffi-sys = { version = "2.3.0", features = ["system"]}
# `external-account` is off in the crate's defaults, which compiles out the token source for
# Workload Identity Federation credentials — the keyless setup for running outside GCP. Without it
# an ADC file of that type is rejected as an unsupported account type.
google-cloud-pubsub = { version = "0.30.0", features = ["external-account"] }
google-cloud-googleapis = {version = "0.16.1", features = ["pubsub"]}
# TODO: remove once deno fixes the issue on their end
# https://github.com/denoland/deno/issues/28557
winapi = { version = "0.3.9", features = ["sysinfoapi"] }
sysinfo = { version = "0.32.1" }
swc_common = "=14.0.4"
swc_ecma_parser = "=24.0.3"
swc_ecma_ast = "=15.0.0"
swc_ecma_visit = "=15.0.0"
async-recursion = "^1"
base64 = "^0.22.1"
base32 = "^0"
hmac = "0.12.1"
sha2 = "0.10.6"
md-5 = "0.10.6"
sha1 = "0.10.6"
sqlx = { version = "0.8.0", features = [
"macros",
"migrate",
"uuid",
"json",
"chrono",
"postgres",
"runtime-tokio-rustls",
"bigdecimal"
] }
bigdecimal = {version = "^0"}
dotenv = "^0"
ulid = { version = "^1", features = ["uuid"] }
futures = "^0"
futures-core = "^0"
lazy_static = "1.4.0"
serde_derive = "1.0.147"
const_format = { version = "0.2.35", features = ["rust_1_64", "rust_1_51"] }
const-str = "0.5"
constant_time_eq = "0.3.1"
rsa = "^0"
spki = { version = "0.7", features = ["pem"] }
pkcs1 = "0.7"
aes-gcm = "0.10.3"
async_zip = { version = "0.0.17", features = ["tokio", "tokio-fs", "deflate", "chrono"] }
once_cell = "1.17.1"
dashmap = "6.1.0"
gosyn = "0.2.6"
bytes = "1.4.0"
gethostname = "0.4.3"
# Not pinned exactly: the excluded `parsers/windmill-parser-wasm` workspace pins
# =0.2.103 to match its vendored `cli/wasm/*` artifacts, yet path-depends on
# sibling parser crates that inherit this requirement from here. Two exact pins
# on the same semver range cannot both resolve, so keep this a range and let each
# workspace's lockfile settle it (here, js-sys forces 0.2.108).
wasm-bindgen = "0.2"
serde-wasm-bindgen = "^0"
wasm-bindgen-test = "^0"
convert_case = "0.6.0"
getrandom = "0.2"
tokio-postgres = {version = "^0.7", features = ["array-impls", "with-serde_json-1", "with-chrono-0_4", "with-uuid-1", "with-bit-vec-0_6"]}
postgres-protocol = "0.6"
rust-postgres = { package = "tokio-postgres", git = "https://github.com/MaterializeInc/rust-postgres", rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe"}
rust-postgres-native-tls = { package = "postgres-native-tls", git = "https://github.com/MaterializeInc/rust-postgres", features = ["runtime"], rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe" }
bit-vec = "=0.6.3"
mappable-rc = "^0"
mysql_async = { version = "*", default-features = false, features = ["minimal", "default", "native-tls-tls", "rust_decimal"]}
postgres-native-tls = "^0"
native-tls = ">=0.2, <0.2.17"
# samael will break compilation on MacOS. Use this fork instead to make it work
# samael = { git="https://github.com/njaremko/samael", rev="464d015e3ae393e4b5dd00b4d6baa1b617de0dd6", features = ["xmlsec"] }
libxml = { version = "=0.3.3" }
samael = { git="https://github.com/njaremko/samael", rev="f879f1942ec1b34b6d3027ce7e4724ad95d15dfa", features = ["xmlsec"] }
gcp_auth = "0.9.0"
rust_decimal = { version = "^1", features = ["db-postgres", "serde-float"]}
# aws_lc_rs, not rust_crypto: the RustCrypto backend refuses RSA keys above 4096 bits, and
# external/guest JWT issuers may sign with 8192-bit keys.
jsonwebtoken = { version = "^10.3", features = ["aws_lc_rs"] }
pem = "3.0.1"
nix = { version = "0.27.1", features = ["process", "signal"] }
fs4 = "0.13"
tinyvector = { git = "https://github.com/windmill-labs/tinyvector", rev = "20823b94c20f2b9093f318badd24026cf54dcc85" }
hf-hub = "0.4.3"
tokenizers = "0.14.1"
candle-core = "0.9.1"
candle-transformers = "0.9.1"
candle-nn = "0.9.1"
tiberius = { version = "0.12.3", default-features = false, features = ["rustls", "tds73", "chrono", "sql-browser-tokio"]}
pin-project = "1"
indexmap = { version = "2.2.5", features = ["serde"]}
tokio-native-tls = "^0"
openssl = "=0.10"
mail-parser = "^0"
matchit = "=0.7.3"
rdkafka = { version = "0.36.2", features = ["cmake-build", "ssl-vendored", "curl-static"] }
rdkafka-sys = "=4.9.0"
pg_escape = "0.1.1"
async-nats = "0.38.0"
nkeys = "0.4.4"
nu-parser = { version = "0.101.0", default-features = false }
globset = "0.4.16"
croner = "2.2.0"
rmcp = { version = "=3.1.0", features = ["client", "transport-streamable-http-client", "transport-streamable-http-client-reqwest"] }
rquickjs = { version = "0.11", features = ["futures", "parallel", "macro"] }
process-wrap = { version = "8.2.1", features = ["tokio1"] }
systemstat = "0.2.4"
datafusion = "47.0.0"
# The row API only: a dbt engine's parquet index is six string columns, so this
# needs no arrow and no writer. `parquet` is already in the tree with `arrow` for
# every shipped edition (`oss_core`), and cargo unifies the features there; this
# set is what a build WITHOUT object storage compiles. ZSTD is what the engine
# writes today, snap what parquet writers most often default to.
parquet = { version = "55.2.0", default-features = false, features = ["snap", "zstd"] }
object_store = { git = "https://github.com/apache/arrow-rs-object-store", rev = "36752c975d4f29e20b57c91f81a10872dcd48ae7", features = ["aws", "azure", "gcp"] }
openidconnect = { version = "4.0.0-rc.1" }
aws-config = "^1"
aws-sdk-bedrock = "1.129.0"
aws-sdk-bedrockruntime = "=1.122.0"
aws-credential-types = "^1"
aws-smithy-types = "^1"
aws-sdk-secretsmanager = "^1"
aws-sdk-sqs = "^1.89.0"
aws-sdk-sts = "^1.91.0"
aws-sdk-sso = "=1.77.0"
aws-sdk-ssooidc = "=1.78.0"
rustls = "=0.23.35"
async-once-cell = "0.5.4"
size = "0.5.0"
aws-smithy-types-convert = { version = "^0", features = ["convert-chrono"] }
crc = "^3"
tar = "^0"
flate2 = "^1"
http = "^1"
async-stream = "^0"
opentelemetry = "0.30.0"
tracing-opentelemetry = "0.31.0"
opentelemetry_sdk = { version = "0.30.0", features = ["rt-tokio", "testing"] }
opentelemetry-otlp = { version = "0.30.0", features = ["grpc-tonic", "tls", "http-proto", "gzip-tonic", "zstd-tonic"] }
opentelemetry-appender-tracing = "0.30.0"
opentelemetry-semantic-conventions = { version = "0.30.0", features = ["semconv_experimental"] }
opentelemetry-proto = { version = "0.30.0", features = ["with-serde", "gen-tonic"] }
prost = "0.13"
bollard = "0.18.1"
tonic = { version = "^0.13", features = ["tls-native-roots"] }
byteorder = "1.5.0"
tikv-jemallocator = { version = "0.5" }
tikv-jemalloc-sys = { version = "^0.5" }
tikv-jemalloc-ctl = { version = "^0.5" }
triomphe = "^0"
pin-project-lite = "^0"
tantivy = { git="https://github.com/windmill-labs/tantivy", rev="ea3b818c7b93db0c2b5db4f5e7ffef38f339060a" }
backon = "1.3.0"
flume = { version = "0.11.1", features = ["async"] }
kube = { version = "1.1.0", features = ["runtime", "derive"] }
schemars = "0.8"
k8s-openapi = { version = "0.25.0", features = ["latest"] }
libloading = "0.8.8"
# Macro-related
proc-macro2 = "1.0"
pulldown-cmark = "0.9"
toml = "0.7"
syn = { version = "2.0.74", features = ["full"] }
quote = "1.0.36"
regex-lite = "0.1.6"
yaml-rust = "0.4.5"
tokio-tungstenite = { version = "0.24.0", features = ["native-tls"] }
tree-sitter = { version = "=0.23.2", features = [] }
tree-sitter-c-sharp = "=0.23.1"
tree-sitter-java = "=0.23.5"
tree-sitter-ruby = "=0.23.1"
tree-sitter-r = "=1.2.0"
oracle = { version = "0.6.3", features = ["chrono"] }
rumqttc = { version = "0.24.0", features = ["use-native-tls"]}
lapin = "2.5"
tokio-executor-trait = "2.1"
tokio-reactor-trait = "1.1"
strum = { version = "0.27", features = ["derive"] }
strum_macros = "0.27"
hudsucker = { version = "0.22", features = ["rcgen-ca", "native-tls-client"] }
hyper-http-proxy = { version = "1", default-features = false, features = ["rustls-tls-native-roots"] }
hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "ring", "tls12"] }
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"] }
rustls-native-certs = "0.8"
webpki-roots = "1"
rcgen = "0.13"