One simple trick helped us a lot: we have a rules transpiler (fireplan) that adds a default "$other": {".read": false, ".write": false} rule to _every_ property. This makes it so that any new fields must be added explicitly, making it all but impossible to unknowingly "inherit" an existing rule for new values. (If you do need a more permissive schema in some places you can override this, of course.)
Our use of Firebase dates back 10+ years so maybe the modern rules tools also do this, I don't know.
What would really help us, though, would be:
1. Built-in support for renaming fields / restructuring data in the face of a range of client versions over which we have little control. As it is, it's really hard to make any non-backwards-compatible changes to the schema.
2. Some way to write lightweight tests for the rules that avoids bringing up a database (emulated or otherwise).
3. Better debugging information when rules fail in production. IMHO every failure should be logged along with _all_ the values accessed by the rule, otherwise it's very hard to debug transient failures caused by changing data.
Our use of Firebase dates back 10+ years so maybe the modern rules tools also do this, I don't know.
What would really help us, though, would be:
1. Built-in support for renaming fields / restructuring data in the face of a range of client versions over which we have little control. As it is, it's really hard to make any non-backwards-compatible changes to the schema.
2. Some way to write lightweight tests for the rules that avoids bringing up a database (emulated or otherwise).
3. Better debugging information when rules fail in production. IMHO every failure should be logged along with _all_ the values accessed by the rule, otherwise it's very hard to debug transient failures caused by changing data.