Hi Andy,
With your current logic,
Line 19 wouldn't work as expected because
Line 12 would (in theory) already have allowed access to farm members. If any level of the hierarchy allows read, then it is granted. To see this in action, try adding "read": true at the "rules" level in Forge and then running the simulator. Read access will be allowed even to anonymous users, even though they have more restrictive read privileges at the child level.
An easy way to solve this is to have a public profile for the user which is separate from their secured data. This might also simplify your overall use case, since at worst, if I could successfully guess another user's ID, I could at most see their public data (name, rank, and what not). I find this the easiest way to secure user data since it's generally not an issue if I can find somebody's screen name without permission.
Accomplishing your desired behavior at line 12 is a bit of a tricky case. There is not an {any} wildcard yet. One simple answer is to maintain an index which includes anyone in my "farms". Thus, if the farms I belong to looked something like this:
/farms/farmA/users/ [kato, mary, john, ginger]
/farms/farmB/users/ [kato, bill, john, mary]
Then my user profile would have a "friends" index with keys like this (the values don't really matter here, a true or 1 would do fine):
/users/kato/friends/mary
/users/kato/friends/john
/users/kato/friends/ginger
/users/kato/friends/bill
Then I could write Line 12 as follows:
"read": "auth.id == $user_id || data.child('friends').child(auth.id).exists()"
Obviously, it's a bit of extra work to keep those items synchronized, but this pattern has worked for me in a few instances.
Hope this helps,
Kato