You *can* get more fine-grained with your permissions, completely securely - I've started using…
The claims can only be updated from a secure node (firebase-admin), so you do need to use a server or firebase functions.
You *can* get more fine-grained with your permissions, completely securely - I've started using "customClaims" on the user, which *are* accessible in *both* firestore and storage. Setting/changing is slightly wonky. (I've experienced the customClaims object presented to firebase-admin is closer to a JSON string that a proper object, so I've had to JSON.parse(JSON.stringify(customClaims)) to get it to merge with new claims - I have already two, and likely to have a couple more. There's a limit of 1000 bytes, so don't go hog-wild)
The claims can only be updated from a secure node (firebase-admin), so you do need to use a server or firebase functions.