".write": "data.exists() && auth.uid === $uid && newData.exists()"
A security rule that allows users to edit their profile but only Forge (admin: true) to create them:
Great point. While it helps with reading the errors in the simulator, it doesn't actually affect what users see or change the rule behavior. It's a short circuit, since user must still be authenticated for the rule to pass.
If you're terribly OCD and don't like that approach, then you can cut out Simple Login. As stated previously, it just creates tokens on your behalf. So simply create your own.
In this way you have complete control over account creation and token generation.
Instead, just utilize security rules to control access to data. When an admin creates an account, have them also add a profile into the data. If only an admin in Forge is allowed to create the profile, then someone could create an account, but it would be superfluous and pointless, since all it does is give them an inert token.
Simple Login is just a convenience wrapper that creates Firebase tokens. There is no limit on how many accounts can be stored and they have no affect on your Firebase usage. With this in mind, there's really no reason you need to restrict creation of accounts.
You can't prevent users from being created on the client using simple login. There are two options you can utilize instead:
Your rule should read: ".write": "auth != null && root.child('valid_account/'+auth.uid).exists()" otherwise, you're getting denied because it can't add the path to null (auth.uid is null if not authenticated) - but it seems like you want to do something more than deny access on an operator error. The exact error you get without checking for auth != null is: Type Error: + only operates on numbers and strings. ;)