Player Domain¶
User accounts, the in-game Player row, the first-login onboarding flow, teams, reputation, and messaging.
User¶
Source: services/gameserver/src/models/user.py
Purpose: Authentication-layer account. One User may own one Player (game state) and/or AdminCredentials. Subscription / billing flags live here.
Fields:
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| username | String(50) | unique, not null | |
| String(255) | unique, nullable | optional | |
| is_active | Boolean | default true | |
| is_admin | Boolean | default false | |
| last_login | DateTime | nullable | |
| deleted | Boolean | default false | soft delete |
| paypal_subscription_id, subscription_tier, subscription_status | String | nullable | galactic_citizen etc. |
| subscription_started_at, subscription_expires_at | TIMESTAMP | nullable |
Relationships:
- player (1:1, cascade), admin_credentials (1:1, cascade), player_credentials (1:1, cascade), mfa_secret (1:1, cascade).
- oauth_accounts, refresh_tokens, mfa_attempts (1:many).
- owned_regions → Region.
Player¶
Source: services/gameserver/src/models/player.py
Purpose: In-game state for a user — credits, turns, reputation snapshot, location, ship pointer, ARIA AI counters, and regional citizenship.
Fields:
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| user_id | UUID FK users.id | unique, not null, CASCADE | 1:1 with User |
| nickname | String(50) | nullable | optional in-game name |
| credits | Integer | default 10000 | |
| turns | Integer | default 1000 | |
| reputation | JSONB | default {} | per-faction reputation snapshot |
| personal_reputation | Integer | default 0 | -1000..+1000 alignment (migration fe22441146b1) |
| reputation_tier | String(50) | default Neutral |
cached tier name |
| name_color | String(20) | default #FFFFFF |
UI color cache |
| military_rank | String(50) | default Recruit |
rank progression |
| rank_points | Integer | default 0 | |
| aria_bonus_multiplier | Float | default 1.0 | 1.0-1.5 (migration f4a5b6c7d8e9) |
| aria_consciousness_level | Integer | default 1 | 1-5 |
| aria_relationship_score | Integer | default 25 | 0-100 |
| aria_total_interactions | Integer | default 0 | |
| current_ship_id | UUID FK ships.id | nullable, SET NULL | |
| home_sector_id, current_sector_id | Integer | default 1 | integer sector numbers |
| is_docked | Boolean | default false | |
| current_port_id | UUID FK stations.id | nullable, SET NULL | station player is docked at (migration 5f5a988bdbb1); FK targets stations |
| is_landed | Boolean | default false | |
| current_planet_id | UUID FK planets.id | nullable, SET NULL | |
| team_id | UUID FK teams.id | nullable, SET NULL | |
| attack_drones, defense_drones, mines, genesis_devices | Integer | defaults 0 | aggregated counters |
| insurance | JSONB | nullable | |
| last_game_login | DateTime | nullable | distinct from User.last_login |
| turn_reset_at | DateTime | nullable | |
| settings | JSONB | default {} | UI / language / audio / accessibility / privacy / notifications / active bounties — full shape in jsonb-schema.md#playersettings |
| first_login | JSONB | default | quick flag, separate from FirstLoginSession trail |
| is_active | Boolean | default true | in-game deactivation |
| home_region_id, current_region_id | UUID FK regions.id | nullable | |
| is_galactic_citizen | Boolean | default false | unlocks cross-region travel |
Relationships:
- user → User.
- ships → Ship (1:many, FK Ship.owner_id); current_ship → Ship (FK current_ship_id, post-update).
- team → Team (FK team_id); team_membership → TeamMember (1:1).
- faction_reputations → Reputation (1:many).
- planets (many-to-many via player_planets), stations (many-to-many via player_stations).
- discovered_sectors → Sector.
- genesis_devices → GenesisDevice (1:many — note: this shadows the integer counter genesis_devices defined on the same class earlier; the relationship wins at runtime).
- combat_logs_as_attacker, combat_logs_as_defender → CombatLog.
- created_warp_tunnels → WarpTunnel.
- market_transactions → resource.MarketTransaction (resource-enum table); enhanced_market_transactions → market_transaction.MarketTransaction (commodity-string table).
- first_login_sessions (1:many), first_login_state (1:1).
- regional_memberships → RegionalMembership; inter_regional_travels → InterRegionalTravel.
- AI: trading_profile, ai_recommendations, aria_memories, aria_market_intelligence, aria_exploration_map, aria_trading_patterns, ai_assistant.
- commanded_fleets → Fleet; fleet_memberships → FleetMember.
- drones → Drone; drone_deployments → DroneDeployment.
Note: the genesis_devices name is overloaded (integer column + relationship). In practice the relationship overwrites the column attribute. The integer counter is still backed by the database column; access via Player.__table__.c.genesis_devices if you need it.
FirstLoginSession + Friends¶
Source: services/gameserver/src/models/first_login.py
Purpose: Captures the AI-driven onboarding dialog where the player tries to claim a starter ship from a guard; logs negotiation outcomes and drives starting state.
FirstLoginSession¶
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| player_id | UUID FK players.id | not null, CASCADE | |
| started_at | DateTime | server default now | |
| completed_at | DateTime | nullable | |
| ai_service_used | Boolean | default false | |
| fallback_to_rules | Boolean | default false | |
| guard_name, guard_title, guard_trait, guard_description | String | nullable | personality bundle (migration ec92f8afd44a) |
| guard_base_suspicion | Float | nullable | |
| ship_claimed | Enum ship_choice |
nullable | what player tried to claim |
| extracted_player_name | String | nullable | |
| negotiation_skill | Enum negotiation_skill_level |
nullable | WEAK/AVERAGE/STRONG |
| final_persuasion_score | Float | nullable | |
| outcome | Enum dialogue_outcome |
nullable | SUCCESS/PARTIAL_SUCCESS/FAILURE |
| awarded_ship | Enum awarded_ship_type |
nullable | |
| starting_credits | Integer | nullable | |
| negotiation_bonus_flag, notoriety_penalty | Boolean | nullable | |
| client_info, performance_metrics | JSONB | nullable |
Relationships: player, dialogue_exchanges (1:many cascade), ship_options (1:1 cascade).
DialogueExchange¶
Per-turn record of the negotiation. Key columns: session_id (FK), sequence_number, npc_prompt, player_response, topic, persuasiveness, confidence, consistency, key_extracted_info JSONB, detected_contradictions ARRAY(String). AI logging fields (migration 6acc65ee7a72): ai_provider, ai_system_prompt, ai_user_prompt, ai_raw_response, believability, current_suspicion, response_time_ms, estimated_cost_usd, tokens_used.
ShipPresentationOptions¶
Per-session ship offering. Columns: session_id FK, available_ships ARRAY(String), escape_pod_present (default true), rarity_roll (0-100), special_event_active, seed_value.
ShipRarityConfig¶
Static config: ship_type (unique), rarity_tier (1-5), spawn_chance (0-100), base_credits, and three persuasion thresholds (weak_threshold, average_threshold, strong_threshold). Several migrations rebalance these (2e78250f47bc, 6b1d95a38c98, c5e32c313020).
PlayerFirstLoginState¶
Tracks completion across sessions. Columns: player_id (unique FK), has_completed_first_login, current_session_id (FK), attempts, last_attempt_at, completion bools (claimed_ship, answered_questions, received_resources, tutorial_started), and history arrays previous_ship_claims, previous_dialogue_strategies.
Team¶
Source: services/gameserver/src/models/team.py
Purpose: Player alliance with shared treasury, sector claims, and reputation aggregation policy.
Fields:
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| name | String(80) | unique, not null | |
| description | Text | nullable | |
| leader_id | UUID | nullable | not a FK constraint; resolved via Player.team_id and the leader check |
| reputation_calculation_method | String(20) | default AVERAGE |
AVERAGE/LOWEST/LEADER |
| tag | String(10) | nullable | display tag |
| logo | String | nullable | URL |
| is_public | Boolean | default true | |
| max_members | Integer | default 4 | |
| sector_claims | ARRAY(Integer) | default [] | claimed sector numbers |
| home_sector_id | Integer | nullable | |
| recruitment_status | String(20) | default OPEN |
OPEN/INVITE_ONLY/CLOSED |
| treasury_credits, treasury_fuel, treasury_organics, treasury_equipment, treasury_technology, treasury_luxury_items, treasury_precious_metals, treasury_raw_materials, treasury_plasma, treasury_bio_samples, treasury_dark_matter, treasury_quantum_crystals | Integer | default 0 | shared treasury per resource |
| total_credits, total_planets | Integer | default 0 | aggregates |
| combat_rating, trade_rating | Float | default 0.0 | |
| join_requirements, member_roles, resource_sharing, invitation_codes | JSONB | defaults |
Relationships:
- members → Player (1:many via Player.team_id).
- team_members → TeamMember (1:many cascade) — adds roles/permissions on top of plain membership.
- reputation → TeamReputation (1:1 cascade).
- controlled_sectors → Sector.
- drones, fleets, messages.
TeamMember¶
Per-member roles/permissions. Columns: team_id FK, player_id FK, role (LEADER/OFFICER/MEMBER/RECRUIT), joined_at, permissions JSONB, individual booleans can_invite, can_kick, can_manage_treasury, can_manage_missions, can_manage_alliances, last_active, contribution_credits JSONB.
Reputation¶
Source: services/gameserver/src/models/reputation.py
Purpose: Per-(player, faction) reputation row with a 17-tier enum and effects flags.
Fields:
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| player_id | UUID FK players.id | not null, CASCADE | |
| faction_id | UUID FK factions.id | not null, CASCADE | |
| current_value | Integer | default 0 | numeric score |
| current_level | Enum reputation_level |
default NEUTRAL | 17 tiers from PUBLIC_ENEMY (-8) to EXALTED (+8) |
| title | String(50) | default Neutral |
display |
| decay_paused | Boolean | default false | |
| history | JSONB | default [] | |
| trade_modifier | Float | default 0 | |
| mission_availability | JSONB | default [] | |
| port_access_level | Integer | default 0 | |
| combat_response | String(50) | default neutral |
|
| is_locked | Boolean | default false | admin lock |
| lock_reason, lock_expires, special_status | mixed | nullable |
Relationships: player, faction.
TeamReputation¶
Aggregated team reputation. Columns: team_id (unique FK), calculation_method (AVERAGE/LOWEST/LEADER), faction_reputation JSONB, history JSONB, last_recalculated, next_recalculation, pending_notifications JSONB.
Message¶
Source: services/gameserver/src/models/message.py
Purpose: Player-to-player and team messaging with threading and moderation.
Fields:
| name | type | constraints | notes |
|---|---|---|---|
| id | UUID | PK | |
| sender_id | UUID FK players.id | not null, indexed | |
| recipient_id | UUID FK players.id | nullable, indexed | null for team messages |
| team_id | UUID FK teams.id | nullable, indexed | null for direct messages |
| subject | String(255) | nullable | |
| content | Text | not null | |
| sent_at | DateTime | default utcnow, indexed | |
| read_at | DateTime | nullable | |
| deleted_by_sender, deleted_by_recipient | Boolean | defaults false | soft delete per side |
| thread_id | UUID | indexed | conversation grouping |
| reply_to_id | UUID FK messages.id | nullable | direct reply |
| message_type | String(20) | default player |
player/team/system |
| priority | String(10) | default normal |
low/normal/high/urgent |
| flagged | Boolean | default false | |
| flagged_reason | String(255) | nullable | |
| moderated_at | DateTime | nullable | |
| moderated_by | UUID FK users.id | nullable | admin user |
Relationships: sender, recipient, team, reply_to (self-ref), moderator (User).
Composite indexes: (recipient_id, read_at), (team_id, sent_at), (thread_id, sent_at).
Auth side-tables (referenced)¶
PlayerCredentials, AdminCredentials (see ./admin.md), OAuthAccount, RefreshToken, MFASecret, MFAAttempt all hang off User 1:1 or 1:many. They are mechanical auth plumbing — no game logic — and not expanded here.