ADR 0026. Random Analytics Subject and Provider-Global Cohort (not alias)
Status
Accepted.
Does not change ADR 0014: a provider-global alias remains forbidden by default. This record allows a provider-global cohort (Account counts, numbers only).
Context
Partners want enrichment without correlating a person across Audiences. Two tempting shortcuts both fail the identity invariants:
- Hang partner analytics off
players.idor expose UUID /pp_plr_.../ another Audience’s alias on a partner read. - Mint one
pp_plr_prv_...per provider so that provider can join the same person across operators. ADR 0014 already rejects that default.
A third need appears at Delete Account: gameplay facts may be retained, but the live UUID join must disappear. A PlayerPal-only clustering key is required so retained Activity is not re-attached to a person on a partner API, and so studio KPIs can count distinct Accounts rather than aliases.
Deriving that key from UUID or pp_plr_... would make it reversible.
Summing per-alias serving rows would double-count a Player with two
integrations at the same provider.
Decision
- Mint a cryptographically random analytics subject (
pp_anl_...) at Account activation. Never derive it from UUID,pp_plr_..., PII, or a partner identifier. Never return it on player or partner APIs (including/v1/me, link exchange, activity ingest, and studio reads). - Live loyalty processing may use Account id in memory. Persisted
partner-facing analytics and serving rows must not expose Account id.
Partner studio HTTP is machine-authenticated and provider-Party scoped
(
x-party-idaspp_prv_...), not ingest’sx-integration-id, and not a payloadoperator_id. - Per-alias studio lookup uses only a
pp_plr_prv_...that provider was issued. A foreign alias is the same unknown as a missing alias. Two aliases for the same Account at that provider return the same Account-level numbers. “On you” is all of that provider’s integrations for the Account, not one casino. Response body is numbers only:from,to,bets,wins,bet_eur,share_of_their_slot_turnover,rounds_on_you,rounds_elsewhere. - Studio rollup counts distinct Accounts for that provider Party and is not
implemented as a sum of per-alias serving rows. It includes
accounts. Windows below a configurable Account floor are suppressed (production default 50; tests/demo may lower it). Per-alias lookup is n=1 by design. - Unlink freezes new partner-player-day rows for that alias; historical days
remain. Delete Account deletes partner-player-day (and related serving)
rows for that Player’s aliases, nulls
player_id/player_aliason retained Activity, destroys the UUID↔analytics-subject mapping, and leavesround_refand the analytics subject on retained facts. Live per-alias GET for those aliases is unknown. - v1 stores UUID↔analytics-subject in application storage. Crypto-shredding / KMS envelope encryption is out of scope. A restored pre-delete backup can still join; do not market otherwise.
Consequences
- ADR 0014 still governs aliases. Open question 5 (which providers, if any, get a provider-global alias exception) stays open. Cohort is not that exception.
- Identity and loyalty topic pages must not say partner analytics hang off
players.id. Internal ledger and identity tables still may. - Closes open question 6 for output (numeric cohort and per-alias enrichment; never another Audience’s identifier) and open question 7 (Unlink vs Delete Account retention). Legal joint-controller contracts stay a product-permission assumption, not an identifier rule.
- Glossary:
CONTEXT.md. Day-to-day: docs/loyalty.md, docs/identity.md. Unlink skeleton: spec §36.6.