# Linking and bootstrap

A bootstrap method is the first proof used to create and secure a PlayerPal account. An operator or provider assertion proves local partner context; it does not give that partner permanent ownership of the portable account.

Long-form: spec §10-§11, §33, §36.6, §45-§46. Decisions: ADR 0009, 0010, 0014, 0017, 0019, 0020, 0024, 0026, 0027.

Diagrams: [spec/playerpal-bootstrap-diagrams/](../spec/playerpal-bootstrap-diagrams/). Mockups: [spec/playerpal-device-mockups/](../spec/playerpal-device-mockups/).

## When an account exists

No activity data for a `(player, audience)` relationship is transmitted to PlayerPal until the player has registered or linked at least once (ADR 0009). After that, earning is automatic. A browser cookie expiring does not break the server-side link. Reauthentication is for viewing, spending or managing the account, not for continued asynchronous earning (spec §33).

The first link creates the account. A later audience either signs into that account (unification) or creates a separate independent account. Fragmented accounts are expected, not a bug (ADR 0010). There is no separate later "claim" step.

Earning starts only after explicit registration/activation. PlayerPal does not create pre-registration shadow profiles or award historical points by default (spec §33). Events are eligible only when `occurred_at >= connection.effective_from` and before Unlink revocation (`unlinked_at`; spec §36.6 `effective_at`).

## Bootstrap methods

| Method | Creates first account? | Recommendation |
|---|---|---|
| Passkey | Yes | Default |
| Approved social OIDC (`iss + sub` only) | Yes | After provider POC |
| Partner assertion + passkey | Yes | Best embedded flow |
| Partner assertion + recovery secret | Yes | Controlled fallback, then upgrade |
| Generated PlayerPal ID + password | Provisional only | Restricted fallback (A0) |
| Player-chosen username + password | Technically yes | Do not launch initially |
| Native device key | Yes | Mobile complement; do not replace WebAuthn |
| Existing-device QR | No; adds a device | Recommended device-add |
| Partner activation code | Only after a durable credential | Campaign / invitation context |

`POST /v1/registrations` creates short-lived registration state only. It does not create a player until a permitted bootstrap ceremony completes. All mutating calls require an `Idempotency-Key`. HTTP examples: spec §45.3 and §37.

## Operator / provider linking

Do not put the assertion or an access token in a URL.

1. Operator (or provider) authenticates as a machine client and `POST /v1/link-intents` with a short-lived signed assertion in the body (about five minutes; replay-protected `jti` / nonce).
2. PlayerPal returns a `link_url` containing an opaque one-time code.
3. The player completes a first-party PlayerPal ceremony (passkey, social, or existing-account discovery).
4. The player consents to that exact operator/provider connection.
5. Exchange returns aliases for the completing Audience only:
   - **Operator-led:** `pp_plr_opr_...` plus requested `pp_plr_prv_...` aliases already authorized for that operator (spec §37.4).
   - **Provider-led:** only that integration’s `pp_plr_prv_...`. It does not mint `pp_plr_opr_...` or an operator identity link.

`requested_provider_integrations` must already be authorized for that operator; it does not grant scope. Normal game launch then carries the provider alias in the operator's existing launch payload. No synchronous PlayerPal call (ADR 0015).

## Unlink and Delete Account

Unlink and Delete Account are player session APIs next to `GET /v1/me` (`DELETE /v1/me/connections/:audienceId`, `DELETE /v1/me`). Both require recent reauthentication and `Idempotency-Key`.

**Unlink** is spec §36.6: revoke one consented Audience; stop qualifying later events; keep aliases reserved; optional async partner notice; delayed pre-revocation Activity may still qualify. Operator-led Unlink is Unlink of that operator (cascade-revoke provider aliases for that operator’s integrations). Provider-led Unlink is Unlink of that provider-operator integration only. Relink mints a new Pairwise alias. Play at the partner continues. Demo Bucks has no player-links revoke; PlayerPal pushes a notice and Bucks may reconcile alias status so casino chrome can show Connect ([ADR 0032](decisions/0032-unlink-partner-notice.md)).

**Delete Account** erases the identity graph and retains gameplay facts without identity keys. It does not command partner erasure. Details: [identity.md](identity.md) and [ADR 0026](decisions/0026-analytics-subject-and-provider-cohort.md).

## Account discovery

Before creating an account, the UI asks "Already have PlayerPal?" and offers passkey, approved social, PlayerPal ID + password, existing-device approval, or recovery code. Never email or telephone lookup. Never reveal whether an arbitrary PlayerPal ID exists. Uniform authentication errors.

A repeatable external proof maps through a non-reversible lookup key scoped by issuer (spec §46.2). The same active social, operator, or integration-scoped provider subject cannot create a second player.

## Merge

Merge is a high-risk correction, not automatic deduplication. The player must independently authenticate both accounts with recent step-up. Preview consequences without exposing private partner identifiers. Ledger history stays immutable; adjustments use compensating entries.

Automatic merge is prohibited for matches based on email, name, phone, IP, device fingerprint, timing, gameplay similarity or profile similarity (ADR 0019).

## Related ADRs

- [0009](decisions/0009-mandatory-one-time-link-before-data-flows.md) no data before link
- [0010](decisions/0010-linking-unifies-no-separate-claim.md) unification at link time
- [0014](decisions/0014-provider-operator-alias-scope.md) provider-operator audience
- [0017](decisions/0017-operator-assertion-popup-linking.md) assertion + popup
- [0019](decisions/0019-scoped-bootstrap-proofs-controlled-merge.md) duplicates and merge
- [0020](decisions/0020-assurance-levels-provisional-password.md) A0-A3
- [0024](decisions/0024-nest-owned-portal-auth.md) Nest-owned portal password/passkey
- [0026](decisions/0026-analytics-subject-and-provider-cohort.md) analytics subject and cohort
- [0027](decisions/0027-alias-provisioning-at-link.md) mint listed aliases at link complete
