Description
I think an unauthorized user could discover whether an Organization "o1" exists by attempting to lookup a project "p1" inside it. You'll get back a 404 no matter what. If "o1" exists, the 404 will say that p1 doesn't exist. If "o1" doesn't exist, the 404 will say that o1 doesn't exist. In an ideal world, if you had access to see that "o1" existed, we'd tell you it was "p1" that didn't exist; otherwise, we'd tell you that "o1" doesn't exist.
The problem: it's hard for us to know whether you should be able to see "o1". The rule we currently use is: you can see an Organization "o1" if you have permissions to see or do anything with something inside o1. That way, if you want to share, say, o1/p1/i1 with some other user, you don't also have to remember to share o1/p1 or o1 with them. (An alternative would be to require you to share o1 and p1 with them, but have the API do that automatically. That seems to get hairy: what if i1 moves to another Project or Organization? Do we also revoke any automatically-created roles for you? At that point, isn't this just the same rule we're using, implemented using database denormalization?)
A consequence of this: it's prohibitive to answer the question "can user X see Organization Y" -- we have to either enumerate all the resources they have access to and see if they're in that Organization, or we have to enumerate all the resources in the Organization and see if they have access to them. Both of these are potentially huge quantities.
One way to solve this would be to have the 404 always report the complete path that you looked up. Arguably at that point, the error message is useless anyway, so we could just have it be something generic like "resource does not exist". But it does feel like we're throwing away potentially useful information there.