That's a very nice example of Theory VS Practice !
I agree, in Theory, PK should be identified by the natural unique key identifier of the domain. Your example with national_id is proper.
In practice :
- due to their varying underlying type, manipulating natural key identifier throught an application (passing values) is not always easy. UUID or INT are reliable and always works.
- sometimes, we want a "poor" anonymization when passing and calculting data. As the PK is the identifier of the tuple, having a personal data for PK can be problematic.
- last but not least : using PK that is subject to change is a terrible idea. An address mail, for example, anybody can be subject to change. When it's the PK, you are fuck to do or propagate the change.
And in this age of gods war, Practice always win.