feat(scum): add local game player intelligence
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-28
|
||||
@@ -0,0 +1,57 @@
|
||||
## 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
|
||||
|
||||
1. **Use server-local game identity.** `game_player` is unique on `(server_instance_id, game_player_id)`; it has no foreign key to `user`. 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.
|
||||
|
||||
2. **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.
|
||||
|
||||
3. **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.
|
||||
|
||||
4. **Treat failures and anomalies as review evidence.** Failed login/connection event payloads create bounded `game_access_attempt` records. A threshold (five failures for the same fingerprint within fifteen minutes) creates or refreshes an `excessive-failed-access` signal; multiple player IDs sharing one server-local fingerprint create a `possible-alt-account` signal. 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.
|
||||
|
||||
5. **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
|
||||
|
||||
1. Add model-first tables and repositories; existing installations begin with no projected players.
|
||||
2. Deploy manifest schemas and Platform projection; only newly ingested declared events create records. Historical log backfill remains an explicit later operation.
|
||||
3. Deploy APIs and console page after backend authorization is available.
|
||||
4. 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.
|
||||
@@ -0,0 +1,23 @@
|
||||
## Why
|
||||
|
||||
SCUM login semantics are currently retained only as operational logs, so operators cannot safely review a local player's identity history, sessions, or suspicious access behavior. A server-scoped game-player projection turns declared SCUM login/logout events into reviewable evidence without conflating game identities with platform users or exposing network data.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a server-scoped local game-player domain with aliases, sessions, access attempts, and review-only security signals.
|
||||
- Project declared `scum.login` and `scum.logout` semantic log events idempotently, including duplicate, renamed-player, out-of-order, and session-boundary handling.
|
||||
- Derive a server-isolated irreversible network correlation fingerprint; do not persist raw IP addresses or raw fingerprints.
|
||||
- Add authenticated player-profile, aliases, access-trajectory, and security-signal APIs plus SCUM console contracts and records.
|
||||
- Define bounded retention and manual-review semantics for access evidence and risk signals.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `scum-game-player-intelligence`: Server-local SCUM player identities, event projection, privacy-preserving access evidence, and review-only risk signals.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects Platform domain/model/repository/service/API/validation layers and durable metadata storage.
|
||||
- Affects the SCUM plugin semantic-event schemas and page declaration, plus Platform Web API contracts, routing, and shared-console records.
|
||||
- Adds no Platform account authentication, direct game-database access, raw network data, automatic moderation, Run protocol, or host/executor data exposure.
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Server-local game-player identity
|
||||
The system SHALL maintain a game-player identity independently of platform users, uniquely scoped by `serverInstanceId` and immutable game-player ID, with bounded display-name alias history.
|
||||
|
||||
#### Scenario: A known game player logs in under a new name
|
||||
- **WHEN** a successful declared SCUM login contains an existing player ID and a different valid display name
|
||||
- **THEN** the system SHALL update the player's current display name and retain the previous and new names as server-local aliases
|
||||
|
||||
### Requirement: Idempotent semantic login/logout projection
|
||||
The system SHALL project accepted `scum.login` and `scum.logout` semantic events using a durable event identity and SHALL tolerate duplicate and out-of-order delivery without creating duplicate access evidence or regressing player state.
|
||||
|
||||
#### Scenario: A duplicate login event is received
|
||||
- **WHEN** the same accepted log stream sequence is ingested again
|
||||
- **THEN** the system SHALL return the normal duplicate acknowledgement and SHALL not create an additional session or alias record
|
||||
|
||||
#### Scenario: A stale logout arrives after a later login
|
||||
- **WHEN** a logout event is older than the player's latest successful login
|
||||
- **THEN** the system SHALL only close an eligible earlier open session and SHALL not overwrite the newer player last-seen state
|
||||
|
||||
### Requirement: Privacy-preserving access evidence
|
||||
The system SHALL persist no raw IP address, raw network fingerprint, host path, credential, or raw sensitive log content in game-player access records or browser-visible responses. Network correlation SHALL be derived as an irreversible value scoped to one server instance.
|
||||
|
||||
#### Scenario: An access event carries a source address
|
||||
- **WHEN** a SCUM event contains a source address or network identifier
|
||||
- **THEN** the system SHALL use it only to derive a server-isolated correlation value and SHALL omit the source value from stored models and API responses
|
||||
|
||||
### Requirement: Review-only risk signals
|
||||
The system SHALL create bounded security signals for thresholded failed access and possible shared-fingerprint identities, and SHALL expose them as manual-review evidence only.
|
||||
|
||||
#### Scenario: Repeated failed access crosses the threshold
|
||||
- **WHEN** five failed attempts with one server-local correlation value occur within fifteen minutes
|
||||
- **THEN** the system SHALL create or refresh an excessive-failed-access signal with an explicit textual review status and evidence count
|
||||
|
||||
#### Scenario: An operator reviews a signal
|
||||
- **WHEN** an authorized operator reads a player security signal
|
||||
- **THEN** the response SHALL contain no automated enforcement command, raw network identifier, or raw log line
|
||||
|
||||
### Requirement: Authorized player intelligence console
|
||||
The system SHALL provide server-authorized player profile, aliases, sessions, access-attempt, and security-signal responses through named contracts, and the SCUM console SHALL render labels and status text rather than relying only on color.
|
||||
|
||||
#### Scenario: An unauthorized user requests server player data
|
||||
- **WHEN** a platform session lacks read access to the requested server instance
|
||||
- **THEN** the player intelligence API SHALL deny access without revealing whether a game-player record exists
|
||||
|
||||
### Requirement: Bounded evidence retention
|
||||
The system SHALL retain access attempts and active security evidence for a bounded period, prune expired evidence during normal service operations, and keep independent player identity history intact.
|
||||
|
||||
#### Scenario: Evidence is older than the retention limit
|
||||
- **WHEN** a query or projection runs after an access attempt exceeds the retention period
|
||||
- **THEN** the system SHALL remove the expired attempt and any expired non-active signal evidence without deleting the game-player identity
|
||||
@@ -0,0 +1,21 @@
|
||||
## 1. Domain and persistence
|
||||
|
||||
- [x] 1.1 Add server-local game-player, alias, session, access-attempt, and security-signal domain/models, repositories, MySQL migration, memory/file stores, validation, and retention helpers.
|
||||
- [x] 1.2 Add idempotent SCUM login/logout and failed-access projection from accepted semantic log entries, including rename, duplicate, stale event, session boundary, isolated HMAC correlation, and review-only signal thresholds.
|
||||
- [x] 1.3 Add focused domain/service/repository tests for privacy, ordering, idempotency, access control, retention, aliases, sessions, and risk signals.
|
||||
|
||||
## 2. APIs and plugin contract
|
||||
|
||||
- [x] 2.1 Add named request/response DTOs, authorized handlers/routes, safe projections, and API tests for player profiles, lists, aliases, sessions, attempts, and signals.
|
||||
- [x] 2.2 Extend the SCUM manifest semantic schemas/page contract for bounded player intelligence and add plugin validation fixtures/tests.
|
||||
|
||||
## 3. SCUM console
|
||||
|
||||
- [x] 3.1 Add Platform Web API/client contracts and route resolution for the SCUM player intelligence work surface.
|
||||
- [x] 3.2 Render full-width shared-console player records, access trajectories, and manual-review signals with explicit text status and no raw network/log exposure.
|
||||
- [x] 3.3 Add frontend contract/component tests for safe rendering and status readability.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run strict OpenSpec validation and focused backend, plugin, and frontend test suites.
|
||||
- [ ] 4.2 Run `scripts/check-structure.sh`, stage only task files, commit on `main`, and push the configured remote.
|
||||
Reference in New Issue
Block a user