5.2 KiB
Context
Platform already receives sequenced, durable runtime log batches and has a game.scum manifest that declares scum.login and scum.logout schemas. Those entries are queryable as logs but are not durable player-domain records. The new projection must remain local to a server instance, be safe to invoke as part of log ingestion, and not make raw network data browser-visible or persistent.
Goals / Non-Goals
Goals:
- Persist independent game-player records keyed by server instance and SCUM player ID, with aliases, bounded sessions, access attempts, and review-only security signals.
- Project success login/logout semantics atomically and idempotently from accepted log entries, with sequence/event keys for duplicates and timestamp ordering for stale updates.
- Derive server-isolated correlation identifiers using an HMAC secret and a normalized source value, while retaining only the derived value.
- Offer permission-scoped, server-authorized management APIs and console records that never return IP values, raw source identifiers, secrets, raw log lines, or automatic enforcement controls.
- Retain access attempts and signals for a configurable bounded period and preserve player identity/session summaries after evidence expiry.
Non-Goals:
- Platform-user accounts, credentials, game database reads/writes, skill/attribute editing, gifts, map trails, or any automatic ban/kick/punishment.
- Changes to Run channels, direct host/socket/database access, or browser access to raw semantic log bodies.
Decisions
-
Use server-local game identity.
game_playeris unique on(server_instance_id, game_player_id); it has no foreign key touser. This prevents platform-console authentication from being mistaken for SCUM identity. An alias table records renamed display names with first/last-seen times.Alternative considered: use display name as the identifier. It cannot safely handle player renames or duplicate names.
-
Project only accepted SCUM semantic events in the ingestion transaction. The log sequence (
log_stream_id,seq) is the projection idempotency key. Login/open-session changes only apply when their event time is not older than the player's latest projected event; a logout closes the latest matching open session no later than its event time. Duplicate batches perform no second projection.Alternative considered: asynchronous parsing of raw log lines. It would duplicate declared parsing rules, complicate order guarantees, and retain unnecessary sensitive content.
-
Store only an HMAC-derived, server-scoped network correlation key. A server-specific HMAC domain separator plus a process secret produces the correlation key. The source is never saved in models, logs, DTOs, or signal evidence. A digest is useful only within the same server and cannot be compared across servers.
Alternative considered: hash the raw IP directly. Unsalted hashes are reversible for common address spaces and correlatable across servers.
-
Treat failures and anomalies as review evidence. Failed login/connection event payloads create bounded
game_access_attemptrecords. A threshold (five failures for the same fingerprint within fifteen minutes) creates or refreshes anexcessive-failed-accesssignal; multiple player IDs sharing one server-local fingerprint create apossible-alt-accountsignal. Signals include text status and evidence counts, and have no action API.Alternative considered: automatic moderation. It is excluded because heuristic evidence requires an operator review.
-
Use existing session authorization and console primitives. New endpoints use existing server read authorization. The frontend fetches named API contracts and renders an ordinary full-width shared table/record list with explicit status labels, never raw logs or a new page-local visual system.
Risks / Trade-offs
- [A plugin payload omits a usable player ID] → Ignore the event for projection and retain normal log ingestion; validate only bounded known fields.
- [Late logout arrives after another login] → Close only a compatible open session whose start is no later than logout; never regress
lastSeenAt. - [Projection failure follows log body append] → Return the ingest error and retry the acknowledged range safely; event identity prevents duplicate records.
- [HMAC secret rotates] → Derived keys intentionally cease correlating across rotations; raw data is never recoverable. Deployment config keeps the secret stable during its intended retention window.
- [Evidence tables grow] → Perform retention pruning during projection/query and cap query limits.
Migration Plan
- Add model-first tables and repositories; existing installations begin with no projected players.
- Deploy manifest schemas and Platform projection; only newly ingested declared events create records. Historical log backfill remains an explicit later operation.
- Deploy APIs and console page after backend authorization is available.
- Rollback by disabling the page and projection. Existing records contain no raw network data and can expire through normal retention cleanup.
Open Questions
None. Initial thresholds and retention are conservative constants covered by tests and can become declared policy in a later change.