"Happening at a higher level" is a reasonable solution, if it happens consistently, no matter which higher level you're using. If you have 18 different functions to open a file, and 11 of them normalize and 7 don't, then you're screwed before you even get out the door. Programmers simply aren't capable of getting this right in a consistent way if asked to solve the problem application by application.
which screws you because anyone can just call fopen on their own without using the core foundation libraries, leading to inconsistent states in the filesystem. You can be higher level than the filesystem, but only a little bit. You can't be higher level than some API that developers will regularly use (unless you do like ZFS and normalize at lookup rather than create).