From 6604d5882e1b2def71840a8bc9f1a04b4fbb740c Mon Sep 17 00:00:00 2001 From: Will Pfleger Date: Tue, 23 Jun 2026 16:31:10 -0400 Subject: [PATCH] fix(relay): fail-visible on DB error resolving approval-note channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit enforce_latched_approval_note swallowed every get_workflow error via .ok(), collapsing a transient DB error to None and skipping the latch check. A PgPool blip during channel resolution would let a plaintext approval note reach a latched DM — the leak this PR closes, reopened on the security boundary itself. Match enforce_latched_body's posture: NotFound passes (no resolvable channel, cannot be latched), any other DbError is fail-visible. Co-authored-by: Will Pfleger Signed-off-by: Will Pfleger --- .../src/handlers/command_executor.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/crates/buzz-relay/src/handlers/command_executor.rs b/crates/buzz-relay/src/handlers/command_executor.rs index ad513f196b..b4c72529fc 100644 --- a/crates/buzz-relay/src/handlers/command_executor.rs +++ b/crates/buzz-relay/src/handlers/command_executor.rs @@ -120,18 +120,22 @@ async fn enforce_latched_body( /// latched-body rule on the approval note. Approvals reference no `h` tag of /// their own — the channel is the workflow's (`get_workflow().channel_id`). /// A workflow with no channel (global) cannot be latched, so it passes through. +/// +/// The `get_workflow` lookup honors the same fail-VISIBLE posture as +/// [`enforce_latched_body`]: a missing workflow (`NotFound`) cannot be latched +/// and passes, but a genuine DB error rejects rather than silently skipping the +/// check — otherwise a transient pool blip would let a plaintext note slip into +/// a latched channel. async fn enforce_latched_approval_note( state: &Arc, content: &str, workflow_id: Uuid, ) -> Result<(), IngestError> { - let channel_id = state - .db - .get_workflow(workflow_id) - .await - .ok() - .and_then(|w| w.channel_id); - enforce_latched_body(state, content, channel_id).await + match state.db.get_workflow(workflow_id).await { + Ok(w) => enforce_latched_body(state, content, w.channel_id).await, + Err(buzz_db::DbError::NotFound(_)) => Ok(()), + Err(e) => Err(IngestError::Rejected(format!("error: database error: {e}"))), + } } /// Persist a command event inside a transaction. Returns the OPEN transaction