Phoenix API: sync exp/cash from game servers — current state and work items
## Goal
Enable the Elixir/Phoenix backend and web UI by having **game servers submit authoritative deltas** (experience, cash, pills, etc.) instead of holding all state only in MySQL/game. First slice: **periodic or batched API sync** of exp/cash (and related fields) with a clear failure/retry story.
## Current state (`develop`)
- **HTTP stack is present**: `pr/api/base.sp`, `pr/api/utils.sp` included from `pointsreloaded.sp`; `_API_Init()` runs from `onplugin_start.sp`.
- **Player stats sync is not active**: `pr/api/player_stats.sp` exists but is **not `#include`d** in `pointsreloaded.sp`, so `API_UpdatePlayerStats` is **not compiled into the plugin** and is **never called**.
- **Deltas are already tracked in-game**: `g_iExpDelta`, `g_iCashDelta`, `g_iPillsDelta` (`global_variables.sp`, updated from `stat_variables.sp`).
- **Healthcheck**: `sm_api_healthcheck` → `API_GetHealthcheck()`; callback logic in `utils.sp` appears **inverted** (non-OK reported as OK).
- **`base.sp` transaction helpers are buggy**: wrong key when nesting transactions under steam id; `_API_GetTransactionData` has **inverted `HasKey` logic**; HTTP header typo **`Authorizaton`** instead of **`Authorization`**.
- **Secrets in source**: `BASE_URL` and bearer `ACCESS_TOKEN` are hardcoded in `base.sp` — should move to ConVars/env and token rotated if the repo is shared.
- **Build-time API** (separate concern): `.deploy/build.py` uses `PR_API_URL` / `PR_API_TOKEN` for `fetchDataFromAPI` (quest data); local fetch failure without env is expected and does not reflect in-game HTTP.
## Branches (for reference)
| Branch | Notes |
|--------|--------|
| `feature/api-config` | One commit ahead of an older base: **includes `player_stats.sp` + new `config.sp`** (GET `/config` → apply ConVars), fixes transaction map, `Authorization`, healthcheck, **PATCH** `/players/{steamid}/stats`, zero deltas on send, pending-transaction guard. **Behind current `develop`** — needs merge/rebase. |
| `feature/api-integration` | Only SMX/gitignore churn; **no substantive API work**. |
| `origin/feature/api-migration` | Older **parallel** prototype (not ancestor of `develop`); similar files but not the source of truth for current tree. |
## Proposed work items
1. **Land API fixes and wiring**
- Merge or cherry-pick from `feature/api-config` (or reapply): transaction fixes, correct auth header, healthcheck, PATCH path/method aligned with Phoenix API contract.
- **`#include "pr/api/player_stats.sp"`** in `pointsreloaded.sp` once the above is consistent.
2. **Define sync policy**
- Add **timer-based** and/or **critical-event** calls to `API_UpdatePlayerStats` (e.g. every N seconds, on disconnect, map end — product decision).
- Confirm API expects **PATCH** vs POST and exact path (`/internal/...` vs relative to HTTPClient base).
3. **Configuration & security**
- Replace hardcoded URL/token with **ConVars** (or server env read at startup) matching deploy patterns; **rotate** any token that lived in git history.
4. **Optional: remote config**
- If still desired, port **`pr/api/config.sp`** from `feature/api-config` (`API_FetchConfig`, admin refresh command).
5. **Verification**
- Rebuild with `docker compose up --build`; exercise healthcheck and a test stats sync against staging API.
## Related context
- Long-term: web “buy” flows need server-side truth; this ticket is the **first server→API push** for exp/cash deltas.
issue