Part of #796 — Gamify: editor half. Pairs with qtmesh-cloud#80.
Goal
Give the editor a reliable, offline-tolerant way to send gamification events to the account and read back stats — built on the existing cloud session, not a parallel stack.
Work
- Reuse
QtMeshCloudSession / QtMeshCloudClient and the existing credential store (CloudCredentialStore) + device-flow auth. No new auth.
- Add a persistent event queue (
GamificationEventQueue): append-only local store (e.g. JSON/SQLite in the app config dir) of pending events, each with a client-generated idempotency id. Survives restarts.
- Add client methods:
postEditorEvents(bearer, events[]) → POST /v1/events/editor (feature usage).
postOperationEvents(bearer, ops[]) → POST /v1/events/operations (outcomes; new cloud endpoint).
fetchStats(bearer) → GET /v1/me/stats → parsed {level, xp, streak, achievements, featureUsage, recentlyEarned}.
- Flush policy: batch every N minutes / on app idle / on graceful shutdown; exponential backoff on failure; drop nothing until acked. Cap queue size with FIFO eviction + a logged warning (no silent loss).
- Return newly-earned achievements from flush so E-P4 can toast them.
Acceptance criteria
Notes
- Keep the queue transport-agnostic so E-P2 (usage) and E-P3 (operations) just enqueue.
Part of #796 — Gamify: editor half. Pairs with qtmesh-cloud#80.
Goal
Give the editor a reliable, offline-tolerant way to send gamification events to the account and read back stats — built on the existing cloud session, not a parallel stack.
Work
QtMeshCloudSession/QtMeshCloudClientand the existing credential store (CloudCredentialStore) + device-flow auth. No new auth.GamificationEventQueue): append-only local store (e.g. JSON/SQLite in the app config dir) of pending events, each with a client-generated idempotency id. Survives restarts.postEditorEvents(bearer, events[])→POST /v1/events/editor(feature usage).postOperationEvents(bearer, ops[])→POST /v1/events/operations(outcomes; new cloud endpoint).fetchStats(bearer)→GET /v1/me/stats→ parsed{level, xp, streak, achievements, featureUsage, recentlyEarned}.Acceptance criteria
retryhints.fetchStatsparses into a typed struct with unit tests.Notes