notificationId
Stable platform-notification identity shared by posting and cancellation paths.
Deliberately excludes reply_id and time: both change on every firmware reply, so hashing the full notification (e.g. via toString()) mints a fresh id per occurrence and defeats coalescing — a repeated advisory would stack up as a new tray entry every time instead of updating the same one.
Hashes only strings and the enum's wire value, never the enum object: enum hashCodes are identity-based, and the tray outlives the process — a repost after a service restart must land on the same id.