# User identity data

## Stored values and validation

The identity fields are `name_first`, `name_last`, `name_nick`, and
`date_of_birth`. Registration, account editing, child editing, and
administrative editing use the same model-level rules.

When an optional birth date supplied during public registration does not meet
the independent-registration age rule, validation rejects the registration.
The user-facing error refers only to the requirement for an adult account
holder and directs the parent or guardian to add the child profile. The model
enforces the rule independently of browser validation.

Names have surrounding and repeated whitespace removed. A component written
entirely in uppercase or lowercase is converted to title case. Existing mixed
case is preserved. Common lowercase surname particles, including `vel`, are preserved. Nicknames
only have whitespace normalized.

The first and last name cannot be equal after case-insensitive whitespace
normalization. A nickname cannot repeat the first name, last name, or the full
name in either order. Multi-component names remain valid and are never split by
the application.

## History

`user_identity_history` stores only fields that changed, as JSON snapshots
before and after the update. It also stores the affected account, optional
actor, source, and timestamp. Sources are `account`, `parent`, and `admin`.

For existing accounts, the user update and history row are committed in one
transaction after locking the current user row. Registration does not create a
history entry. Administrators can read paginated history on the account edit
screen. No web interface edits or deletes history rows.

Account deactivation is the formal personal-data removal operation. It deletes
the affected account's history and sets `id_actor` to `NULL` on history entries
for other accounts. It then anonymizes the account in the same transaction.

## Deployment and verification

The additive migration `20260919120000_add_user_identity_history.sql` creates
the history table. It must remain tracked after deployment. Existing account
values are not changed in bulk; history starts with subsequent saved edits.

Run `tests/user_identity_test.php` for normalization and duplicate validation.
Run `tests/user_identity_history_test.php` only against an isolated test database
using `RP_TEST_DATABASE`. Verify the account, child and administrative forms,
read-only history, and atomic rollback when history cannot be saved.
