mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 16:02:14 +00:00
c19441bc8cb2da064e4ad44d77dc04ab8bbb22ec
26 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2ddf93de96 | fix(auth): enforce monotonic privilege on user token lifecycle endpoints (#9371) | ||
|
|
b125eca762 |
feat(service-accounts): allow choosing role at creation time (#9307)
* [ee] feat(service-accounts): allow choosing role at creation time Previously, service accounts were hardcoded to operator and could not be used as the CLI sync user since they had no write access. They also only counted as 0.5 seat each. This change: - Extends `NewServiceAccount` to accept optional `is_admin` / `operator` (defaults to `operator=true` for backward compatibility). - Exposes a role picker in `AddUser.svelte` when creating a service account (Operator / Developer / Admin). - Lets admins update a service account's role from the user list (it used to be locked to "Operator" with a tooltip). - Updates the OpenAPI spec + regenerates the frontend client. A developer/admin service account counts as 1 seat under the existing seat-cap logic (operators stay at 0.5). Companion PR on windmill-ee-private updates the `INSERT INTO usr` to honour the chosen role. Fixes WIN-1985 * [ee] feat(service-accounts): wm_deployers opt-in for Dev role When creating a service account with role=Developer, surface a toggle "Add to wm_deployers" (recommended). Members of wm_deployers can deploy on behalf of other users — the typical setup when the service account is used as the CLI sync / CI deploy identity. - `NewServiceAccount` gains an optional `add_to_deployers` flag. - Frontend defaults the toggle to on but only shows it under Developer (admins have it implicitly; operators can't deploy). - Tooltip links to docs.windmill.dev "Run on behalf of". Companion EE PR updates the handler to INSERT into usr_to_group for wm_deployers when the flag is set. Refs WIN-1985 * chore: update ee-repo-ref to 974ed42067d9f63acb42332b671b8c01ffd4b625 This commit updates the EE repository reference after PR #589 was merged in windmill-ee-private. Previous ee-repo-ref: f7dbc3cc2ba21c396f4828881e3b9d9ab6f50c69 New ee-repo-ref: 974ed42067d9f63acb42332b671b8c01ffd4b625 Automated by sync-ee-ref workflow. * [ee] fix(service-accounts): unhardcode role in superadmin user list Two review issues from the merged #9307 / #589: 1. P1 — The global Users tab in #superadmin-settings still pinned every service account to "Operator". Now it shows the actual role (Admin / Operator / Developer), derived from the SA's usr row. - `list_users_as_super_admin`: replaced `true as operator_only` with the real `operator` value, and added `is_workspace_admin` from the row (NULL for password users since their admin status is per-workspace). - `global_whoami`: when the email belongs to a service account, look up its real `operator` / `is_admin` instead of pinning to operator. - `SuperadminSettingsInner.svelte`: drop the hardcoded "Operator" badge; render Admin / Operator / Developer using the new fields, matching the workspace-level view. 2. P2 — Regenerate the bundled `openapi-deref.{yaml,json}` so the `createServiceAccount` body (now exposing `is_admin`, `operator`, `add_to_deployers`) and the new `GlobalUserInfo.is_workspace_admin` field show up at runtime in `/api/openapi.{yaml,json}`. Bumps `ee-repo-ref.txt` to the EE follow-up that adds the offline seat-cap check on `create_service_account`. Refs WIN-1985 * chore: update ee-repo-ref to b7a6068c1f3dc845e012959268b2426f0de4d697 This commit updates the EE repository reference after PR #590 was merged in windmill-ee-private. Previous ee-repo-ref: 0b1307c21d1bfd6fb43a03c2ba39d2a8bf8e6470 New ee-repo-ref: b7a6068c1f3dc845e012959268b2426f0de4d697 Automated by sync-ee-ref workflow. --------- Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
e5286f4607 |
feat: include service accounts in instance settings users list (#9157)
* feat: include service accounts in instance settings users list Service accounts (workspace-scoped, no password row) now appear in the superadmin users list with a Bot icon, workspace badge, and a link to manage them in the workspace settings. Role is locked to Operator. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: update sqlx offline cache Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: use composite key for users each block Service accounts can share emails across workspaces, so key by email + workspace_id to avoid Svelte each_key_duplicate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d666e8431c |
feat: read-only flag on API tokens (#9144)
* feat: read-only flag on API tokens, orthogonal to scopes Add a per-token `read_only` boolean set at creation time. When true, the token can only call HTTP methods classified as Read (GET/HEAD/OPTIONS). Mutating methods and job-run actions are rejected with 403, regardless of which scopes are attached. Surfaced as a prominent toggle in the standard token-creation flow and a discreet `2xs` toggle in MCP mode (where users often want write access, so we don't bias them toward enabling it). MCP enforcement: read-only tokens hide all script/flow/hub tools from `list_tools` and only see endpoint tools whose method is GET, and the runner rejects `call_tool` on anything mutating. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: review fixes for read-only token flag - Exempt /api/mcp/* and /mcp/* paths from the read-only middleware check. MCP transport runs over POST (streamable HTTP / SSE), so otherwise the middleware would 403 every MCP request before the runner could enforce read-only at the tool-call level. - Tighten is_endpoint_read_only to GET only, matching the read_only_hint that create_endpoint_annotations actually emits. - Add unit test for check_read_only_for_route covering GET/HEAD/OPTIONS, mutating methods, and run paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: bump ee-repo-ref to read-only-trigger-toggle Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(frontend): make read-only toggle discreet in both modes Match the MCP-mode treatment in standard mode: text-tertiary, 2xs, shared "Read-only" label. The tooltip switches per mode so the explanation still fits the context. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(frontend): gate read-only toggle behind Limit token permissions The read-only toggle now only shows when the user has limited the token's scopes (standard mode) or in MCP mode (which always picks an MCP scope). Turning the limit off also resets read-only so it doesn't silently stick. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(frontend): hide incompatible MCP tools when read-only is on When the read-only toggle is on in MCP mode: - Endpoint badges and the custom-mode endpoint MultiSelect filter to GET. - Already-selected non-GET endpoints are pruned from the scope. - The scripts/flows preview is replaced with a note explaining they're hidden (the runner already rejects script/flow runs for read-only). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(frontend): place read-only toggle at top of limited scope area The previous gate required at least one scope to be picked before the read-only toggle appeared, which made it look missing while the user was still building their scope list. Move the toggle inside ScopesPicker: - Standard mode: sits directly under the "Limit token permissions" toggle whenever Limit is on, before the scope selector. - MCP mode: sits at the top of the MCP scope block. readOnly is now $bindable on ScopesPicker so CreateToken still owns the value. The auto-reset on un-limit moves into ScopesPicker too. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(frontend): nest read-only toggle inside the scope list card Place the read-only toggle at the top of the scope list (between the Selected Scopes summary and the bordered domain list) via a new optional topSlot snippet on ScopeSelector. Keeps ScopeSelector decoupled from read-only specifics; ScopesPicker fills the slot. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 9bc8160be50b3e57a60daf4e1b71c389a6e02b8a This commit updates the EE repository reference after PR #571 was merged in windmill-ee-private. Previous ee-repo-ref: f53d26e6685dfd60bfa67686fbd7358169cfd130 New ee-repo-ref: 9bc8160be50b3e57a60daf4e1b71c389a6e02b8a Automated by sync-ee-ref workflow. * fix: address CI review for read-only token flag - P1 (Codex): narrow the MCP middleware exemption from "any /api/mcp/*" to just the streamable HTTP transport endpoints (/api/mcp/gateway, /api/mcp/w/{ws}/{mcp,sse,list_tools}). Without this, a read-only token could POST /api/mcp/gateway/oauth/server/approve and mint a follow-on non-read-only MCP token via the OAuth code/token exchange. - P2 (Claude/cubic): fix test comment/assertion mismatch — the run-path assertion now exercises GET (which is what the RUN_PATH_ACTIONS elevation comment describes) in addition to POST. Add a regression assertion for /api/mcp/gateway/oauth/server/approve. - P2 (cubic): short-circuit script/flow/hub-script/resource fetches in MCP list_tools when read_only is on — they would only be discarded below, so skipping the DB and resource fan-out is pure win. - P2 (cubic): when scopes are pre-supplied via the CreateToken prop, the ScopesPicker isn't rendered, which previously hid the read-only toggle entirely. Render it next to the pre-supplied scopes display. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
e74f06cb56 |
fix: handle singlestepflow zombies and stop filtering them from runs page (#9055)
* fix: handle singlestepflow zombies and stop filtering them from runs page * fix: support singlestepflow in batch_rerun_jobs Previous PR added singlestepflow to list_selected_job_groups so the BatchReRun pane shows them, but batch_rerun_jobs_inner still joined on kind = 'script' / 'flow' with j.runnable_id (which is NULL for SingleStepFlow), so the rows were silently filtered out — user sees the option, click Re-run, gets zero successes. Mirror the norm_kind CTE projection from list_selected_job_groups inside batch_rerun_jobs_inner: pull the wrapped runnable type and pinned script hash from raw_flow.modules[id='a'], cast back to JOB_KIND so the existing handler dispatch works unchanged. Path-based schema fallback so input_transforms still resolve at rerun time. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: project singlestepflow in batch-rerun schema lookups Codex review pointed out two follow-on regressions from the previous fix: (1) list_selected_job_groups returned schemas with script_hash=null and schema=null for singlestepflow rows because the inner schemas subquery still joined runnable metadata via j.runnable_id (NULL for SingleStepFlow). The BatchReRun pane consumes every selected.schemas entry through mergeSchemasForBatchReruns / buildExtraLibForBatchReruns, both of which assume real schema objects. (2) When use_latest_version=true, batch_rerun_handle_job re-fetched latest_schema from v2_job filtering jb.kind='script' or 'flow' — neither matched singlestepflow, so schema came back NULL and every input_transforms entry silently no-op'd. Both queries now project singlestepflow rows via raw_flow.modules[id='a'] — norm_kind for dispatch and effective_hash for the schemas join, plus a path-based latest-schema fallback so flow-wrapped SSF (no version pinning) and any SSF whose pinned hash has been deleted still resolve. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test: add batch_rerun integration tests, fix SSF hash hex parsing Adds 11 integration tests against /jobs/run/batch_rerun_jobs and /jobs/list_selected_job_groups (both endpoints had zero CI coverage). Tests cover the full 4-kind × 3-mode matrix: regular Script and Flow (baseline regression for the SQL refactor), script-wrapped and flow- wrapped SingleStepFlow (regression for the bugs this PR fixes), and a mixed-kind batch. Writing the tests caught a real bug in the previous commit: ScriptHash serializes as a 16-char hex string in raw_flow.modules[a].value.hash (per the custom Serialize impl in windmill-types/scripts.rs), not as an integer. The earlier `(m->'value'->>'hash')::bigint` cast worked on the hand-inserted SQL fixture I'd used for live testing (which embedded the hash as a raw integer) but failed in production where all SSF jobs are pushed via JobPayload::SingleStepFlow's serialized form. Replaced with `('x' || lpad(hex, 16, '0'))::bit(64)::bigint` — preserves the twos-complement bit pattern so both positive and negative i64 hashes round-trip correctly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Update SQLx metadata --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
1174d7d77f |
refactor: replace SELECT * with explicit column lists (#9010)
* refactor: replace SELECT * with explicit column lists Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: update sqlx offline query cache * chore: update sqlx offline query cache * chore: update sqlx offline query cache with EE support * chore: update sqlx offline query cache, no deletions * chore: update sqlx offline query cache after rebase * fix: correct column names in explicit script query lists - concurrency_limit → concurrent_limit (matches DB column name) - runnable_settings → runnable_settings_handle (matches DB column name) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add missing delete_after_secs column to script queries Also add integration test covering all explicit-column export queries. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add workspace export integration test covering all explicit-column queries Covers tarball_workspace (folder, script, resource, resource_type, variable, schedule, usr, group_) and the mcp_oauth_client SELECT query from windmill-mcp. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add tarball export integration test covering all explicit-column queries Single test creates one of each entity type and exercises every runtime-checked explicit-column query in tarball_workspace. Uses archive_type=tar to avoid zip feature-gate in CI. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: fix stale verification step and CI contradiction in update-sqlx skill - Regenerate current_files.txt after EE cache restoration so step 4 reports accurate diff - Scope "Never use SQLX_OFFLINE=true" to local prepare (CI legitimately uses it) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: remove Co-Authored-By from commit skill template * refactor: extract SCRIPT_COLUMNS const to single source of truth Replaces 5 duplicated 44-column lists with a shared const in windmill-types. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
392888d113 |
docs: add SAFETY comments to all dynamic SQL call sites (#9009)
* docs: add SAFETY comments to all dynamic SQL call sites Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: address review feedback on SAFETY comments - Fix missed comment for obo_triggers loop in offboarding.rs - Fix variable name in comment (table -> table_name) in offboarding.rs - Fix api-settings comment to reference inline VALID_NAME regex, not validate_dbname() - Add SAFETY comments to batch_execute calls in api-settings - Fix db.rs comment: PG_SCHEMA is env var, not compile-time constant - Add doc comments on RunnableSettingsTraitInternal constants * docs: remove misleading SAFETY comment on static SQL --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
e9e72fbbf8 |
feat: edit scopes on existing API tokens (#8967)
* feat: edit scopes on existing API tokens Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address PR review feedback on token scope edit - add SECURITY DEFINER to notify_token_scopes_change so trigger fires under windmill_user/admin roles (cubic P1) - drop banned $bindable(default) on optional props (CLAUDE.md): make ScopesPicker.value and EditTokenScopesModal.open required - detect MCP only when *every* scope starts with mcp: so mixed/null-scope tokens fall back to standard picker without dropping non-mcp scopes - audit log scope payload via serde_json instead of Rust {:?} Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d6c642b170 |
feat: add Azure Event Grid triggers (#8888)
* feat: add Azure Event Grid triggers (EE)
Introduces a new enterprise trigger kind `azure` that supports three
modes via a single unified trigger type:
- basic_push: Azure Event Grid basic — custom topics, system topics
(Storage, Resource Manager, Key Vault, etc.), domains (push only)
- namespace_push: Event Grid Namespace topics (CloudEvents over HTTP push)
- namespace_pull: Event Grid Namespace topics (HTTP pull with lock-token
ack/reject for dead-lettering)
Auth uses a Service Principal resource (tenant_id, client_id,
client_secret, subscription_id). Subscriptions are created in
CloudEvents 1.0 schema so the push webhook handler and the pull listener
share one payload parser.
Backend
- New crate `windmill-trigger-azure` (OSS stubs + EE impl symlinked from
windmill-ee-private)
- Migration `azure_trigger` table with CHECK constraints enforcing
mode/columns coherence
- `TriggerKind::Azure`, `JobTriggerKind::Azure`,
`DeployedObject::AzureTrigger` variants
- Push route `/api/azure/w/{workspace}/*path` handles classic
Event Grid SubscriptionValidation handshake and CloudEvents 1.0
abuse-protection OPTIONS handshake
- Optional inbound JWT validation (audience check only for v1)
- Feature flag `azure_trigger` propagated through windmill-api,
windmill-store (resource helper), and added to ee_core
Frontend
- `triggers/azure/` editor with mode toggle (basic/namespace-push/
namespace-pull) and per-mode config (topic ARM id / namespace +
topic name / subscription / filters / push auth / pull options)
- Registered in icon map, display names, save functions, badge,
wrapper, editor, add-trigger menu
OpenAPI
- `AzureTrigger`, `AzureTriggerData`, `AzureMode`,
`AzureSubscriptionMode`, `AzureDeliveryConfig`, `TestAzureConnection`
schemas; `/azure_triggers/*` endpoints; client regenerated
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to eaa7c3a9cb37a9ccc93f10a2535d929365acd2d8
This commit updates the EE repository reference after PR #541 was merged in windmill-ee-private.
Previous ee-repo-ref: 9689014e8c12c36c1059fd8fa5758d550b8b8bc9
New ee-repo-ref: eaa7c3a9cb37a9ccc93f10a2535d929365acd2d8
Automated by sync-ee-ref workflow.
* feat(azure-trigger): secret-auth push, ARM discovery, capture isolation, CLI + parity
Frontend:
- Split mode selector into Namespace/Basic + Pull/Push
- ARM resource dropdowns (namespaces, Basic topics, namespace topics)
populated from the service principal; cascade with stale-selection
reset on SP / edition change
- Remove stale authenticate toggle + audience input (server-managed
push_auth_config has replaced them)
- Azure listing page: "Create from template" button; "Also delete Azure
subscription" toggle in the delete modal; simplified trigger label
falling back to path
- AzureCapture.svelte: "Test subscription name" with -wm-capture suffix
- CompareWorkspaces.svelte: wire Azure for fork/compare
- Drop Trigger-deployed/event-loss warning (capture subscription is
isolated with -wm-capture)
Backend:
- Shared-secret push auth (see EE crate for detail)
- JSONB push_auth_config column (renamed from delivery_config), #[serde(skip)]
so clients/CLI/exports never see it
- Drop redundant enabled column; mode supersedes
- Azure capture infra: AzureTriggerConfig + set_azure_trigger_config +
azure_payload route + TriggerKind::Azure arm; PT15M queue TTL on
capture subscriptions so they bound storage after tab close
- Granular ACLs, users offboarding, trash, git-sync deployed-object:
all include azure_trigger
CLI:
- Add azure to TRIGGER_TYPES, pushObj dispatch, getTypeStrFromPath,
trigger commands (get/update/create/list/template), sync delete
switch + regex; e2e test for `trigger new --kind azure`
- system_prompts: SCHEMA_MAPPINGS + schema_names include AzureTrigger;
auto-generated/* regenerated
Skill:
- .claude/skills/adding-a-trigger/ checklist covering every file that
needs editing when wiring a new trigger type (learned from this PR)
ee-repo-ref bumped to b0e490cbf3724b7b64c6a5b010e3bdf24acd873c.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(azure-trigger): ci — ShareModal Kind + regenerated system_prompts
- frontend/src/lib/components/ShareModal.svelte: add 'azure_trigger'
to the Kind type so the listing page's "Permissions" action compiles
(ts2345 — caught by npm_check on CI, missed by fast-check locally).
- system_prompts/auto-generated/: regenerate to drop the stale
delivery_config / AzureDeliveryConfig fields from the Azure schema
(check-freshness on CI).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(azure-trigger): use workspace constant_time_eq crate
Drop hand-rolled constant-time compare in favour of the workspace
constant_time_eq crate (same one used by http_trigger_auth).
ee-repo-ref bumped to 9659382d47286e7f7f66d01b6f5dd8d4ed34848b.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(azure-trigger): pass placeholder + disabled via inputProps
`TextInput`'s `placeholder` and `disabled` go through its `inputProps`
prop — CI's `npm run check` caught the stale top-level passing that
`npm run check:fast` missed. Align with the DefaultEmailConfigSection
pattern.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(azure-trigger): correct LATEST_GIT_SYNC_SCRIPT_PATH version to 28213
The hub deploy of the azure-aware sync-script is version 28213, not
28214. Backend was pinning a non-existent hub script, which broke the
git_sync_e2e suite (every deploy's sync step 404'd).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(azure-trigger): add azure_triggers to token scope selector + skill
- windmill-api/src/token.rs: `build_trigger_scope_domains` was missing
`("azure_triggers", "Azure Event Grid")`, so the CreateToken UI's scope
selector didn't surface azure_triggers:read/write. Backend already had
`ScopeDomain::AzureTriggers` wired (scopes.rs), this just exposes it.
- .claude/skills/adding-a-trigger/SKILL.md: capture both scope-related
files under the hardcoded-arrays section so future triggers don't miss
the UI surface.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(adding-a-trigger-skill): clarify token.rs scope effect
Not a regression — nothing was working before. Skipping TRIGGER_DOMAINS
just means the scope works via API/CLI but has no UI checkbox.
* docs(adding-a-trigger-skill): trim token.rs bullet
* fix(azure-trigger): regen openapi-deref + swap textarea for TextInput
- Run build_openapi.sh to regenerate openapi-deref.{yaml,json} with the
12 azure_triggers paths + schemas. These files are served by the
runtime (include_str! in windmill-api/src/lib.rs) to external SDK
consumers; without this regen the new endpoints wouldn't be advertised.
- Replace the raw <textarea> for event type filters with the
design-system TextInput in textarea mode (frontend/CLAUDE.md bans raw
HTML elements).
Addresses cubic + claude PR review items.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
|
||
|
|
0cfa131254 |
feat: add disable_password_login global setting (#8873)
Adds an instance-level toggle that hides the email/password form on the login page and rejects password login, password reset request, and password reset endpoints server-side. Useful for OAuth/SAML-only deployments. - New `disable_password_login` global setting + lazy_static AtomicBool - `load_disable_password_login` loader wired into monitor initial_load and notify_global_setting_change listener - Unauthenticated `GET /auth/is_password_login_disabled` endpoint so the login page can hide the password form when enabled - Toggle in Instance Settings → Auth/OAuth/SAML - Login.svelte hides the password form and the "Log in without third-party" toggle when the setting is on Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
5b3913052e |
refactor: convert read-hot globals to AtomicBool/I64 and ArcSwap (#8815)
* refactor: extract load helpers from reload_setting family Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: convert atomic primitive globals to AtomicBool/AtomicI64 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: convert CRITICAL_*/HUB_API_SECRET/INSTANCE_EVENTS_WEBHOOK/JWT_SECRET to ArcSwap Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: pin ee-repo-ref to arcswap-refactor EE branch commit * refactor: convert BASE_URL/HUB_BASE_URL/MIN_VERSION/LICENSE_KEY*/LICENSE_KEY_ID to ArcSwap Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: convert worker hot-path globals to ArcSwap (WORKER_CONFIG et al) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: pin ee-repo-ref to combined arcswap-urls+worker EE commit * chore: update ee-repo-ref to d8be8f88cb8898c8f6b27421989d53528223815d This commit updates the EE repository reference after PR #532 was merged in windmill-ee-private. Previous ee-repo-ref: c375aaaac9ec0fc0480993627d0defc8054c31a4 New ee-repo-ref: d8be8f88cb8898c8f6b27421989d53528223815d Automated by sync-ee-ref workflow. * fix: cleanup unused imports + fix 2 missed WORKER_CONFIG readers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to ce0f8fbbbde09c4a858312d2d8716d224e99042c This commit updates the EE repository reference after PR #534 was merged in windmill-ee-private. Previous ee-repo-ref: 450b601b5aba0ca0b2045f4b5071aa8701b4bfb7 New ee-repo-ref: ce0f8fbbbde09c4a858312d2d8716d224e99042c Automated by sync-ee-ref workflow. * fix: secret_backend_integration test — BASE_URL.write().await → .store() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: convert APP_WORKSPACED_ROUTE to AtomicBool for symmetry with HTTP_ROUTE_WORKSPACED_ROUTE Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to e587df8 (post-#535 merge) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
435b25e6a4 |
feat: add user offboarding flow with object reassignment (#8647)
* feat: add user offboarding flow with object reassignment Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: require new_operator for permissioned_as when reassigning to folder Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update on_behalf_of_email on scripts/flows during offboarding Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: extract offboarding to separate module and add integration tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: delete tokens, add operator preview counts, remove token reassignment UI Tokens are now always deleted during offboarding. Preview now shows scripts/flows/apps with on_behalf_of and schedules/triggers with permissioned_as referencing the departing user (even outside their path). Token reassignment UI removed since webhooks break on path changes anyway. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: rich preview with path lists, warnings, and downloadable report Preview now returns full path lists (not just counts) for owned objects and objects executing on behalf of the user. Adds warnings for: - HTTP triggers (webhook URLs will change) - Email triggers (addresses will change) - Broken $var:/$res: references in resources/variables Frontend provides "Export list" button to download affected content. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add coverage for dynamic queries (triggers, extra_perms, operator schedules) Adds HTTP trigger, extra_perms reference, and shared schedule to test fixture. Tests verify that non-macro sqlx queries (trigger reassignment, extra_perms cleanup, operator schedule update) work correctly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove broken_references, add full dynamic query test coverage Remove broken_references field from preview (user's resources/variables are already in the owned paths list). Add shared HTTP trigger fixture to test all dynamic query paths: trigger operator preview (line 232), trigger permissioned_as update for non-user-path (line 951), and extra_perms cleanup on trigger tables (line 983). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add referencing field to preview for content/value path references Preview now includes a 'referencing' section listing scripts (by content), flows (by value JSON), apps (by policy/extra_perms), and resources (by value) that contain references to u/{username}/ paths. These references may break after reassignment. Shown in export list and as a warning in the UI. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: rename objects to items in UI, detect on_behalf_of items in hasItems Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: replace remaining objects with items in UI text Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: rename operator to on_behalf_of, separate owned vs on-behalf UI sections - Rename new_operator to new_on_behalf_of_user in API and frontend - Rename op_ prefixed variables to obo_ in backend - UI now shows separate sections for owned items and items running on behalf, with the operator selector shown only when needed - canSubmit logic updated: operator needed for folder targets OR when on-behalf items exist Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: CSV export, side-by-side layout, always accept new_on_behalf_of_user - Export affected items as CSV instead of text - Owned items and on-behalf items shown side by side in summary boxes - new_on_behalf_of_user always accepted (defaults to target user for user targets, required for folder targets) - On_behalf_of selector always visible, auto-defaults when user target is selected Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: proper pluralization and bottom-aligned counts in summary boxes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: stack info boxes vertically, referencing box as warning style at top Info boxes (owned, on-behalf, referencing) now one per row instead of side-by-side. Referencing box uses warning colors. Webhook/email trigger alerts shown below boxes. Proper pluralization in global modal too. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: CSV exports only referencing items, export button inside warning box Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: use ToggleButtonGroup for user/folder, add reassign toggle on remove - User/Folder selection now uses ToggleButtonGroup component - When removing a user, a "Reassign items before removing" toggle lets the admin skip reassignment and just delete directly - In reassign-only mode, the toggle is not shown (always reassigns) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: show token details with labels and scopes in preview Preview now returns token label, scopes, and expiration instead of just a count. Frontend shows a dedicated token box listing each token with its scopes. Test updated to verify token label in preview response. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: extract shared offboarding components, per-type trigger links, hash deep linking - Extract OffboardItemsBox, OffboardReassignControls, OffboardWorkspaceSection, and offboarding-utils.ts as shared components used by both workspace and global modals - Change triggers in OffboardAffectedPaths from Vec<String> to HashMap<String, Vec<String>> so frontend knows which trigger page to link to - Add hash-based deep linking to all 9 trigger pages and schedules page - Preserve URL hash in updateQueryFilters across all trigger pages - Only open editor drawer if the item is found in the list - Reassign toggle at top with warning alert when disabled (both modals) - Referencing items box uses yellow warning variant with expandable path links - Cleaner labels: "Move u/{username}/* items to", "Update triggers/runnables permissions to" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: rename on_behalf_of section label to match flow advanced settings Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: regenerate sqlx query cache Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR review issues for offboarding - Add 9 trigger tables to check_path_conflicts for user-friendly conflict messages - Fix submit button no-op when user has only on-behalf items (show target selector, fix canSubmit) - Only delete workspace user when reassignment entry exists (prevent orphaned objects) - Add $azure_kv: prefix to vault secret query (match rename_user pattern) - Use Svelte 5 onSelected callback instead of deprecated on:selected - Make ScriptBuilder section label conditional on canPreserve - Fix CSV export to include trigger paths via flattenPaths utility - Fix test_offboard_reassign_only to remove conflicts and assert on response - Parallelize workspace config fetches in global modal with Promise.all - Delete tokens when deleting workspace user - Return structured JSON from global offboard endpoint Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * sqlx * fix: address second round of PR review issues - Accumulate per-workspace OffboardSummary in global offboard instead of returning zeros - Delete workspace user unconditionally when delete_user=true (prevent orphaned usr rows) - Filter archived/deleted scripts in check_path_conflicts to match preview - Reset form state when workspace offboard modal reopens - Move hashHandled=true inside trigger-found guard on all 10 deep-link pages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: improve offboarding integration tests - Add second workspace to fixture for multi-workspace global offboard testing - Add test_global_offboard_execution: verifies items reassigned across 2 workspaces, user deleted from both, and password row deleted from instance - Add test_offboard_invalid_target: verifies 400 for nonexistent user, nonexistent folder, and invalid target format - Fix test_offboard_to_user: use single DELETE, add explicit new_on_behalf_of_user - Fix test_global_offboard_preview: assert 2 workspaces instead of 1 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address third round of PR review issues - Fix ScriptBuilder tooltip to match conditional section label wording - Clear stale conflicts in global modal on reopen - Fix test_offboard_to_folder to assert on specific moved path, not pre-existing data - Allow deleting user with zero items (show Offboard button, skip reassignment) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add global token deletion warning in instance-level offboard modal Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * update sqlx * fix: add raw_app path and dependency_map path reassignment to offboarding Audit found these tables with user-scoped paths were not being updated: - raw_app: mirrors app paths, needs path reassignment - dependency_map: importer_path and imported_path reference user paths Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: move user cleanup to delete_workspace_user_internal, fix review issues - Move extra_perms, folder owners, drafts, favorites, inputs, captures cleanup into delete_workspace_user_internal so any user deletion gets proper cleanup (not just offboard path) - Fix flow INSERT missing labels and lock_error_logs columns (data loss) - Fix validate_target returning 404 instead of 400 for nonexistent targets - Fix canSubmit blocking delete when user has no items to reassign - Fix token preview query filtering out tokens without scopes - Fix token warning messages: workspace-level mentions webhooks/HTTP triggers, instance-level mentions API calls using credentials - Fix "Schedules and triggers" -> "Triggers and runnables" wording - Show token section at instance level only when tokens exist - Show Offboard button at instance level when user has no items but deleteUser=true Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
c86846ac19 |
rate limit token creation on CLOUD_HOSTED (10/min per user) (#8664)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
754b88a52c |
fix: harden login rate limiting with CLOUD_HOSTED gating and memory eviction (#8602)
* fix: harden login rate limiting with CLOUD_HOSTED gating, memory eviction, and race fix Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: replace global DashMap with atomics and move extract_client_ip inside conditional Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
06bbe7b94b |
fix: add per-IP and per-account brute force protection on login endpoint (#8601)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
3959fe8297 |
feat: add workspace-level service accounts (#8560)
* feat: add workspace-level service accounts (EE) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * sqlx * sqlx * chore: update ee-repo-ref Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
0389d9601c |
chore: upgrade axum 0.7 to 0.8 (#8539)
* chore: upgrade axum 0.7 to 0.8 and related dependencies Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add route reachability tests for ~80 previously untested endpoints Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: switch feature-gated trigger handlers from axum::async_trait to async_trait crate Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update new trash routes to axum 0.8 path syntax Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to latest EE commit Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: upgrade route tests to assert 2xx responses with proper data setup Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: restore npm_proxy and ai_routes tests using local echo servers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: gate workspace fork test behind enterprise feature flag Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add ~40 more endpoint tests (jobs authed, health, favorites, ACLs, reachability) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address review findings from axum 0.8 upgrade - Use cookie value_trimmed() instead of value() for cookie 0.18 compat - Update comments still referencing old :workspace_id syntax Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 61ae055ea31481f1899953e9d5f65566b8c707b1 This commit updates the EE repository reference after PR #486 was merged in windmill-ee-private. Previous ee-repo-ref: 0059d175a6fdddf52998b183bf91059b224704ac New ee-repo-ref: 61ae055ea31481f1899953e9d5f65566b8c707b1 Automated by sync-ee-ref workflow. * test: add test for new get_imports endpoint Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove unused import in raw_apps test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
0bd756839c |
feat: SCIM user deprovisioning (active:false) + instance-level user disable (#8484)
* [ee] feat: handle active:false in SCIM user PATCH/PUT for deprovisioning Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref for SCIM active:false deprovision fix Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * nit sqlx * [ee] feat: add password.disabled column for SCIM user deactivation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [ee] feat: enforce password.disabled in auth checks Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [ee] refactor: use scim_deactivated_user table instead of password.disabled Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [ee] fix: apply SCIM filters to deactivated users, add name column Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: add down migration for scim_deactivated_user Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: rename migration to avoid timestamp conflict, update sqlx cache Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [ee] refactor: use password.disabled for SCIM deactivation, block login for disabled users Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [ee] feat: show disabled toggle in superadmin user list, add disabled field to API Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add confirmation modal when disabling instance user Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: improve disable user confirmation text Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: revert toggle state when disable confirmation is cancelled Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: properly revert toggle on disable cancel using reset key Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: move disable/enable to dropdown menu, add disabled badge on email Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: rename 'Show active users only' to 'Recently active only' to avoid confusion with disabled state Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: remove accidentally committed gen files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use .catch() for enable user error handling in dropdown action Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: delete tokens on user removal, improve confirmation modal texts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update sqlx cache for non-enterprise code paths Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: restore sqlx cache files deleted by incorrect prepare run Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add missing sqlx cache for non-enterprise git sync query Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to a1274aa11a83f608eacc32c0d449ca3527d98c15 This commit updates the EE repository reference after PR #473 was merged in windmill-ee-private. Previous ee-repo-ref: 30f8c53b101b9e25107e793cdc038b0e07061739 New ee-repo-ref: a1274aa11a83f608eacc32c0d449ca3527d98c15 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
4c8edd5e94 |
fix: restrict logout redirect to whitelisted domains (#8524)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
f2f178eb31 | chore: remove dead users_oss module (#8458) | ||
|
|
18b3528ba4 |
feat: instance groups instance-level role support (#8404)
* [ee] feat: instance groups instance-level role support Add ability to assign instance-level roles (superadmin/devops) to instance groups. Group members automatically receive the role with proper precedence: manual elevated roles always win, superadmin > devops. - Migration: add instance_role to instance_group, role_source to password - Role propagation on all mutation paths (add/remove/update/delete/import) - SCIM sync integration (companion PR: windmill-ee-private#463) - Frontend: role toggle in group editor, role column in tables, role source indicator in superadmin settings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: update ee-repo-ref to 278a3887f759f9d1146554baa0765518d5bc70f2 This commit updates the EE repository reference after PR #463 was merged in windmill-ee-private. Previous ee-repo-ref: b407fe4604153d09ff223e11d43c2df83a1de5d0 New ee-repo-ref: 278a3887f759f9d1146554baa0765518d5bc70f2 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 4.6 <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> |
||
|
|
f2be625348 |
feat: store hashed tokens instead of plaintext (#8217)
* feat: store hashed tokens in the token table instead of plaintext
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address review issues in token hash migration
- Update all base.sql fixtures to include token_hash/token_prefix columns
- Keep plaintext token for webhook tokens (needed for URL reconstruction)
- Restore get_token_by_prefix to query DB for webhook tokens
- Fix down migration to delete NULL-token rows before restoring NOT NULL
- Update parser fixture standalone schema
- Update EE dedicated_worker_ee.rs to use token_hash/token_prefix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: restore sqlx offline cache (only add new query files)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: keep writing plaintext token column for backward compat
Write to token column alongside token_hash until MIN_VERSION_SUPPORTS_TOKEN_HASH
(1.649.0) is reached. This ensures older workers can still authenticate
during rolling upgrades. Remove the separate UPDATE in new_webhook_token
since create_token_internal now writes plaintext directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: branch on MIN_VERSION to write plaintext token or null
Check MIN_VERSION_SUPPORTS_TOKEN_HASH at runtime: write plaintext to
token column while old workers exist, switch to NULL once all workers
are >= 1.649.0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: set MIN_VERSION_SUPPORTS_TOKEN_HASH to 1.650.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use token_hash for email lookup and expiry notifications
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: rotate webhook tokens instead of recovering plaintext from DB
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: use token_hash for native trigger token lookups and deletes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* sqlx
* refactor: drop webhook_token_prefix from native_trigger table
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: backward compat for token rotation and make webhook_token_hash NOT NULL
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: prevent panic on short superadmin secret token prefix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: prevent panic on short superadmin secret token prefix
Replace all `token[0..TOKEN_PREFIX_LEN]` slicing with
`token.get(..TOKEN_PREFIX_LEN).unwrap_or(token)` to prevent
panics when a token shorter than 10 chars is provided (e.g.
malformed Authorization header, short superadmin secret).
Co-authored-by: hugocasa <hugocasa@users.noreply.github.com>
* fix: prevent panic on short token prefix slicing
Replace all `token[0..TOKEN_PREFIX_LEN]` with safe
`token.get(..TOKEN_PREFIX_LEN).unwrap_or(token)` to prevent panics
on malformed tokens shorter than 10 characters.
Co-authored-by: hugocasa <hugocasa@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Revert "fix: prevent panic on short superadmin secret token prefix"
This reverts commit
|
||
|
|
2aef01d18c |
feat: partition audit log table by day with configurable retention (#8292)
* feat: partition audit log table by day with configurable retention Introduce daily range partitioning for audit logs to replace expensive DELETE-based retention with instant DROP TABLE per partition. - Create `audit_partitioned` table alongside existing `audit` table - New inserts go to `audit_partitioned`, reads UNION ALL both tables - Monitor creates future partitions and drops expired ones - Add `audit_log_retention_days` instance setting (default 365 days) - Old `audit` table empties naturally via existing DELETE cleanup Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add audit log retention setting to Core instance settings UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: bump audit partitioning migration timestamp to avoid collision Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: update ee-repo-ref.txt for audit partitioning Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add RLS/grants to audit_partitioned, run partition mgmt hourly, CE default 14d - Add grants for windmill_user/windmill_admin and all 5 RLS policies - Move manage_audit_partitions to hourly via should_run(120) - Default retention: 14 days CE, 365 days EE - Download JSON button is now icon-only Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address code review — quote SQL identifiers, add workspace index, deduplicate retention logic - Quote partition names in dynamic SQL for defense in depth - Add idx_audit_partitioned_workspace(workspace_id, timestamp DESC) index - Extract audit_log_retention_days() helper to deduplicate retention logic Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: update ee-repo-ref for audit insert error handling Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: update ee-repo-ref to cef4dfc45e6d6344c5d8d107bd2b4d1bf9bbdd64 This commit updates the EE repository reference after PR #450 was merged in windmill-ee-private. Previous ee-repo-ref: f09284bb257d461bcbe3c50fe31eb6f1e7eafee5 New ee-repo-ref: cef4dfc45e6d6344c5d8d107bd2b4d1bf9bbdd64 Automated by sync-ee-ref workflow. * fix: create audit partitions on startup in initial_load Ensures partitions exist before any requests arrive, closing the gap between server start and the first hourly monitor run. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
e56ccd200b |
feat: token expiration notifications (#8190)
* feat: add token expiration notifications via email, critical alerts, and webhooks - Monitor loop checks for tokens expiring within 7 days and sends email notifications to token owners. Tracks notification state via new `expiry_notified` column on the token table to avoid duplicates. - When tokens expire and are deleted, owners are also notified. - Critical alerts (in-app UI) are gated behind a new instance setting `critical_alerts_on_token_expiry` (off by default); emails are always sent regardless of the setting. - Add TokenExpiringSoon and TokenExpired webhook message variants for workspace webhook integrations. - Frontend: show expiration badges and a warning banner on the tokens table for tokens expiring within 30 days. - Exclude session and ephemeral tokens from all notifications. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: use separate token_expiry_notification table for dedup - Replace `expiry_notified` column on token table with a dedicated `token_expiry_notification` table (token, expiration) - Insert notification row on token creation via shared `register_token_expiry_notification()` helper - Delete notification row atomically when sending the notification - Clean up orphaned rows in `delete_expired_items()` - No FK constraint to avoid cascade overhead on token deletions - Add index on expiration column for efficient range queries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: calendar-based expiration badge and move notification cleanup - Fix daysUntilExpiration to compare calendar dates instead of time diff - Move notification row cleanup from delete_expired_items to check_expiring_tokens to keep it off the hot path - Use simple expiration <= now() index scan instead of NOT EXISTS join Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
82e5f6de48 |
feat: add Kubernetes operator and instance settings YAML editor (#7836)
* Add windmill-operator crate for Kubernetes CRD-based instance config Introduces a new `windmill-operator` crate that enables declarative management of Windmill instance configuration via a Kubernetes `WindmillInstance` CRD. The operator watches CRD resources and performs full declarative sync of global_settings and worker configs to the database, supporting GitOps workflows for instance-level configuration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add tests for windmill-operator CRD and db_sync - 9 unit tests for CRD serialization, deserialization, metadata, and status field behavior - 15 integration tests for db_sync using #[sqlx::test] with full declarative sync coverage: upsert, delete, protected keys, idempotency, worker config prefix handling, and end-to-end sync Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Replace untyped BTreeMap CRD fields with typed structs for schema validation GlobalSettings, SmtpSettings, IndexerSettings, and WorkerGroupConfig now have explicit typed fields with serde(flatten) catch-all for forward compatibility. The generated CRD YAML includes a full OpenAPI v3 schema that Kubernetes validates on kubectl apply. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Type opaque serde_json::Value CRD fields with real structs Replace most remaining serde_json::Value fields in WindmillInstance CRD with properly typed structs derived from the codebase: - oauths: BTreeMap<String, OAuthClient> - otel: OtelSettings - otel_tracing_proxy: OtelTracingProxySettings with ScriptLang enum - critical_error_channels: Vec<CriticalErrorChannel> (untagged enum) - critical_alerts_on_db_oversize: DbOversizeAlert - ducklake_settings: DucklakeSettings with nested catalog/storage types - custom_instance_pg_databases: CustomInstancePgDatabases - autoscaling (worker config): AutoscalingConfig with integration struct - custom_tags, default_tags_workspaces: Vec<String> - default_tags_per_workspace: bool Still opaque (serde_json::Value): object_store_cache_config (kube-core can't generate schemas for internally-tagged enums), secret_backend (EE-private), slack, teams (no clear struct definitions). Regenerated CRD YAML with full OpenAPI schema (352→703 lines). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Unify instance config types and add bulk GET/PUT API Move all typed settings (GlobalSettings, WorkerGroupConfig, etc.) from windmill-operator/crd.rs into windmill-common/instance_config.rs so both the API server and operator share a single source of truth. Add diff/apply logic (Merge mode for UI, Replace mode for operator) and InstanceConfig::from_db(). Add GET/PUT /settings/instance_config endpoints so the frontend loads all settings in 1 call instead of 42, and saves with a single bulk PUT. The backend handles the diff internally, running pre-write hooks for changed keys. Refactor windmill-operator/db_sync.rs to use the shared diff+apply functions and slim crd.rs down to the CRD wrapper with re-exports. Includes 32 unit tests and 30 integration tests covering serialization, diff logic, DB roundtrips, protected settings, and edge cases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Form/YAML toggle to instance settings UI Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: show Form/YAML toggle regardless of hideTabs prop Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: replace toggle button group with simple YAML toggle Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: mask sensitive fields in YAML view with show/hide toggle Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: hide internal settings and mask sensitive fields in YAML view Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: hide jwt_secret and min_keep_alive_version from API and config exports Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * all * feat: add secretKeyRef support for sensitive fields in operator CRD Allow sensitive fields (license_key, hub_api_secret, scim_token, smtp_password, OAuthClient.secret, custom PG user_pwd) to reference Kubernetes Secrets via the standard secretKeyRef pattern instead of inlining values as plaintext YAML. The reconciler resolves all refs by reading K8s Secrets before syncing to the database. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * all * all * all * fix: merge main and update dev environment docs Resolve merge conflicts from origin/main, fix duplicate UV_INDEX_STRATEGY_SETTING import, and add Playwright MCP testing instructions to CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * all * fix: init tracing for CLI subcommands and deduplicate setting side-effects Initialize tracing subscriber before early-return CLI paths (sync-config, operator) so tracing calls are not silently dropped. Refactor set_global_setting_internal to call run_setting_pre_write_hook instead of duplicating the side-effect logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add `wmill instance get-config` CLI command Dumps the current instance config (global settings + worker configs) as YAML. Supports --output-file to write to a file instead of stdout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * all --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
c580572252 |
refactor: extract windmill-api-scripts and windmill-api-users subcrates (#7850)
* refactor: extract windmill-api-scripts and windmill-api-users subcrates Split the monolithic windmill-api crate by extracting scripts.rs, flows.rs, users.rs, and users_oss.rs into dedicated subcrates. This reduces incremental rebuild times when editing these modules. Changes: - Create windmill-api-scripts crate (scripts.rs + flows.rs, ~4.3K lines) - Create windmill-api-users crate (users.rs + users_oss.rs, ~2.4K lines) - Move clear_schedule to windmill-queue (shared by scripts, flows, workspaces) - Move username utilities (VALID_USERNAME, INVALID_USERNAME_CHARS, generate_instance_wide_unique_username) to windmill-common/src/usernames.rs - Move COOKIE_DOMAIN, IS_SECURE, WithStarredInfoQuery, BulkDeleteRequest, WebhookShared to windmill-common for cross-crate access - Original files in windmill-api become thin stubs with pub use re-exports - EE-dependent route handlers remain in windmill-api (create_user, rename_user, set_password, reset_password, etc.) - Feature forwarding for enterprise, private, parquet, no_auth Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract windmill-api-workspaces subcrate (Step 3) Move workspaces.rs, workspaces_extra.rs, workspaces_oss.rs, and workspaces_ee.rs into a new windmill-api-workspaces crate (~7K lines). Routes that depend on windmill-api internals (AI copilot, teams, tarball export, critical alerts, stripe) remain in the windmill-api stub. The subcrate handles all other workspace management routes. Also moved send_email_if_possible to windmill-common/email_oss.rs to make it available across subcrates without circular deps. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * all * refactor: extract windmill-api-groups subcrate (groups.rs + folders.rs) Extract groups.rs (1,093 lines) and folders.rs (833 lines) into a new windmill-api-groups subcrate. Both modules had clean dependencies on already-extracted crates (windmill-api-auth, windmill-common, windmill-api-workspaces). Also removes unused re-exports of get_instance_username_or_create_pending and INVALID_USERNAME_CHARS from windmill-api/src/utils.rs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: add granular_acls.rs and folder_history.rs to windmill-api-groups Extract granular_acls.rs (395 lines) and folder_history.rs (68 lines) into the windmill-api-groups subcrate. Both modules only depend on already-extracted crates and belong to the same access-control domain as groups and folders. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: remove unused imports and dead code from subcrate extraction - Remove unused BASE_URL import from lib.rs - Remove workspaces_extra.rs and workspaces_oss.rs re-export stubs (no consumers in windmill-api) - Remove dead send_email_if_possible OSS stub (callers moved to windmill-api-users) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * all * chore: bust CI cargo cache for subcrate split Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: re-export BASE_URL for EE files that use crate::BASE_URL Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: forward no_auth feature to windmill-api-users, remove dead code - Add "windmill-api-users/no_auth" to windmill-api's no_auth feature so the login bypass in users.rs:1600 activates correctly - Remove dead send_email_if_possible from windmill-api-users/users_oss.rs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: re-enable cargo cache for backend tests Cache was disabled to bust stale entries from before subcrate split. Now that a clean build has run, re-enable for faster CI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: install mold+clang in CI workflows The .cargo/config.toml uses mold linker for x86_64-linux. Build scripts require linking even during cargo check. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: increase cargo test timeout to 30 min Exit code 143 (SIGTERM) means the 20-min timeout was hit during compilation without cache. Bump to 30 min as safety net. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: limit cargo build jobs to 4 to prevent OOM in CI Exit code 143 (SIGTERM) after 8 min = OOM kill during compilation. 8 parallel LLVM codegen jobs exhaust memory on ubicloud-standard-8. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |