mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-09 16:05:42 +00:00
docs: state the RLS and restamp constraints once each
The RLS envelope was argued at three sites in drafts.rs; it now sits only on `resolve_moved_to_in`, whose signature is what a caller would break. The restamp scoping was copy-pasted at all three deploy call sites while already documented in full on `move_drafts_for_path`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3528054801
commit
f79812cc44
@@ -1385,10 +1385,7 @@ async fn update_flow(
|
||||
if is_new_path {
|
||||
// Everything left at the old path is a draft this deploy didn't consume
|
||||
// — teammates' rows, and the deployer's own when the caller asked us to
|
||||
// keep it. Carry them rather than strand them. Only the deployer's own
|
||||
// row is restamped: this runs on any path-changing deploy, content edits
|
||||
// included, and a teammate whose draft claimed the new head would lose
|
||||
// their stale-draft warning.
|
||||
// keep it. Carry them rather than strand them.
|
||||
let outcome = windmill_common::user_drafts::move_drafts_for_path(
|
||||
&mut tx,
|
||||
&w_id,
|
||||
|
||||
@@ -2137,10 +2137,7 @@ async fn create_script_internal<'c>(
|
||||
if p_path != &ns.path {
|
||||
// Everything left at the old path is a draft this deploy didn't
|
||||
// consume — teammates' rows, and the deployer's own when the caller
|
||||
// asked us to keep it. Carry them rather than strand them. Only the
|
||||
// deployer's own row is restamped: this runs on any path-changing
|
||||
// deploy, content edits included, and a teammate whose draft claimed
|
||||
// the new head would lose their stale-draft warning.
|
||||
// asked us to keep it. Carry them rather than strand them.
|
||||
let outcome = windmill_common::user_drafts::move_drafts_for_path(
|
||||
&mut tx,
|
||||
&w_id,
|
||||
|
||||
@@ -3450,10 +3450,7 @@ async fn update_app_internal<'a>(
|
||||
if npath != path {
|
||||
// Everything left at the old path is a draft this deploy didn't consume
|
||||
// — teammates' rows, and the deployer's own when the caller asked us to
|
||||
// keep it. Carry them rather than strand them. Only the deployer's own
|
||||
// row is restamped: this runs on any path-changing deploy, content edits
|
||||
// included, and a teammate whose draft claimed the new head would lose
|
||||
// their stale-draft warning.
|
||||
// keep it. Carry them rather than strand them.
|
||||
let outcome = windmill_common::user_drafts::move_drafts_for_path(
|
||||
&mut tx,
|
||||
&w_id,
|
||||
|
||||
@@ -415,9 +415,7 @@ fn draft_lineage(kind: UserDraftItemKind, value: &str) -> Option<DraftBaseVersio
|
||||
/// caller can't see where it went.
|
||||
///
|
||||
/// Reads under RLS so the answer can never reveal an item the caller has no
|
||||
/// access to. `resolve_moved_to_in` makes no such guarantee on its own — it
|
||||
/// inherits whatever scoping the transaction it is handed carries, which is why
|
||||
/// every caller passes an RLS-scoped one.
|
||||
/// access to.
|
||||
async fn resolve_moved_to(
|
||||
authed: &ApiAuthed,
|
||||
user_db: &UserDB,
|
||||
@@ -429,14 +427,10 @@ async fn resolve_moved_to(
|
||||
if draft_lineage(kind, value).is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
// RLS is not optional on THIS entry point: it runs before the write gate, so
|
||||
// the envelope is what stops the answer naming an item the caller cannot see.
|
||||
// Cost, stated honestly: `UserDB::begin` is not a bare BEGIN — it issues
|
||||
// BEGIN, `set_session_context`, and `SET LOCAL search_path` when `PG_SCHEMA`
|
||||
// is set, and the commit is another round-trip. So 3-4 round-trips wrap one
|
||||
// indexed existence check, and the lineage query runs only once that check
|
||||
// says the item is gone. `draft_lineage` above is what keeps all of it off
|
||||
// the drafts that have nothing to follow.
|
||||
// `UserDB::begin` is not a bare BEGIN — it also issues `set_session_context`
|
||||
// and, under `PG_SCHEMA`, `SET LOCAL search_path`, so this wraps one indexed
|
||||
// existence check in 3-4 round-trips. The `draft_lineage` check above is what
|
||||
// keeps that off every draft with nothing to follow.
|
||||
let mut tx = user_db.clone().begin(authed).await?;
|
||||
let moved = resolve_moved_to_in(&mut tx, &authed.username, w_id, kind, path, value).await;
|
||||
tx.commit().await?;
|
||||
|
||||
Reference in New Issue
Block a user