Skip to content

Admin & Audit

Admin authentication is a side table on User; permissions are gated by User.is_admin plus the presence of AdminCredentials. There is no separate "permissions" table — granular flags live on the resource being administered (e.g., MarketTransaction.flagged_suspicious / reviewed_by, CombatLog.admin_resolved / admin_reviewed, Message.flagged / moderated_by, PriceAlert.acknowledged_by).


User (admin flag)

Source: services/gameserver/src/models/user.py

The is_admin: Boolean column on User is the master switch. See ./player.md for the full User schema. An admin user is identified by is_admin=True AND a populated AdminCredentials row.


AdminCredentials

Source: services/gameserver/src/models/admin_credentials.py

Purpose: Separate password hash for the admin login path, isolated from the OAuth/MFA flow used by ordinary users.

Fields:

name type constraints notes
user_id UUID FK users.id PK, CASCADE 1:1 with User
password_hash String(255) not null bcrypt/argon2
last_password_change DateTime server default now for rotation policy

Relationships: user (1:1, back-pop User.admin_credentials).


AuditLog

Source: services/gameserver/src/models/audit_log.py

Purpose: Catch-all request/audit trail emitted by middleware. Used for security/compliance review and admin search.

Fields:

name type constraints notes
id UUID PK
timestamp DateTime default utcnow, indexed
method String(10) not null HTTP verb
path String(255) not null, indexed
status_code Integer nullable
duration_ms Integer nullable
user_id UUID nullable, indexed no FK constraint (logs survive user deletes)
user_type String(20) nullable admin/player/anonymous
client_ip String(45) not null IPv6-safe
user_agent Text nullable
action String(100) indexed login/logout/economy_intervention/…
resource_type String(50) nullable auth/ship/economy/message/…
resource_id UUID nullable affected resource id
query_params, request_body, security_flags JSON nullable request body should be sanitized of secrets
response_summary Text nullable
violation_detected String(100) nullable violation classifier

Relationships: none (deliberately decoupled — no FK).


Per-resource admin flags

Several entities carry inline admin / moderation columns rather than living in a centralized permissions table. These are the surfaces an admin UI hits:

Entity Admin columns Source
MarketTransaction (enhanced_market_transactions) admin_notes, flagged_suspicious, reviewed_by (FK users.id) market_transaction.py
CombatLog admin_notes, admin_resolved, admin_resolved_at, disputed, resolved, admin_reviewed combat_log.py
Message flagged, flagged_reason, moderated_at, moderated_by (FK users.id) message.py
PriceAlert acknowledged_by (FK users.id), acknowledged_at, resolved_at market_transaction.py
Reputation is_locked, lock_reason, lock_expires, special_status reputation.py

Indexes on audit_logs.timestamp, audit_logs.path, audit_logs.user_id, and audit_logs.action cover the common admin-search queries. Composite indexes for user-activity searches are defined inline.


Note on "admin permissions"

Permission gating is done in middleware/routes by checking User.is_admin and then per-route logic. There is no permissions table.