Domain Model¶
Who is this page for?
Integrators who need to know what each object means on the wire, and
contributors who need the schema. The canonical machine-readable ERD
(Mermaid) lives in docs/domain-model.md; this page is the prose
reference.
The big picture¶
GAME’s entities fall into five clusters. Solid arrows below read “parent → many children”:
AUTH / ACCESS CAMPAIGN HIERARCHY
┌──────────┐ ┌──────────┐
│OAuthUsers│◄──owns────► │ Games │──┬──► GameParams (key/value config)
└────┬─────┘ ┌────────►└────┬─────┘ └──► Tasks ──► TaskParams
│ │ │
▼ │ ▼
┌──────────┐ │ ┌──────────────┐
│ ApiKey │───┘ │UserGameConfig│ (enrolment + experiment group)
└────┬─────┘ └──────────────┘
│ audit trail: every entity records the ApiKey that created it
▼
PARTICIPATION & SCORING ECONOMY
┌──────────┐ ┌──────────┐
│ Users │──► UserActions │ Wallet │──► WalletTransactions
│ │──► UserInteractions └────▲─────┘
│ │──► UserPoints ◄──awards──┐ │ one wallet per user
│ │──────────────────────────┴───────┘
└──────────┘
STRATEGY OBSERVABILITY
┌────────────────────┐ ApiRequests · Logs · KpiMetrics
│ StrategyDefinition │──► versions UptimeLogs · StrategyExecutionLog
│ (custom DSL) │ AbuseLimitCounter · ExportAuditLog
└────────────────────┘
Core entities¶
Identity & access¶
Entity |
Meaning |
|---|---|
OAuthUsers |
A human/admin identity federated from Keycloak ( |
ApiKey |
A machine credential ( |
Campaign hierarchy¶
Entity |
Meaning |
|---|---|
Games |
A campaign/project. Carries an |
GameParams |
Key/value configuration attached to a game (e.g. base points). These feed strategy variables. |
Tasks |
A concrete activity inside a game ( |
TaskParams |
Key/value configuration attached to a task; overrides/extends game params for that task’s scoring. |
Participation & scoring¶
Entity |
Meaning |
|---|---|
Users |
A participant, keyed by your |
UserGameConfig |
A user’s enrolment in a game, including their |
UserActions |
An explicit event a user performed ( |
UserInteractions |
A typed interaction between a user and a task
( |
UserPoints |
The heart of the system: one row per award. Holds |
Economy¶
Entity |
Meaning |
|---|---|
Wallet |
Exactly one per user. Tracks |
WalletTransactions |
An append-only ledger of wallet movements ( |
Strategy & observability¶
Entity |
Meaning |
|---|---|
StrategyDefinition |
A custom, DSL-authored strategy and its versions. Saving a published
version creates a new |
StrategyExecutionLog |
A sampled trace of a custom-strategy run: status, latency, node count, case name, error code, and (bounded) node-by-node trace. Drives the observability dashboard. |
ApiRequests / Logs / KpiMetrics / UptimeLogs |
Operational telemetry: per-request records, structured application logs, daily KPI rollups, and uptime samples. |
AbuseLimitCounter |
Backing store for the database rate-limiter (scope, window, counter). See Security. |
ExportAuditLog |
Records data-export operations for compliance/audit. |
The BaseModel contract¶
Every persisted entity inherits a common base (app/model/base_model.py)
that contributes four columns to every table:
Column |
Type |
Notes |
|---|---|---|
|
|
Primary key, server-generated. |
|
|
Set on insert. Stored as timezone-aware UTC. |
|
|
Refreshed on update. |
|
FK / string |
The credential that performed the write - the audit + scoping anchor. |
Because apiKey_used is stamped on every write, GAME can answer “who
created this?” for any row and can scope reads so one API key only sees the
data it created (admins bypass scoping). See Security.
Identifiers: internal vs. external¶
GAME maintains a clean separation between its identifiers and yours:
Internal ids are
UUIDprimary keys (gameId,taskId,userId). They appear in URLs that address a specific record (/games/{gameId}/...).External ids are the strings you supply (
externalGameId,externalTaskId,externalUserId). They let you address records using your own domain keys and keep GAME loosely coupled to your system.
A common integration pattern: create a game and keep the returned
gameId; thereafter reference tasks and users by your external ids.
Idempotency & concurrency¶
Point assignment accepts an idempotency key (request header, surfaced into the event
dataaseventId). A repeated request with the same key does not create a secondUserPointsrow - safe to retry.Writes are transactional; wallet movement and points persistence happen together so a partial failure does not leave a points row without its wallet effect.
Where to go next¶
Integrating with GAME - the request/response shapes for creating games, tasks, and awarding points.
Strategies - how
strategyIdresolution and scoring actually work.Codebase Reference - the generated reference for
app/modeland the rest.