I think when you do "typename Flag = ..." you're actually just setting the *default* type of Flag, so there's not any constraint there... so that's why it lets you use flags from a different struct. if you use "typename Mask::e" as the argument type it seems to work, and correctly fails if the types don't match.
I can't tell whether your neat enum-in-struct implementation is enabled as the result of terrible or genius design on the part of the C++ designers. In some ways I find your solution very compelling, but the lack of proper generic constraints requiring you to do weird stuff with just makes me want to return to the wilful ignorance I can enjoy from using children's languages like C#.
In C++20 the problem of constraining types is much improved with the introduction of concepts to the language so i believe there is no need to ever use enable_if anymore if you are using c++20 or higher. I don't think there is anything to make working with bit flags any better though