Commit Graph
7 Commits
Author SHA1 Message Date
Ruben Fiszelandwindmill-internal-app[bot] dda59767c2 feat: stamp webhook trigger_kind on token-driven job runs (#10431)
* feat: stamp ui vs webhook trigger_kind on direct job runs

* fix: gate ui trigger kind on min worker version and dedupe display names

* docs: state that the ui trigger kind attributes rather than proves

* refactor: fold the trigger fallback into one trigger_or_fallback helper

* feat: hold trigger_kind as a tolerant label on the worker paths

* chore: refresh the sqlx offline cache for the trigger_kind label queries

* chore: update ee-repo-ref to 7de7daff5eed410e0c815ad6b292d2b4303f02f2

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

Previous ee-repo-ref: 974ab910d9a30c5565e1198ee312acc6d11239f3

New ee-repo-ref: 7de7daff5eed410e0c815ad6b292d2b4303f02f2

Automated by sync-ee-ref workflow.

* fix: keep the API job structs tolerant of unknown trigger kinds too

* chore: point ee-repo-ref at the merged EE main

---------

Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-07-31 14:46:08 +00:00
Ruben FiszelandClaude Opus 4.8 710a13a59d fix(apps): cover script/flow component outputs in deployed-app S3 provenance gate (#10070)
* fix(apps): cover script/flow component outputs in deployed-app S3 provenance gate

Deployed apps read S3 files on-behalf of the app author for logged-in viewers
(#10048). A confused-deputy guard confines those reads to files the app
"produced", but the recent-production check only matched inline `appscript`/
`preview` jobs nested under the app path. Files produced by the deployed
script/flow components an app is wired to run (e.g. a SQL query persisted to S3)
were therefore denied "File restricted" for every viewer, admins included.

Expand the provenance check to also match completed `script`/`flow`/`flowscript`/
`flownode` jobs whose `runnable_path` is one of the app's declared triggerables,
and accept the author identity via `permissioned_as = on_behalf_of` (not only
`created_by = caller`) so files produced on-behalf of the author are covered.
Reads outside the app's declared triggerables stay denied.

Adds a regression test seeding a script-kind produced file that reproduces the
"File restricted" denial before the fix and passes after.

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

* fix(apps): key S3 provenance on on-behalf identity + cover flow steps (review)

Addresses the CI review on the S3 provenance gate:

- P1 (confused deputy): the recent-production check keyed on `created_by =
  caller`, so a viewer who can run a declared script/flow directly (outside the
  app, with un-pinned inputs) could craft a result naming an author-only key and
  read it back through the app as the author. Key provenance instead on the
  producing job's `permissioned_as` matching the on-behalf identity the download
  reads as (the author in author-mode); a viewer's direct run has
  `permissioned_as = viewer` and no longer clears the gate. Drops `created_by`
  from both the appscript/preview and script/flow branches, closing the same
  latent hole in the pre-existing inline-script branch.

- P2 (dead flow-step branch): `flowscript`/`flownode` jobs have
  `runnable_path = <flow_path>/<step_id>`, which exact `= ANY(...)` never matched.
  Split script vs flow triggerable paths; flow kinds now match the flow's own job
  (bare path) and its step jobs via a `<flow_path>/%` prefix, bounded to declared
  flows.

- P2 (test realism): the regression test now uses the production
  component-prefixed triggerable key format (`<id>:script/...`), exercises a
  flow-step-produced key, and asserts a viewer's own direct run of a declared
  script stays denied (the P1 case).

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

* fix(apps): tie deployed-app S3 provenance to an app-origination marker (review)

Second CI-review round flagged that `permissioned_as` still does not prove a job
was app-launched: a runnable configured with its own `on_behalf_of` makes a direct
`/jobs/run` resolve `permissioned_as` to that identity (the app author), so a viewer
with run access could execute a declared runnable directly, craft an S3 result, and
read it back through the app. The flow-path `LIKE fp || '/%'` match also let `_`/`%`
in a declared path admit unrelated flows.

Introduce a real app-origination marker instead of inferring provenance:

- Add `JobTriggerKind::App`; `execute_component` stamps every app-launched job with
  `trigger_kind = 'app'` + `trigger = <app path>`. A direct `/jobs/run` cannot set
  this, so it is the authoritative signal that a file was produced *by the app*.
- The provenance gate's recent-production check collapses to
  `trigger_kind = 'app' AND trigger = <this app path>` (+ the 3h window and result
  containment). This drops the forgeable `created_by`/`permissioned_as`/
  `runnable_path`/kind logic entirely and removes the `LIKE` wildcard issue.
- Provenance is scoped to THIS app's path, so another app's jobs (even same author)
  do not authorize this app's reads.

Regression test rewritten to the marker model: an app-produced key clears for viewer
and admin; a direct run whose `permissioned_as` resolves to the author stays denied
(the forgery); another app's output stays denied. Adds `app` to the OpenAPI
JobTriggerKind enum.

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

* test(apps): assert execute_component stamps trigger_kind='app' at runtime

Adds an end-to-end test that runs a real script component through the app
runtime (`apps_u/execute_component`) and asserts the enqueued job carries the
app-origination marker `trigger_kind = 'app'` + `trigger = <app path>` (not the
runnable path). The provenance-gate tests seed the marker directly; this proves
the runtime actually produces the exact marker the gate depends on.

execute_component commits the job row and returns its id, so the assertion reads
the row directly — no worker needed to run the job.

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

* fix(triggers): reject trigger_kind=app for suspended-job reassignment (review)

`JobTriggerKind::App` (added for the app-origination S3 marker) became a valid
value for the resume/cancel suspended-trigger routes, whose handler derives the
table name `<kind>_trigger`. There is no `app_trigger` table, so both endpoints
would fail with a missing-relation database error (500). Reject `App` in
`get_suspended_trigger` alongside webhook/schedule so it returns a clean 400.

Adds a regression test asserting the reassignment route returns 400 (not 500) for
trigger_kind=app.

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

* fix(apps): don't stamp app-origination marker on preview runs (review)

The app-origination marker (trigger_kind='app') was stamped unconditionally,
including preview mode. A preview lets a `jobs:run` caller supply arbitrary
`raw_code` against ANY app path without that app's deployed policy (raw_code with
no path/id skips all app authorization), so a preview returning
`{"s3":"<author-only-key>"}` would forge the exact marker the S3 provenance gate
trusts and read the victim app author's file.

Gate the marker on `!is_preview`: only deployed, policy-checked executions are
app-provenanced. Preview/editor S3 display does not rely on this marker (the editor
routes reads through the force_viewer allowlist), so nothing legitimate regresses.

Adds a regression test asserting a preview run's job is not stamped trigger_kind='app'.

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

* fix(apps): editor-authorize preview marker + per-viewer S3 provenance isolation (review)

Closes the codex P1 (preview forgery) without breaking editor preview downloads,
and adds cross-viewer isolation to the provenance gate.

- Preview marker now requires app write: `execute_component` stamps the
  app-origination marker on a preview only when the caller can EDIT that app
  (`require_is_writer`), instead of never stamping previews. An app editor already
  wields the app's author identity (they can deploy a component that reads the same
  file), so marking their own preview is no escalation and keeps preview-produced
  S3 results downloadable in the editor; a `jobs:run`-only caller who cannot edit
  the app still cannot forge the marker. Deployed runs are unchanged (always
  marked).

- Per-viewer isolation: the provenance gate now also requires
  `j.created_by = <this caller>`. The security boundary stays the un-forgeable
  `trigger_kind='app'` marker; `created_by` is an additional filter ANDed under it,
  so it only narrows — a viewer can only download keys their OWN app runs produced,
  not another viewer's result. Restores the per-caller scoping #10048 had, now safe
  on top of the marker.

Tests: preview marked iff caller can edit the app; cross-viewer isolation (another
viewer's app-marked key denied, no admin bypass); direct-run and other-app keys
still denied; deployed run still stamped.

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

* fix(apps): require apps:write scope (not just writer ACL) to mark preview provenance (review)

require_is_writer checks the user's underlying ACL but ignores token scopes, so a
writer's token deliberately scoped to apps:run/apps:read/jobs:run but WITHOUT
apps:write could still mark a preview and forge provenance — even though that token
cannot deploy the app (update_app requires apps:write), breaking the "any marked
caller can deploy equivalent code" rationale.

Require BOTH apps:write:<path> scope (check_scopes) AND the writer ACL
(require_is_writer) before stamping a preview's app-origination marker. Deployed
runs unchanged.

Adds a scope-restricted-writer token to the test (apps:run/read + jobs:run, no
apps:write) and asserts its preview stays unmarked; retains the full-editor
positive case and the non-editor negative case.

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

* fix(apps): never app-provenance preview runs; read editor S3 as the caller (review)

Simplifies the preview handling: a preview executes as the *caller* (Viewer mode),
never as the author, so its results must be read back as the caller — never
author-mode — and must never carry the app-origination marker. This removes the
whole `require_is_writer` / `apps:write` / `can_preserve_on_behalf_of` reasoning
(which was also unsound: a writer's token or session may not be able to deploy a
component running as the app's on-behalf identity, so marking their preview could
still escalate).

- Backend: mark the app-origination marker for deployed runs only (`!is_preview`).
- Frontend: `getS3File` (AppImage/AppPdf/AppDownload) now routes editor/preview
  reads through the viewer-scoped `job_helpers/download_s3_file` endpoint (reads as
  the caller), matching what DisplayResult/ParqetCsvTableRenderer already do; only
  a deployed app view uses the provenance-gated `apps_u` endpoint. This is the path
  that previously relied on marking previews, so nothing regresses.

Test: a preview is never app-provenanced (owner's own preview and a non-editor's
both stay unmarked). Cross-viewer isolation, deployed marking, and the reassignment
guard are unchanged.

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

* fix(apps): app components run on-behalf of the app, not the referenced runnable (review)

Root-causes codex's on-behalf-preview finding: `execute_component` was overriding the
app's resolved on-behalf identity with the referenced script/flow's OWN
`on_behalf_of` (its `on_behalf_of_email`). That is wrong in the app context — the
app's execution mode should govern:

- A Viewer-mode app could execute a component AS the referenced runnable's on_behalf
  identity (privilege confusion / escalation), instead of as the viewer.
- A preview would run as that identity rather than as the caller, so its S3 output
  could not be read back as the caller — the download-identity mismatch codex flagged.

Always use the app-resolved identity (author in author-mode, caller in
viewer/preview); a referenced runnable's own `on_behalf_of` no longer leaks into app
execution. Direct `/jobs/run` still honors a runnable's `on_behalf_of` (unchanged).
With this, previews always run as the caller, so reading editor/preview S3 as the
caller (viewer-scoped `job_helpers`) is unconditionally correct.

- Test: the deployed-component e2e now seeds the script with a distinct on_behalf and
  asserts the component job's `permissioned_as` is the app identity, not the script's.
- Also reword the getS3File `configuration` param comment to describe current state
  only (AGENTS.md comment rule).

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

* chore(apps): surface 'app' trigger kind in Runs UI; condense provenance comments (review)

Addresses codex review nits:
- Add `app` to `jobTriggerKinds`, `triggerIconMap` (LayoutDashboard), and
  `triggerDisplayNamesMap` so app-component jobs (which now carry
  `trigger_kind = 'app'`) are filterable in Runs and render their trigger info.
- Condense the app-origination marker, on-behalf-identity, and provenance-gate
  comments to state each invariant once in <=4 lines at its relevant site
  (AGENTS.md comment rule).

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 10:29:48 +02:00
Ruben FiszelandClaude Opus 4.8 aa098c70c0 perf: drop v2_job side-table ON DELETE CASCADE FKs to speed retention deletes (#9786)
* perf: drop v2_job side-table ON DELETE CASCADE FKs to speed retention deletes

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

* fix: document delete_jobs auth contract and workspace-scope jobs_export purge

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:52:30 +00:00
hugocasa 2db1c0a1fc fix: early return should consider failure_module result (#9241) 2026-05-20 15:58:05 +00:00
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>
2026-05-07 08:00:38 +00:00
efb4a27d51 fix: replace email with permissioned_as for triggers/schedules (#8439)
* refactor: replace email with permissioned_as for triggers/schedules

Add a new `permissioned_as` column (format: `u/{username}`, `g/{group}`,
or raw email) to all trigger tables and schedule. This value is used
directly for job permission checks, removing the need for email lookups
when creating/updating triggers.

- Migration: add permissioned_as to all 9 trigger tables + schedule,
  drop email from trigger tables (schedule keeps it for backwards compat)
- Backend: resolve_email() (async, DB) -> resolve_permissioned_as() (sync)
- Email cache: get_email_from_permissioned_as() with quick_cache for
  places that still need email (fetch_api_authed, schedule backwards compat)
- Frontend: rename email/preserve_email -> permissioned_as/preserve_permissioned_as
  in deploy data and OpenAPI schemas
- Tests updated for new field names and u/{username} format

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

* fix sqlx/build

* update ee ref

* refactor: simplify resolve_edited_by to always use authed username

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

* fix compile + migration

* update ref

* test: add trigger trait method tests for permissioned_as queries

Add tests that call TriggerCrud and Listener trait methods directly
to verify dynamic SQL correctly references the permissioned_as column.
Covers get_trigger_by_path, list_triggers, set_trigger_mode, and
fetch_enabled_unlistened_triggers for all trigger types.

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

* update sqlx

* fix: use permissioned_as directly for schedules and fix audit RLS for groups

- Schedule: permissioned_as only set on create, not on edit/set_enabled
- Schedule: stop reading email column, use get_email_from_permissioned_as
- Triggers: use fetch_api_authed_from_permissioned_as instead of edited_by
- Triggers: rename listener fields for clarity (username -> edited_by)
- Fix audit author username for group permissioned_as (g/test -> group-test)
  to match session.user, preventing RLS policy violations on audit_partitioned
- OpenAPI: remove permissioned_as/preserve_permissioned_as from EditSchedule
- Add backwards-compat comments for schedule email writes

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

* chore: regenerate system prompts for permissioned_as field

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

* fix build

* refactor: generalize onBehalfOf naming, add permissioned_as to EditSchedule

- Frontend: rename onBehalfOfPermissionedAs -> onBehalfOf with comments
  explaining it carries emails for flows/scripts and permissioned_as for
  triggers/schedules
- Frontend: rename getOnBehalfOfEmail -> getOnBehalfOf,
  getOnBehalfOfPermissionedAsForDeploy -> getOnBehalfOfForDeploy,
  customOnBehalfOfEmails -> customOnBehalfOf
- Backend: add optional permissioned_as/preserve_permissioned_as to
  EditSchedule with COALESCE (only updates when provided)
- Backend: add on_behalf_of audit log for schedule edit
- Backend: remove unused resolve_on_behalf_of_permissioned_as
- Tests: remove email assertions from schedule update test (email is
  just backwards compat, only permissioned_as matters)

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

* fix: preserve email column when permissioned_as is preserved on schedule edit

Derive email from the preserved permissioned_as via cache lookup instead
of always writing authed.email. This keeps the email column consistent
with the old behavior for backwards compat with old workers.

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

* fix: update deploy UI labels from "edited by" to "run as" for triggers

Triggers now use permissioned_as (not edited_by) for permissions, so
update the deploy UI wording to reflect this. Also update wm_deployers
group description to mention schedules and permissioned_as.

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

* fix: use u/username format for custom trigger/schedule deploy selection

When picking a custom user for trigger/schedule deployment, store
u/${username} (permissioned_as format) instead of the email. Flows/scripts
continue to use email format for on_behalf_of_email.

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

* fix: show u/username format for "me" option in trigger deploy selector

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

* refactor: simplify OnBehalfOfSelector to return the right format per kind

OnBehalfOfSelector now handles the email vs permissioned_as format
internally based on kind:
- triggers: returns u/username, displays u/username in all options
- flows/scripts/apps: returns email, displays username

The onSelect callback now takes (choice, value?) where value is already
in the correct format. Parent components just store it directly without
needing to know about the format difference.

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

* fix: always show u/username format in OnBehalfOfSelector for all kinds

Display is now consistent: all kinds show u/username in the selector.
The returned value still differs (email for flows/scripts, u/username
for triggers) since the backend APIs expect different formats.

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

* fix: replace email with permissioned_as in http_trigger test insert

The email column was dropped from trigger tables in the migration.

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

* fix: review fixes — migration, app policy, capture cleanup, naming

- Migration: remove DEFAULT '', use nullable → populate → SET NOT NULL
- App policy: set both on_behalf_of and on_behalf_of_email for all choices
- OnBehalfOfSelector: return OnBehalfOfDetails {email, permissionedAs} instead of ambiguous value
- Remove unused email field from Capture struct and query
- Rename getSourceEmail/getTargetEmail → getSourceOnBehalfOf/getTargetOnBehalfOf
- Rename test functions from preserve_email to preserve_permissioned_as

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

* fix: add permissioned_as to all test schedule INSERTs

Since the migration no longer uses DEFAULT '', all INSERTs must
explicitly provide permissioned_as. Updated test fixtures and
schedule_push tests.

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

* fix: strip permissioned_as from exports/sync, fix OpenAPI required field

- Add permissioned_as to workspace export strip list (like edited_by)
- Add permissioned_as to CLI TriggerFile Omit list
- Fix TriggerExtraProperty.required: email → permissioned_as
- Regenerate frontend and CLI types

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

* fix: remove accidentally committed generated files

These directories are gitignored and should not be tracked.

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

* chore: regenerate system prompts for permissioned_as schema changes

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

* fix: remove permissioned_as from CLI TriggerFile Omit list

Already stripped in workspace export, no need to also omit from the type.

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

* fix: optimize email cache key and revert TriggerFile Omit change

- Use single concatenated string for cache key instead of (String, String) tuple
- Remove permissioned_as from CLI TriggerFile Omit (already stripped in export)

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

* fix: zero-allocation email cache lookups using Equivalent trait

Use a borrowed EmailCacheKey(&str, &str) for cache lookups via
quick_cache's Equivalent support. Only allocates (String, String)
on cache miss for insert. This is called on every trigger fire
and schedule push.

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

* fix: add permissioned_as to Schedule required fields in OpenAPI spec

The backend always returns permissioned_as (non-optional String),
so the schema should reflect that.

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

* fix: handle group- prefix in migration UPDATE statements

edited_by can be 'group-{name}' for group-owned triggers/schedules.
The migration now correctly maps these to 'g/{name}' format instead
of incorrectly producing 'u/group-{name}'.

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

* Revert "fix: handle group- prefix in migration UPDATE statements"

This reverts commit 0971392b38.

* fix: use superadmin email to resolve permissioned_as in schedule migration

For users upgrading from older versions where edited_by may not reflect
the actual schedule owner, check if the email belongs to a superadmin
and look up their username. Otherwise fall back to edited_by.

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

* fix: fall back to superadmin email when not in workspace usr table

If the superadmin isn't a member of the workspace, use their email
as raw permissioned_as instead of falling back to edited_by.

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

* fix: always update permissioned_as and email on schedule edit

Consistent with pre-refactor behavior where email and edited_by
were always updated on every edit. permissioned_as is now always
set (to editing user or preserved value), removing the COALESCE
that previously preserved it when not provided.

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

* feat: add schedule permission tests and centralize group prefix constants

Tests: schedule create/update for normal user, workspace admin, and
superadmin not in workspace. Verifies schedule fields (email,
permissioned_as, edited_by) and pushed job fields (permissioned_as,
permissioned_as_email).

Constants: centralize "u/", "g/", "group-" as PERMISSIONED_AS_USER_PREFIX,
PERMISSIONED_AS_GROUP_PREFIX, USERNAME_GROUP_PREFIX.

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

* fix: use @unknown.windmill.dev for synthetic email fallback

Prevents privilege escalation: a user with username like
'superadmin_secret' would get superadmin via the synthetic
email matching SUPERADMIN_SECRET_EMAIL. Using a different
subdomain avoids any collision with hardcoded @windmill.dev emails.

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

* update ee ref

* sqlx

* chore: regenerate system prompts after main merge

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

* chore: update ee-repo-ref to bda51bc33bcb573659e7ff07d0a23ff6e23b8148

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

Previous ee-repo-ref: 8cf1802f8fe183f430830590b4f3172a50207843

New ee-repo-ref: bda51bc33bcb573659e7ff07d0a23ff6e23b8148

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>
2026-03-20 16:28:38 +00:00
Ruben FiszelandClaude Opus 4.6 9ff8a85af6 refactor: extract windmill-api into subcrates for parallel compilation (#7845)
* refactor: extract windmill-api into 4 subcrates (api-auth, store, api-sse, api-jobs)

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

* refactor: eliminate refresh_token OnceLock bridge in windmill-store

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

* refactor: eliminate FromRequestParts OnceLock bridge in windmill-api-auth

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

* refactor: wire subcrates into workspace and clean up unused re-exports

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

* fix: resolve cargo check --all-features errors in subcrate wiring

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

* sqlx

* all

* chore: update ee-repo-ref for warning fixes

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

* refactor: extract windmill-trigger crate and expand windmill-api-jobs

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

* refactor: extract windmill-trigger-kafka crate from windmill-api

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

* refactor: extract windmill-trigger-postgres crate from windmill-api

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

* refactor: extract windmill-trigger-websocket and windmill-trigger-mqtt crates

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

* refactor: extract windmill-trigger-nats, sqs, gcp, and email crates

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

* refactor: extract windmill-trigger-http crate from windmill-api

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

* refactor: move token creation and permission helpers to windmill-api-auth

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

* refactor: extract windmill-native-triggers crate from windmill-api

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

* sqlx

* all

* refactor: extract windmill-api-embeddings crate and fix CI warnings

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

* fix: resolve type mismatch in oauth2_oss and remaining warnings

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

* fix: use correct HTTP_CLIENT config in embeddings crate (30s timeout, cert override)

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

* all

* fix: gate oauth_refresh_ee on oauth2 feature to fix warnings

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

* all

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 22:12:55 +00:00