Skip to main content
InternalMarkdown

ADR 0002. Random Pairwise External IDs (not derived from internal UUID)

Status​

Accepted for generation and encoding. Partner-facing prefix superseded by ADR 0013: operators receive pp_plr_opr_..., providers receive pp_plr_prv_..., and pp_plr_... is player-visible only.

Random 128-bit pairwise values, Crockford Base32, stored mapping, and rejection of Base32(internal UUID) / HMAC derivation still stand. Aliases are generated when the one-time link completes (ADR 0009), not at passive first exposure.

Context​

PlayerPal's core privacy requirement: no partner may correlate the same player across other partners. Two generation strategies were evaluated:

  1. Encode the internal UUID directly (Base32(internal_uuid)), or derive the external ID deterministically via HMAC(secret, internal_id + audience_id).
  2. Generate a fresh, unrelated random 128-bit value per (player, audience) pair, store the mapping, and Base32-encode it for external use.

Option 1's first variant (direct encoding) is reversible. Anyone holding it can decode back to the same internal UUID, which is then a shared, correlatable value across every partner. This would have violated the privacy requirement outright and was caught before implementation.

The HMAC variant avoids exposing the UUID but introduces its own problems: secret management becomes safety-critical, key rotation is hard, and a mapping table ends up being useful anyway for audit/lifecycle purposes, undercutting the main reason to derive rather than store.

Decision​

Use random pairwise IDs: a fresh cryptographically random 128-bit value per (subject_party_id, audience_party_id) pair, generated at first exposure, stored in party_identifier, and rendered externally as pp_<type>_<Crockford-Base32(random 128 bits)>.

Consequences​

  • Requires a stored mapping lookup (acceptable trade-off; also needed for revocation/rotation and audit regardless).
  • Strong unlinkability: no mathematical relationship between a player's aliases across different audiences.
  • Alias can be revoked/rotated per-audience without affecting others.
  • Compromise of one audience's alias mapping does not reveal another audience's alias for the same player.
  • Internal IDs remain UUIDv7 (time-ordered, index-friendly, native DB support); only the external representation uses random pairwise values, never a transform of the internal ID.