Record updates have to be able to change the type of the value in order to work with polymorphic fields. Here's a contrived example:
data Foo a = Foo { foo :: a }
reFoo x = x { foo = "blarg" }
By the same logic, the resulting type can change the phantom parameter because the phantom parameter is not constrained at all. You could have the same problem without record syntax:
unsafeId (Username first last) = Username first last
That looks fine—but completely bypasses the phantom type! (In fact, it could even produce a Username Int or something.)
This is a fundamental limitation of phantom types. Since they're not constrained at all, they're very easy to change. They're useful, but more as a convention and a warning than as an ironclad guarantee.
In this specific case, I can think of two reasonable options. One is to make the Username type abstract—don't export the constructor and ensure that the only provided ways to make one are safe. Another is to make a String newtype with a flag, and keep that abstract. Domain-specific types like Username could use this newtype for their fields.
newtype Str a = Str String
data Username a = Username { first :: Str a, last :: Str a }
As long as you have access to a Str constructor, you can make "Safe" instances however you like; however, if you keep the type abstract, it can be safe outside the defining module.
There are some other design options, and it's something worth thinking about. But what you've found is a fundamental quality (and limitation) of phantom types and has to be kept in mind as you're working with them.