Exception hierarchy

- `UserException` — expected failure; `messageKey` is shown to the user (translated).
  - `ValidationException` — invalid input.
  - `AuthorizationException` — missing permission (also written to the `security` log).
  - `InsufficientBalanceException` — wallet cannot cover a debit.
  - `NotFoundException` — entity does not exist or is not visible to the actor.
  - `InvalidStateException` — illegal status transition (already processed, expired …).
- Anything else is an unexpected error: logged with a trace id; the user sees `error.generic`.
