feat(api): add QR scan-login completion poll on the internal face
QR scan-to-login is a device-code grant where the QR encodes the existing
short-lived account-link code (spec §B3 player game-login). velocity mints a
code in-game, renders it as a QR, the player scans it on a phone already signed
in to the panel, and that web session's verify writes the durable account_links
row bound to that user. The only new verifiable surface that flow needs is the
completion poll velocity calls to learn the link landed and admit the player.
Add GET /api/v1/internal/account/link/status/{mc_uuid}: a read-only, internal
handleLinkStatus keyed by the verified mc_uuid velocity already holds. It reuses
the existing UserByMCUUID, so it adds no migration and no mutation to the
load-bearing VerifyLinkCode; ErrNotFound maps to {linked:false} (pending /
not-yet-scanned), a hit to {linked:true, user_id}. Keying on the public UUID and
not the scanned code means the read carries no guessing surface and needs no
attempt cap — the internal face already gates it to service callers, and the poll
consumes nothing so a velocity restart re-polls safely.
QR render, limbo collision routing, in-game admit, and the reclaim
inherit-disambiguation stay CODE-ONLY (Java/Velocity) and are labeled as such;
this endpoint reports link completion only.
Document the route in openapi.yaml (x-felis-face internal, x-felis-tier service)
so the parity gate holds, and cover it with a hermetic vertical that proves the
poll reflects the durable link only after the external verify and binds the
verifier's id, plus unknown-uuid, idempotency, and internal-only face separation.
This commit is contained in:
4 files changed
+207
No files matched your search
@@ -668,6 +668,37 @@ paths:
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
|
||||
/api/v1/internal/account/link/status/{mc_uuid}:
|
||||
get:
|
||||
tags: [account-internal]
|
||||
operationId: linkStatus
|
||||
summary: Poll whether an in-game UUID has finished linking — the QR scan-to-login completion check (spec §B3).
|
||||
description: >
|
||||
Internal-only, read-only. After a new player scans the QR-encoded link code
|
||||
and the web verify writes the durable account_links row, velocity polls this
|
||||
for the UUID it minted against and admits the player on linked:true, binding
|
||||
the in-game session to user_id. Keyed by the verified UUID (not the scanned
|
||||
code), so it consumes nothing and is safe to poll repeatedly; an unlinked or
|
||||
never-seen UUID returns linked:false, and user_id is present only when linked.
|
||||
x-felis-face: [internal]
|
||||
x-felis-tier: service
|
||||
security: [{ serviceToken: [] }]
|
||||
parameters:
|
||||
- { name: mc_uuid, in: path, required: true, schema: { type: string, format: uuid } }
|
||||
responses:
|
||||
'200':
|
||||
description: Link-completion status; user_id is present only when linked.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [linked]
|
||||
properties:
|
||||
linked: { type: boolean }
|
||||
user_id: { type: string }
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
|
||||
/api/v1/internal/player/reclaim:
|
||||
post:
|
||||
tags: [account-internal]
|
||||
|
||||
Reference in new issue
Block a user