diff --git a/workspace-server/internal/handlers/workspace_broadcast.go b/workspace-server/internal/handlers/workspace_broadcast.go index 27ce7a8ea..d0baa3352 100644 --- a/workspace-server/internal/handlers/workspace_broadcast.go +++ b/workspace-server/internal/handlers/workspace_broadcast.go @@ -82,18 +82,21 @@ func (h *BroadcastHandler) Broadcast(c *gin.Context) { // Find the sender's org root by walking the parent_id chain. // Workspaces with parent_id = NULL are org roots; every other workspace // belongs to the org identified by its topmost ancestor. + // Uses the same CTE shape as org_scope.go (#1954) — the recursive seed + // must NOT carry `id AS root_id` because that resolves non-root senders + // to themselves instead of their true org root (availability bug #1959). var orgRootID string err = db.DB.QueryRowContext(ctx, ` WITH RECURSIVE org_chain AS ( - SELECT id, parent_id, id AS root_id + SELECT id, parent_id FROM workspaces WHERE id = $1 UNION ALL - SELECT w.id, w.parent_id, c.root_id + SELECT w.id, w.parent_id FROM workspaces w JOIN org_chain c ON w.id = c.parent_id ) - SELECT root_id FROM org_chain WHERE parent_id IS NULL LIMIT 1 + SELECT id AS root_id FROM org_chain WHERE parent_id IS NULL LIMIT 1 `, senderID).Scan(&orgRootID) if err != nil { log.Printf("Broadcast: org root lookup for %s: %v", senderID, err)