---
id: server-architecture/011
title: Google Play Games sign-in on Android
epic: server-architecture
state: needs-input
priority: 2
blocked_by: ["server-architecture/010"]
estimate: M
created: 2026-08-12
updated: 2026-08-13
claimed_by: session-88fa322b-agent2
claimed_at: 2026-08-13T03:05:00.000Z
delivers: []
review_artifact: land-of-lor/docs/handoff/historic/011-play-games-server-half.md
---

## What

The first platform-native sign-in provider on the identity seam that task 010 builds:
**Google Play Games Services** on Android — one-tap (usually silent) sign-in, no
password ever typed on a phone. Decided 2026-08-12 as the immediate follow-on to 010,
split out so the core accounts work doesn't block on Play Console setup.

Per the approved architecture (`../010-accounts-plan.md`, "The identity architecture"):
this is **one new row-kind in `auth_identities`** (`provider = 'google_play'`), one new
director message pair (client sends a Play Games server auth code; the director
exchanges it with Google, reads the player ID, finds-or-links the identity, mints a
session), and one client-side integration (the community Godot Play Games Services
plugin wired into `account_session.gd` + a "Sign in with Play Games" button on the
account screen). No schema change, no session-model change — that's the whole point of
the seam.

## Blocked by

- **Task 010** — the `auth_identities` / `sessions` substrate must exist first.
- **Kris, outside the repo:** a Google Play Console entry for the game ($25 one-time if
  no developer account yet), Play Games Services configured on it, OAuth client set up,
  and the signing-cert SHA-1s registered (including the debug keystore's, so sideloaded
  test builds can sign in). Cleared PICKUP.md's question bar in the 2026-08-12 planning
  session — Kris chose this staging himself.

## Non-goals

Game Center (iOS) and Steam — speced in the 010 plan, built when those platforms exist.
Achievements / leaderboards / cloud save via Play Games — later, same integration rides.

## Server half built — 2026-08-13

Everything buildable without the Play Console is DONE, tested, and deployed
(handoff: `land-of-lor/docs/handoff/historic/011-play-games-server-half.md`):
`login_google_play` on the director (injectable Google exchange —
real/disabled by env, mocked in tests; attach-don't-merge with
`IDENTITY_TAKEN`; `PROVIDER_UNAVAILABLE` while unconfigured), the generic
`attachProviderIdentity` helper, the client seam (`login_google_play` RPC +
`platform_supports_play_games()` gate + sign-in/link buttons that never
render without the plugin), and a live-e2e step proving the droplet answers
`PROVIDER_UNAVAILABLE` cleanly. Director 99/99, world 86/86, live verifies
9/9 + 4/4 + 5/5 + 32/32.

**Now waiting on Kris** — the Play Console checklist (with both SHA-1
fingerprints, release + Godot debug, already computed) is in the handoff:
developer account ($25), app `au.com.cocreations.lor_spellgrove`, Play Games
Services config, Android + Web OAuth clients, `GOOGLE_PLAY_CLIENT_ID/SECRET`
into `/etc/lor/game.env`, testers. After that, the device half: vendor the
Iakobs/godot-play-game-services plugin, wire `request_server_side_access`
into the two `_fetch_play_games_auth_code()` stubs, on-device e2e per the
DoD below.

## Definition of done

On a real Android device: fresh install → play as guest → "Sign in with Play Games" →
one-tap → same LoR account appears on a second device signing in with the same Play
Games identity. Attach-vs-conflict behavior matches the plan's "attach, don't merge"
rule. Server-side verification covered by director tests (mocked Google exchange).