Skip to content

Map: Blizzard achievement-fingerprint discovery #4

Description

@Erilla

Destination

An approved design spec for adding Blizzard achievement-fingerprint discovery to SlashWho — the same artifact the MVP started from, ready to hand to /writing-plans and then subagent-driven execution. The map is done when nothing is left to decide before someone writes that spec.

Notes

Domain. World of Warcraft character data. SlashWho currently discovers alt characters from Raider.IO signals only; this effort adds the Blizzard achievement fingerprint that the MVP deliberately cut (design spec non-goals).

How the fingerprint works. Account-wide achievements share an identical completion timestamp across every character on an account, so the proportion of shared achievement ids with matching timestamps identifies same-account characters. Reference implementation in SeriouslyCasualBotV2: src/functions/applications/alts/compareFingerprints.ts (thresholds ≥20% match, ≥200 common achievements; calibrated against four live accounts — unrelated pairs a median 6 identical out of ~4,000, genuine pairs 31–86%), src/functions/applications/alts/discoverAlts.ts (candidate generation by BFS over guild rosters), src/services/blizzard.ts (API client, 48h fingerprint cache, 24h roster cache).

The central tension — restated after the research landed. The map was charted believing candidate enumeration was the constraint. It is not. There is no bulk achievements endpoint, so every candidate tested costs one metered request: 36,000 candidates would consume an entire hour of global Blizzard budget to serve one subject. Reach is bounded by matcher cost, not enumerator yield, and the gain comes from choosing better candidates rather than more of them. See Candidate sources beyond guild rosters.

Skills every session should consult. /grilling and /domain-modeling for decision tickets, /research for research tickets, /prototype for prototype tickets.

Standing constraints (from the MVP's Global Constraints — the spec must not break them without an explicit decision): store no BattleTags, Discord handles, guess strings, raw IPs, API keys, or raw upstream response bodies; never create a snapshot from a transport, 429, or 5xx failure; snapshots are immutable and swapped only after an atomic commit; all operational limits come from validated environment configuration; no internal provenance in public output.

Decisions so far

  • Candidate sources beyond guild rosters — the ticket's premise was wrong: enumeration is not the constraint, matcher cost is, so the ceiling is low thousands of tested candidates per subject. Blizzard has no character search and no guild index. Best find is Raider.IO raid-rankings as a de-facto guild index paired with Blizzard rosters; the self-corpus is a dead end as a generator; bank alts, levelling alts and unguilded players stay unfindable from any public source.

  • Fingerprint mechanics and per-character cost — mechanism intact and better evidenced than the bot assumed (timestamps are account-wide for account and character achievements). One fingerprint is one request, ~333–400 ms, 0.0028% of the hourly budget; 36,000/hour and 100/second confirmed. Fingerprints do not compare across regions and CN has no Profile API. Biggest open risk is unmeasured response weight — at the top of the 1–4 MB estimate, bandwidth rather than rate limit becomes binding.

  • Data-protection exposure for publishing derived account linkagea character name is personal data (ICO: a username identifies a person "regardless of whether it is possible to link the 'online' identity with a 'real world' named individual"), so SlashWho would be an independent UK GDPR controller for every player worldwide, with no exemption and Art 6(1)(f) the only candidate basis. Eleven of thirteen prerequisites are tractable; the balancing and necessity tests both fail for the cohort who deliberately hid the link, because a hidden flag is documented evidence of a contrary expectation under Recital 47. Enforcement probability is low, but publication is irreversible and the exposure is personal and uncapped — an Art 82 claim and Blizzard's indemnity both bite without the ICO acting. The two mitigations that move the risk are behavioural, not documentary: don't publish inferred-only linkage where a contrary preference was signalled (it is detectable), and don't let those pages be indexed.

  • Blizzard API terms and rate limitsambiguous, leaning restrictive; not a green light. Access is permitted in form (ToU last updated 2019, contemplating nothing like this) but registration compels an Intended Use declaration. Storage is a flat no beyond a mandatory 30-day TTL, with anonymisation explicitly rejected as a substitute. Publication turns entirely on "invasive of the privacy of another person… in Blizzard's sole discretion", with termination without notice and an uncapped indemnity. A player-facing opt-out already exists upstream, so a population of players has already refused third-party tools. Reading the terms harder cannot settle this — hence Put the publication question to Blizzard in writing #17.

  • Privacy stance on defeating hidden ownership — Raider.IO is the sole privacy signal: exclude privacy-hidden ownership from fingerprint-derived linkage, follow upstream visibility for public data, and add no separate SlashWho opt-out; state the hidden-owner exclusion on /privacy. Reversed 2026-08-10 — the only available signal could not distinguish a withheld ownership link from a character never claimed on Raider.IO, so it excluded both; both gates were removed in #34 and manual removal requests are now the only exclusion route.

  • Register Battle.net application and provision credentials — Battle.net application SlashWho is registered; BLIZZARD_CLIENT_ID and BLIZZARD_CLIENT_SECRET are Railway secrets on the private worker in test and prod. The registration flow disclosed no rate tier or additional condition.

  • Access and budget model for an expensive sweep — fingerprint discovery runs automatically in each search job; jobs are FIFO under existing 10-anonymous/60-bot hourly limits, wait for capacity, and reserve their full cap before starting against a 28,800-request/hour shared budget (80% of Blizzard's limit).

  • Public presentation of inferred matches — fingerprint-derived and Raider.IO-declared relationships share one undifferentiated public alt list, with no confidence score or discovery-method disclosure.

  • Snapshot and limitation model for probabilistic results — snapshots retain membership, not confidence; cap-bounded sweeps publish partial snapshots with internal fingerprint_sweep_capped; later non-matches simply omit characters in new history, and privacy-hidden ownership is excluded before matching.

  • Retention and compact signature for fingerprint material — fingerprints are transient in-memory sweep inputs only: no IDs, timestamps, compact signatures, or raw response bodies persist; later sweeps re-fetch candidates rather than treating the corpus as a free cache.

  • Measure sweep reach and cost against SlashWho's corpus — with transient fingerprints, the corpus comparison was out of scope; the live Ictinus guild sweep used 393 requests in 134s, found three known hidden-owner alts at 49.6–52.5%, and did not reach Mistakinus; response bodies had a 1.63 MB median and 2.75 MB maximum.

  • Durable job contract for long, large sweeps — a sweep is one atomic, cap-reserved in-memory job: cap reach publishes the allowed partial snapshot and ends; all interruption/failure/shutdown paths discard progress and retry later from the root, preserving the prior snapshot.

  • User-provided Blizzard credentials for fingerprint sweeps — deferred outside this system: only operator-managed credentials are used; accepting requesters’ credentials requires a separate security, lifecycle, and storage decision.

  • Observability for the shared Blizzard request budget — internal-only logs/metrics cover queue, admission, reservation/use, commitment, and retry accounting; alert at 15 minutes blocked admission, 90% reserved capacity, or any Blizzard rate-limit response.

  • Fingerprint match threshold and freshness calibration — launch retains the internal ≥20% identical / ≥200-common rule; the ~50% verified results are normal; change it only after a 10 same-account / 10 unrelated labeled calibration sample.

  • Fingerprint sweep refresh cadence — discovery is eligible at most weekly per root; the first due search queues it and later searches join; the prior snapshot stays visible and only successful publication advances the cadence.

  • Stable character identity for inferred links — deferred to a standalone corrective effort; launch retains canonical realm/name identity, treating renames or transfers as new keys, without persisting fingerprint material.

Not yet specified

Out of scope

  • Guild history and Mythic raid log collection — a separate capability, and an MVP non-goal.
  • SeriouslyCasualBotV2's own implementation and its cutover to the SlashWho API — this map covers SlashWho only; the bot keeps its code and its eventual cutover is its own effort.
  • User accounts, sign-in, and user-editable claims or merges — MVP non-goals, unchanged here.
  • Raider.IO character-rankings as a bulk enumerator — would yield 4.6M characters for 46k requests, but Raider.IO's terms prohibit scraping beyond published endpoints. Ruled out on terms, not on cost (#7).
  • Asking Blizzard in advance whether this use is permitted (#17) — maintainer's decision; no contact was made. The discretionary clause Blizzard API terms and rate limits for public account inference #5 surfaced is therefore not resolved, only unasked: proceeding means accepting that risk rather than retiring it. The Intended Use declaration at registration becomes the whole of the disclosure. Reversible — one new ticket, not a closed door.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions