It does seem confusing at first but it actually makes a ton of sense when you dive in. Every Administrator.Account is a specialization of System.User. You can get the Account version of the object by casting (use the Cast action) the System.User object or even better would be not to use the $currentUser at all and use the Microflow called GET_CurrentUser from the Administrator module (You can also do this with a database retrieve and use id=$currentUser). With regard to the security, remember that Account has all the properties of User because they are inherited. So you can get/set the UserRoles on Account just like you can on a User.
I hope that helps!
All your observations are correct. A lot has already been said on this so I will keep this short.
1: System.User is misnamed. This should have been called Account. Now Account inherits from User. This is just plain wrong. An account is not a user. A user has an account.
2: There are indeed some issues around System.User and security. For this reason I like not inheriting from User, but associating with it instead. (Note: You own the Administration module, you are not forced in any way to use it's current setup).
3: You can make a simple microflow that casts $CurrentUser to an Account if you actually do use the standard inheritance setup.
4: There is no perfect solution. A good solution from a logical point of view required an extra association and therefore slightly slower database performance for everything where you need to check the assocation to currentUser.