In a previous post, I talked about the deny option and how it’s evaluated. The documentation on MSDN is talking about conflicting permissions on the same level, however, in TFS2008 SP1, permissions are evaluated bottom up and the first match wins. If a user, Eve, is denied read on $/ but is a member of [Proj]\Readers (which has Read access), the read permission will be the first match and Eve will be to read $/Proj recursively. If you need to deny users read permission, you have to make sure to remove them from all groups that has read access. The reason behind this design is that administrators usually want to allow permissions for certain projects to certain users and the rest should be denied, consider the following tree structure:
$/ Proj A Proj B Proj C
You may want to grant Eve read permission on Proj B and only Proj B. To do so, you should deny Eve all permissions on $/ then allow Eve read permission on Proj B. Since permissions are evaluated bottom-up on first-match basis, Eve has read access to proj B, while the denied permissions are effective on both existing projects and future projects D, E, F, ..etc.