Rebuild SCUM plugin-owned data flow
This commit is contained in:
@@ -10,13 +10,32 @@ The SCUM plugin owns collection names such as `scum_users`, schemas, upsert keys
|
||||
|
||||
The generic record is scoped by `pluginId`, `serverInstanceId`, `collection`, and `key`, with an opaque JSON `value` and timestamps. The platform validates scope and authorization only. A page bridge exposes list/put/delete and atomic put/delete transaction methods to plugin bundles.
|
||||
|
||||
SCUM uses stable `scum_*` collection names in the Platform database. Game database versions do not become Platform branches: a new SCUM schema updates the plugin SQL, result schema, mappings, and parser declarations while preserving the normalized collection contract.
|
||||
|
||||
## SCUM Data Flow
|
||||
|
||||
1. The plugin declares v57 SQLite `sqlRef` assets, opaque collection row targets, config maps, and log parsers in its own versioned data pack.
|
||||
2. Platform dispatches the selected declared operation to Run; no browser or plugin supplies a machine path or SQL string at request time.
|
||||
3. Run returns structured rows; Platform applies only the declared collection, upsert keys, and column mapping before storing them in the scoped generic store.
|
||||
4. The SCUM page reads those collections through the generic bridge and applies all SCUM-specific presentation and gift logic locally.
|
||||
5. Gift delivery and activity commands use the existing generic Game Client Bridge queue exposed by the plugin-page host.
|
||||
1. The plugin declares SQLite `sqlRef` assets, automatic cadence, collection row targets, config maps, and log projections in its own data pack and manifest. `PRAGMA user_version` is diagnostic evidence, not a Platform version switch.
|
||||
2. When Run polls for work, Platform creates every due declared query before selecting the next job. This naturally follows the existing two-second polling channel and works without a UI or a new background daemon.
|
||||
3. Run executes the declared SQL asset and returns structured rows. Platform applies only the declared collection, key, mapping, merge/replace mode, and fixed values.
|
||||
4. Full snapshot targets delete records absent from a successful complete result. Merge targets preserve stdout presence fields while SQLite later adds profile, economy, squad, and coordinate facts.
|
||||
5. Durable stdout batches are evaluated against plugin-declared ordered regex steps. Named captures with the same name must agree across the sequence; the complete sequence emits one stable event value and resets its bounded per-stream state.
|
||||
6. The SCUM BattlEye declaration correlates `reported as player N` with `Player N SteamID (assumed)` by slot. Steam ID is the `scum_users` key; names are mutable display fields and are never identity keys.
|
||||
7. The presence policy reads the existing user before mutation. A missing record receives the new-player announcement. A record whose last login is inside ten minutes is updated at most once and receives no duplicate announcement. An older record receives the returning-player announcement.
|
||||
8. Announcement text and `#announce` command syntax belong to the SCUM plugin declaration. Platform only renders captured placeholders and queues the already-declared command through the existing Run channel.
|
||||
9. The SCUM page polls Platform collections for display freshness. It never dispatches SQLite queries and exposes no manual synchronization button.
|
||||
10. Gift delivery and activity commands use the existing generic Game Client Bridge queue exposed by the plugin-page host.
|
||||
|
||||
## Declared Cadences
|
||||
|
||||
- `scum.player.profile`, `scum.vehicles`, and `scum.positions`: 3 seconds.
|
||||
- `scum.squads` and `scum.squad-members`: 1800 seconds.
|
||||
- Flags, native event/task observations, and native timed-gift observations use plugin-owned slower cadences appropriate to those datasets.
|
||||
|
||||
Cadence is measured from the latest matching job attempt. A still-active matching query suppresses another job, and idempotency keys include the server, template, and cadence bucket.
|
||||
|
||||
## Real Data Evidence
|
||||
|
||||
The provided complete database is `/Users/tasia/Downloads/SCUM/SCUM.db`; the similarly named file under `Logs/` is empty. The complete database reports SQLite `user_version=57`, contains 162 tables, and passes `quick_check`. All nine packaged SQL files execute against it. The existing users query starts at `user_profile` and therefore misses one real account; it must start at `user` and left join optional profile/prisoner data so stdout-created Steam identities merge correctly.
|
||||
|
||||
## Compatibility
|
||||
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# SCUM Local Data Baseline - 2026-08-18
|
||||
|
||||
## Scope
|
||||
|
||||
This is redacted structural evidence from the user-authorized local SCUM download and legacy projects. It records no player names, Steam IDs, IP addresses, coordinates, credentials, or row bodies.
|
||||
|
||||
## Database
|
||||
|
||||
- `/Users/tasia/Downloads/SCUM/Logs/SCUM.db` is an empty zero-byte file and is not usable evidence.
|
||||
- `/Users/tasia/Downloads/SCUM/SCUM.db` is the complete database: SQLite `user_version=57`, 162 tables, `quick_check=ok`.
|
||||
- Aggregate rows: 74 accounts, 73 profiles, 72 prisoners, 7 squads, 18 squad members, 313 vehicles, 5 bases, 5 flags, 0 native event rounds, and 2 native timed-gift completion records.
|
||||
- All nine packaged v57 SQL assets execute against the complete database.
|
||||
- The account/profile cardinality proves that user extraction must start from `user` and left join the optional profile chain. Steam ID is the stable collection identity; profile ID, prisoner ID, and display name are attributes.
|
||||
- The current map query returns player, vehicle, base, and flag points and the observed coordinates fit the declared SCUM island bounds.
|
||||
|
||||
## Logs
|
||||
|
||||
- The download contains 568 UTF-16LE/LF log files across 19 filename prefixes. Filenames use a server-start timestamp and a file can continue growing for many hours; tailing therefore requires an offset cursor per file rather than a daily filename assumption.
|
||||
- Each file starts with a blank line and one `Game version:` metadata line that must not become a business event.
|
||||
- Login file logs contain single-line login/logout records with optional coordinates.
|
||||
- The user-supplied BattlEye `reported`, `connected`, `SteamID`, and GUID sequence is supervised process stdout and does not occur in the downloaded file logs. It requires a separate ordered stdout projection.
|
||||
|
||||
## Configuration
|
||||
|
||||
- The configuration directory contains `ServerSettings.ini`, list-based access files, `EconomyOverride.json`, `RaidTimes.json`, `Notifications.json`, and engine input/user settings.
|
||||
- `ServerSettings.ini` reports settings version 7 and contains hundreds of `scum.*` keys. Config reads and patches must preserve unknown keys rather than reconstructing the file from a short allowlist.
|
||||
|
||||
## Legacy Behavior
|
||||
|
||||
- The legacy robot continuously updated players and positions in the background and queued welcome text through the server command channel; browser presence was never the acquisition trigger.
|
||||
- Legacy welcome behavior distinguishes first registration from a returning player and suppresses rapid repeated observations. This change uses the explicitly requested ten-minute window.
|
||||
- The legacy implementation contains field-order mistakes in its user creation branch, so only its product behavior and stable field intent are reused, not its SQL/value assignments.
|
||||
@@ -4,11 +4,18 @@
|
||||
|
||||
The previous SCUM data implementation placed game-specific projections, gift rules, and browser callbacks in Platform. That couples every SCUM version change to Platform releases and makes the implementation larger than the required relay role.
|
||||
|
||||
The first rebuild still left collection acquisition behind a page-owned `同步 SCUM.db` action and did not consume supervised SCUM stdout. As a result, opening no UI means no users, squads, vehicles, or coordinates are collected, and a real BattlEye login cannot create a player or produce the expected welcome announcement.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Replace the recent SCUM direct-data and game-gift additions with a generic plugin data store and generic plugin-page data bridge.
|
||||
- Keep SCUM SQLite, configuration, and log access plugin-declared and dispatched through Platform to Run.
|
||||
- Put SCUM `scum_*` collection names, record shapes, gift catalog/grant behavior, map rendering inputs, and feature UI in the SCUM plugin package.
|
||||
- Let each plugin query template declare its own background cadence. Platform creates due jobs from the authenticated Run polling loop, so collection acquisition continues with every browser closed.
|
||||
- Add plugin-declared stdout sequence projections. Platform applies the declaration generically when durable Run log batches arrive; it does not hard-code BattlEye or SCUM line formats.
|
||||
- Use Steam ID as the canonical SCUM user key, merge stdout-created users with later SQLite enrichment, and replace complete snapshot collections so deleted squads, members, vehicles, flags, and map points do not remain forever.
|
||||
- Remove manual database synchronization controls. The plugin page periodically rereads Platform records only; it never initiates machine collection.
|
||||
- On an authentic completed login sequence, create a missing user immediately and queue the plugin-declared global new-player announcement. For an existing user, suppress duplicate logins inside ten minutes and otherwise queue the plugin-declared returning-player announcement.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
@@ -16,3 +23,6 @@ The previous SCUM data implementation placed game-specific projections, gift rul
|
||||
- The SCUM plugin can read and write its scoped platform collections for users, squads, activity, gifts, and map points through generic bridge calls.
|
||||
- Version-specific SQL/config/log declarations remain in the SCUM manifest and assets.
|
||||
- Existing generic lifecycle and machine-job dispatch behavior remains intact.
|
||||
- Player and vehicle coordinates are acquired every three seconds, while squad and squad-member snapshots are acquired every thirty minutes, without a browser request.
|
||||
- A supervised stdout BattlEye login creates or updates exactly one `scum_users` record and exactly one eligible announcement according to the ten-minute presence window.
|
||||
- The SCUM page contains no `同步 SCUM.db`, refresh-projection, or equivalent machine-collection button and never substitutes sample records.
|
||||
|
||||
@@ -33,3 +33,54 @@ SCUM machine SQLite, configuration, and log operations SHALL remain plugin-decla
|
||||
- **WHEN** Run completes a declared SQLite query with a structured `rows` result
|
||||
- **THEN** Platform uses only the plugin-declared collection, upsert keys, and column mappings to persist the rows
|
||||
- **AND** Platform does not branch on the game, query key, collection name, or row fields
|
||||
|
||||
### Requirement: Browser-Independent Automatic Collection
|
||||
Platform SHALL schedule plugin-declared collection queries from the authenticated Run work-poll path without requiring a browser, page load, or manual synchronization action.
|
||||
|
||||
#### Scenario: Coordinate templates become due
|
||||
- **WHEN** Run polls for work at least three seconds after the latest matching player, vehicle, or map-position query
|
||||
- **THEN** Platform queues the due plugin-declared SQLite query before selecting work
|
||||
- **AND** a still-active matching query prevents duplicate queued work
|
||||
|
||||
#### Scenario: Squad templates become due
|
||||
- **WHEN** Run polls for work at least thirty minutes after the latest matching squad or squad-member query
|
||||
- **THEN** Platform queues the due declared query
|
||||
- **AND** no page action or open browser is involved
|
||||
|
||||
#### Scenario: Complete snapshot removes absent records
|
||||
- **WHEN** a replace-mode query succeeds with a complete row set
|
||||
- **THEN** Platform upserts the returned mapped rows and deletes prior records in that scoped collection whose keys are absent
|
||||
- **AND** an empty successful snapshot clears the collection
|
||||
|
||||
### Requirement: Plugin-Declared Login Presence Projection
|
||||
Platform SHALL apply ordered plugin-declared log projections to durable Run log batches and SHALL NOT hard-code SCUM or BattlEye parsing rules in service code.
|
||||
|
||||
#### Scenario: New player completes the BattlEye login sequence
|
||||
- **WHEN** one supervised stdout stream reports a player name and slot and later reports the same slot's Steam ID within the declared line gap
|
||||
- **THEN** Platform creates the Steam-ID-keyed `scum_users` record immediately
|
||||
- **AND** records the login activity
|
||||
- **AND** queues exactly one plugin-declared global new-player announcement
|
||||
|
||||
#### Scenario: Existing player reconnects inside ten minutes
|
||||
- **WHEN** the same Steam ID completes another login sequence within ten minutes of its stored login observation
|
||||
- **THEN** Platform treats the player as already online
|
||||
- **AND** queues no additional welcome announcement
|
||||
|
||||
#### Scenario: Existing player returns after ten minutes
|
||||
- **WHEN** the same Steam ID completes a login sequence after the ten-minute window
|
||||
- **THEN** Platform updates the stored name and login observation
|
||||
- **AND** queues exactly one plugin-declared returning-player announcement
|
||||
|
||||
#### Scenario: Database enrichment follows stdout identity
|
||||
- **WHEN** a later SQLite user query returns the same Steam ID with profile, economy, squad, or coordinate fields
|
||||
- **THEN** Platform merges those fields into the stdout-created record
|
||||
- **AND** does not create a second user keyed by profile ID or display name
|
||||
|
||||
### Requirement: Read-Only Collection Page Loading
|
||||
The SCUM plugin page SHALL read Platform records automatically and SHALL NOT expose a control that dispatches machine collection.
|
||||
|
||||
#### Scenario: User opens a SCUM management page
|
||||
- **WHEN** any users, squads, activity, gifts, or map page is opened
|
||||
- **THEN** it reads only the relevant `scum_*` Platform collections and existing command/snapshot results
|
||||
- **AND** it periodically rereads Platform data for display freshness
|
||||
- **AND** it contains no `同步 SCUM.db`, projection refresh, audit, or sample-data action
|
||||
|
||||
@@ -7,3 +7,11 @@
|
||||
- [x] Rebuild the SCUM plugin page to use only generic collection bridge actions for users, squads, activity, gifts, and map points.
|
||||
- [x] Remove obsolete SCUM-specific Platform/frontend data and gift surfaces that conflict with plugin ownership.
|
||||
- [x] Add focused backend, plugin, and frontend tests; run structure and OpenSpec validation.
|
||||
- [x] Record redacted evidence from the downloaded v57 database, configuration directory, log directory, and legacy SCUM projects; correct the effective database path and canonical user identity.
|
||||
- [x] Extend the generic plugin query declaration with automatic cadence and merge/replace row-target semantics, and extend the manifest with ordered log projection plus presence/announcement declarations.
|
||||
- [x] Schedule due collection queries from authenticated Run work polling, suppress overlapping jobs, and make successful replace snapshots delete absent records including on empty results.
|
||||
- [x] Project supervised stdout login sequences into Steam-ID-keyed users and activity records, apply the ten-minute presence window, and queue plugin-declared global new/returning-player announcements without a UI session.
|
||||
- [x] Correct the SCUM user SQL to include account-only users, declare 3-second player/vehicle/position and 30-minute squad/member cadences, and preserve plugin-owned slower cadences for other observations.
|
||||
- [x] Remove page-owned query dispatch and all manual synchronization/reload controls; reread Platform collections automatically and merge users only by stable IDs.
|
||||
- [x] Remove unverified gift/activity count ceilings that are not imposed by the SCUM data contract, then update focused backend/plugin/frontend tests.
|
||||
- [x] Run focused and full verification, `scripts/check-structure.sh`, and `openspec validate rebuild-scum-plugin-owned-data --strict` before marking these tasks complete.
|
||||
|
||||
Reference in New Issue
Block a user