2.4 KiB
Account Boss Card checkpoints
PATCH /api/cloud-save adds an account-scoped checkpoint for Boss Cards without sending a replacement cloud document. The server derives the owner from the authenticated bearer session; request fields cannot choose an account. The body is { "bossCards": <raw collection>, "expectedRevision": <nonnegative safe integer> }.
The server serializes the compare and write in a SQLite BEGIN IMMEDIATE transaction. A missing save has revision 0. A matching request merges the submitted collection with that account’s saved cards, changes only data.bossCards, increments the cloud revision, and returns { revision, updatedAt, data }. A stale revision returns HTTP 409 with code: "revision_conflict" and writes nothing. The client should reload the current save before retrying. Missing collections and invalid revisions return a client error; malformed collection values normalize to empty under the source policy without removing existing cards; an unauthenticated request is rejected before the body is used.
Normalization and merge behavior match src/game/bossCards.ts: the allowed rarities are Normal, Rare, Epic, and Legendary; positive finite counts are floored and bounded by Number.MAX_SAFE_INTEGER; invalid/unknown entries are dropped; repeated account copies keep maximum counts. Numeric time:revision claim IDs keep the later time and then higher revision; other claim strings use lexical maximum. Map-like output uses null-prototype count/claim records so names such as __proto__ remain ordinary data keys.
Legacy PUT /api/cloud-save remains a full replacement for non-card fields. When either the stored or incoming document has a Boss Cards field, the server max-merges those collections into the incoming document. This keeps old clients that omit or resend stale card snapshots from deleting earned account cards, while their other fields retain the existing replacement behavior. PUT does not gain optimistic concurrency; PATCH is the revision-checked card-only route.
The focused loopback test uses the pinned source server factory, authenticated SQLite accounts, and a temporary database. It covers account isolation, cross-origin PATCH preflight, authorization, normalization, conflict/no-write and retry, concurrent revision checks, stale and omitted-card PUTs, deduplication, and server restart persistence. It does not contact the hosted service or exercise native UI integration.