fix(forks): read schedule fork-ness on non-RLS pool; clarify mutator-rule wording

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hugocasa
2026-06-08 17:37:40 +02:00
co-authored by Claude Opus 4.8
parent 3508c86dcb
commit de13ee9426
3 changed files with 25 additions and 17 deletions
+8 -6
View File
@@ -242,17 +242,19 @@ async fn create_schedule(
let mut tx: Transaction<'_, Postgres> = user_db.begin(&authed).await?;
// Writing into a fork never sets operational state: force `enabled = false`
// so a cloned / synced / merged / UI-created schedule can't fire alongside
// the parent's. The fork owner re-enables locally via `setenabled`. This is
// the schedule analog of the trigger rule in
// A git-sync/merge/create write into a fork never sets operational state:
// force `enabled = false` so a cloned / synced / merged / UI-created schedule
// can't fire alongside the parent's. The fork owner re-enables locally via
// `setenabled`. Schedule analog of the trigger rule in
// `windmill-trigger::handler::workspace_is_fork`; the read half (parent-value
// substitution on fork export) lives in `workspaces_export.rs`.
// substitution on fork export) lives in `workspaces_export.rs`. Read fork-ness
// on the non-RLS `db` pool (like the other two sites) so the determination is
// complete regardless of the caller's folder perms.
let target_is_fork: bool = sqlx::query_scalar!(
"SELECT parent_workspace_id IS NOT NULL FROM workspace WHERE id = $1",
w_id
)
.fetch_optional(&mut *tx)
.fetch_optional(&db)
.await?
.flatten()
.unwrap_or(false);
+10 -9
View File
@@ -34,15 +34,16 @@ use windmill_git_sync::handle_deployment_metadata;
/// True when the workspace is a fork (`parent_workspace_id IS NOT NULL`).
///
/// Operational state (`mode`) belongs to the parent workspace: a write into a
/// fork (git-sync push, merge deploy, clone, or even a plain UI create) must
/// never set it. On create we force `disabled` so a fork trigger can't compete
/// with the parent's listener; on update we preserve the fork's existing value.
/// The only mutator of a fork trigger's mode is the `setmode` endpoint (which
/// carries its own conflict warning). This is the write half of the rule whose
/// read half lives in `workspaces_export.rs` (parent-value substitution on
/// fork export), and it is the single authority shared by both the git-sync
/// round-trip and the in-app compare-workspaces merge.
/// Operational state (`mode`) belongs to the parent workspace: a git-sync /
/// merge / clone / UI-create write into a fork must never set it. On create we
/// force `disabled` so a fork trigger can't compete with the parent's listener;
/// on update we preserve the fork's existing value. `setmode` is the intended
/// explicit mutator of a fork's mode (and carries its own conflict warning) —
/// runtime error handling may still auto-disable an errored trigger, which is
/// orthogonal to this rule. This is the write half whose read half lives in
/// `workspaces_export.rs` (parent-value substitution on fork export), and it is
/// the single authority shared by both the git-sync round-trip and the in-app
/// compare-workspaces merge.
async fn workspace_is_fork(db: &DB, workspace_id: &str) -> Result<bool> {
let is_fork: Option<bool> =
sqlx::query_scalar("SELECT parent_workspace_id IS NOT NULL FROM workspace WHERE id = $1")
+7 -2
View File
@@ -57,8 +57,13 @@ The rule that makes both the normal-git PR merge and the in-app merge behave:
> **A trigger's `mode` (and a schedule's `enabled`) belongs to the parent
> workspace. Git-sync *reads* the parent's value into a fork's synced file and
> *never writes* a fork's value back. The only mutator of a fork's operational
> state is the `setmode` / `setenabled` endpoint.**
> *never writes* a fork's value back. No git-sync / merge / create / update
> write sets a fork's operational state; the `setmode` / `setenabled` endpoint
> is the intended explicit mutator.**
(Runtime error handling can still auto-disable an errored trigger or schedule —
that's orthogonal to this rule, which governs git-sync/merge/create/update
writes.)
This is enforced in two halves, keyed off `parent_workspace_id IS NOT NULL`
(the column, not the `wm-fork-*` naming convention — it stays consistent with