Files
gogobee/internal/plugin/pete_test.go
prosolis ae7ff38996 Pete news: salted per-event GUID token + zone_clear taxonomy
Closes the two deferred code-review follow-ups on the adventure-news
seam, plus folds in two pre-committed WIP fixes.

A. Privacy — the public GUID no longer leaks a stable per-player id.
   Replaced userHash(userID)=sha256(userID)[:6] with
   eventToken(userID, discriminator)=HMAC-SHA256(salt, userID‖disc).
   The salt is 32 random bytes, auto-generated once and persisted in the
   durable news_config table (cached via sync.Once). Because each event
   uses a distinct HMAC message, tokens are a PRF output and are BOTH
   uncomputable from a Matrix handle (no enumeration of a player's
   events, incl. ones anonymized after !news optout) AND mutually
   unlinkable (a named event can't be walked back to a player's other,
   anonymized events). Updated all emit sites: pete.go zone, dnd_combat
   death, adventure_duel rival, dnd_setup arrival, achievements
   milestone, bootstrap x3.

B. Taxonomy — repeat zone clears were mislabeled zone_first. Now emit
   zone_clear (bulletin) vs zone_first (realm-first, priority). Adopted
   the invariant GUID-prefix == event_type, which also fixes latent
   permalink mislabels (achv->milestone, rival->rival_result rendered a
   neutral "Dispatch" on their permalink pages).

Folded-in WIP fixes: create the news_config table b42beec's
newsEmissionOn reads but never created; reap sent pete_emit_queue rows
in RunMaintenance; don't burn a retry attempt when shutdown cancels an
in-flight send.

Tests: TestEventToken (salted/stable/per-event/persisted),
TestEmitZoneClearTaxonomy (first->zone_first, repeat->zone_clear),
updated pete_test.go prefixes. Full internal suite + vet green.

Unshipped. Deploy Pete first (it must know zone_clear), then gogobee.
2026-07-11 07:43:57 -07:00

6.7 KiB