Skip to main content

Asynchronous player battle storage

Async PvP persists invitations, complete deck snapshots, authoritative battle state, and retry receipts. The API resolves deadlines and serves a separate projection for each participant; polling reads committed state.

Player battles compares async and live play. The async API contract owns routes and response formats.

Stored model​

RelationsResponsibility
async_pvp_invitationsChallenger, recipient, status, version, expiry, and accepted match reference.
async_pvp_matchesCurrent actor, deadline, version, winner, and terminal result.
async_pvp_match_participantsExactly 2 participants, engine sides, snapshot references, and outcomes.
async_pvp_match_actionsOrdered legally revealed actions and results.
Private deck snapshots and snapshot cardsComplete battle-ready decks, including unrevealed cards.
private.async_pvp_match_statesFull current battle state at the match version.
private.async_pvp_match_transitionsImmutable before/after state and authoritative action result.
private.async_pvp_submission_receiptsCanonical payload hash and committed actor-relative response.

A public schema name does not grant API access. Private relations have PUBLIC privileges revoked, and participant responses omit hidden opponent cards, full state, and private transition data.

Invitation and match creation​

Invitations start pending at version 0 with a 24-hour expiry. A unique unordered-player-pair key prevents reverse concurrent invitations from both committing. Terminal invitation states cannot reopen.

Acceptance creates the complete match graph in one transaction. Deferred checks require both valid deck snapshots, 2 participants, private state, and a matching receipt. Cancellation is challenger-owned and creates a cancellation receipt without a recipient snapshot or match.

Source deck and owned-copy IDs in snapshots are historical values, rather than restrictive foreign keys to mutable player configuration.

Actions, deadlines, and replay​

An active match has 1 current participant and a 24-hour decision deadline. Match and private-state versions advance together by 1. Every public action has a matching private transition and submission receipt.

Receipts are unique by authenticated actor, operation, and submission UUID. The canonical payload hash distinguishes identical retries from conflicting reuse. A retry returns the committed actor-relative response instead of applying the action again.

The service locks the authoritative resource and rechecks its deadline before accepting a mutation. Deadline workers select bounded due candidates and recheck after locking; reads also reconcile elapsed deadlines where required.

Terminal reasons are defeat, turn_forfeit, voluntary_resignation, and account_deletion_forfeit. A completed match has 1 winner and 1 loser. Snapshots, terminal state, actions, transitions, and receipt history are immutable during normal operation.

Progression​

Completion invokes recordAsynchronousPvpCompletion inside the terminal match transaction. It records 1 award decision per participant in canonical player-ID order under per-player locks. A progression failure rolls back the match result.

Both decisions count as activity, including a zero-point result. Unique match/participant sources prevent repeat awards. Async results do not update live-ranked ratings or territory influence.

Progression storage owns award integrity; Progression rules owns values and achievement behaviour.

Deletion and retention​

Account deletion closes pending invitations and completes active matches before removing personal data. An already-elapsed deadline takes precedence: the current actor loses by turn_forfeit; otherwise the deleting participant forfeits.

Completed shared matches retain profile-free historical actors and immutable battle snapshots. History displays Deleted player after account removal, and retained replay responses redact copied Player Names and old player IDs.

There is no routine purge of terminal invitations. Account deletion has its separate cleanup boundary. See Account retention for personal-data removal and shared records.

AI declaration: Prepared and updated with assistance from Codex-CLI[gpt-5.6-sol medium], Codex[GPT-5], Codex-CLI[GPT-6], and Codex[GPT-6].