Rebuild SCUM plugin data ownership

This commit is contained in:
npc0-hue
2026-08-14 10:03:58 +08:00
parent c8b49c711c
commit a6c4cdac5d
79 changed files with 532 additions and 1842 deletions
@@ -1,28 +0,0 @@
## Context
`scum_new_web` and `scum_robot` establish the useful operator shape: players can be searched and narrowed by squad, squads expose their rosters, maps use layers and marker inspection, and gifts distinguish definitions from a player's receipt history. The existing browser repository already has typed SCUM observations and gift workflows, so the design extends those contracts instead of importing the old direct-access path.
## Decisions
### Projection views compose existing facts
The frontend reads users, squads, squad members, vehicles, flags, map points, observed timed-gift events, and platform gift APIs. It joins those responses only for display. A user action creates existing typed operations or gift grants; it never mutates a projection in the browser.
### Plugin data packs own version-sensitive game data
The SCUM manifest names a v57 gift-item catalog and map geometry data asset. The platform resolves a requested gift item through the installed server plugin and game version. Updating SCUM changes the plugin package, not platform code.
### Observed events have a distinct target table
`finished_timed_gift_spawner` represents a completed in-game timed-gift event. It is stored as `scum_gift_events`; `game_gift_catalogs`, revisions, and grants remain platform-owned operational data. This removes the ambiguous old `scum_gift_catalogs` observation table.
### Map is geometric, not a copied game asset
The plugin supplies world bounds and axis direction. The web client projects points into that normalized frame and exposes player, vehicle, base, and flag layers. No copyrighted tile bundle is copied. Trajectory playback remains dependent on independently collected track points.
## Verification
- Go tests covering observed-gift target and plugin-resolved gift items.
- Plugin typecheck, tests, and manifest validation.
- Frontend typecheck, tests, and build.
- `scripts/check-structure.sh` and `openspec validate align-scum-operations-with-reference-tools --strict`.
@@ -1,23 +0,0 @@
## Why
The SCUM projection pipeline now reads real v57 facts, but the five SCUM pages still present those facts as disconnected tables. The established `scum_new_web` and `scum_robot` tools have useful operator workflows for player search, squad rosters, map overlays, and gifts. Their direct database, FTP, and SQL-transport design does not fit this platform.
## What Changes
- Turn SCUM users into a searchable, squad-filterable projection view with player details and typed-operation entry points.
- Show each squad with its linked roster and flags rather than a disconnected aggregate table.
- Render current player, vehicle, base, and flag points in a versioned plugin-declared coordinate frame with independent layers and a selected-marker inspector.
- Separate game-observed completed timed-gift events from platform-owned gift definitions, revisions, and grants.
- Move SCUM gift item catalogs and map geometry out of platform code into versioned SCUM plugin data packs.
## Boundaries
- Platform remains the durable owner of projections, gift definitions, revisions, and grants; the plugin owns version-specific SQL, item keys, and map geometry; Run only executes declared work.
- Do not reintroduce FTP, direct platform/browser access to `SCUM.db`, arbitrary SQL, raw RCON, host paths, or a `run/` source tree.
- Do not copy third-party map tiles into this repository. The map is an operator coordinate board until a plugin-declared asset reference is available.
## Impact
- `platform/`: separates observed timed-gift events from platform gift catalog data and resolves gift item definitions from the registered plugin.
- `platform_web/`: adds projection-oriented user, squad, map, and gift views within the existing themed console.
- `plugins/examples/scum-server-plugin/`: declares SCUM v57 gift items and map geometry as versioned data-pack assets.
@@ -1,33 +0,0 @@
## ADDED Requirements
### Requirement: Reference-aligned SCUM projection workspaces
The system SHALL present SCUM users, squads, map points, and gifts as connected operator workspaces backed by platform projections and typed workflows.
#### Scenario: Operator filters users by squad
- **WHEN** an operator searches or selects a squad in the SCUM users workspace
- **THEN** the page filters real local player projections by the selected name, Steam identifier, or squad without querying `SCUM.db` from the browser
#### Scenario: Operator inspects a squad
- **WHEN** an operator selects a squad
- **THEN** the page shows its observed members, leader markers, and related flag observations without fabricating missing values
### Requirement: Plugin-declared SCUM map geometry
The system SHALL use SCUM plugin package geometry to project current map-point overlays.
#### Scenario: Operator changes map layers
- **WHEN** an operator enables or disables players, vehicles, bases, or flags
- **THEN** the map renders only the selected real projection classes using the installed plugin's declared coordinate frame
### Requirement: Distinct observed and operational gifts
The system SHALL keep observed SCUM timed-gift completion events separate from platform-owned gift definitions and grant state.
#### Scenario: Operator opens gifts
- **WHEN** an operator opens SCUM gift management
- **THEN** the workspace distinguishes platform gift definitions and grants from completed in-game timed-gift observations
### Requirement: Versioned plugin game data
The system SHALL resolve SCUM gift item definitions from versioned plugin package data.
#### Scenario: SCUM version changes
- **WHEN** the server uses a plugin package with a different declared SCUM item catalog
- **THEN** gift validation uses that plugin package data without changing platform source code
@@ -1,12 +0,0 @@
## 1. Reference-Aligned SCUM Operations
- [x] 1.1 Positive prompt: Deliver practical SCUM user, squad, map, and gift operations shaped by the mature reference tools while retaining the current plugin/platform/Run ownership model.
- [x] 1.2 Directional prompt: Update `platform/`, `platform_web/`, and the SCUM plugin package using existing projection, gift, manifest, and themed-console patterns; verify backend, frontend, plugin, structure, and OpenSpec checks.
- [x] 1.3 Boundary prompt: Do not reintroduce direct SQLite/FTP/browser SQL access, raw RCON, host paths, copied map tiles, unrelated product areas, or a `run/` tree.
- [x] 1.4 Separate observed timed-gift completion events from platform gift catalog/revision/grant records.
- [x] 1.5 Resolve SCUM gift item definitions and map geometry from the versioned installed plugin package.
- [x] 1.6 Implement searchable player and squad-filtered user projections plus roster/flag-aware squad detail.
- [x] 1.7 Implement layered projection map with plugin-declared coordinate conversion and marker inspection.
- [x] 1.8 Implement a gift workspace that clearly separates definitions/grants from observed completed timed-gift events.
- [x] 1.9 Add focused tests and run the required validation suite.
- [x] 1.10 Stage only task files, commit on `main`, and push the configured remote after verification succeeds.
@@ -1,2 +0,0 @@
schema: spec-driven
created: 2026-08-13
@@ -1,57 +0,0 @@
## Context
SCUM database schema, log grammar, and configuration files change with the game. The present Platform implementation identifies SCUM row types from query-key substrings and shapes data into fixed projection structs. That puts version-specific knowledge in the wrong component and forces a Platform update for routine game changes.
The supplied SCUM v57 sample confirms the required real sources: SQLite tables (`user_profile`, `prisoner`, `squad`, `squad_member`, `vehicle_spawner`, `base`, timed gifts/tasks), UTF-16LE server logs, and INI/JSON configuration. Platform needs durable, queryable `scum_*` records; Run remains an independent generic executor and is not changed in this repository.
## Goals / Non-Goals
**Goals:**
- Package SCUM v57 SQL, log grammar, and configuration mappings with the SCUM plugin.
- Make manifest validation accept safe package-relative SQL references and declarative row destinations while rejecting browser-provided or inline SQL.
- Make Platform ingest typed result rows through declaration metadata and upsert relational `scum_*` tables without SCUM query-name dispatch.
- Provide users, squads, activity, gifts, and map data to the management console from those persisted tables.
**Non-Goals:**
- Adding a `run/` tree, implementing Run-side executors, or adding SCUM game details to Run.
- Parsing a SCUM database from the browser or exposing host paths/raw SQL to browser users.
- Supporting every historical SCUM database version in the initial pack, changing lifecycle management, or adding unrelated product areas.
## Decisions
### Plugin package owns version-specific declarations
Each SCUM query template declares a package-relative `sqlRef`, `targetTable`, `upsertKeys`, and optional column mapping. SQL source is a `.sql` package asset named for SCUM database version. Logs/configuration use package assets with explicit encoding/format metadata.
This gives a SCUM version update one editable location: the plugin package. Inline SQL remains invalid so the browser continues to request only named templates and typed parameters. Storing SQL in Platform would reproduce the current coupling; accepting arbitrary browser SQL would make the contract unauditable.
### Platform performs generic declaration-driven ingestion
The execution path resolves a registered plugin declaration, validates the reported columns/keys, and applies its rows to the named `scum_*` relation. The generic layer never infers destination type by matching `player`, `squad`, or other SCUM words in a query key.
Tables are deliberately shaped for the first console features: sync runs, users, squads, squad members, vehicles, flags, map points, activity events, gift catalogs/grants, and configuration files. A generic JSON payload retains plugin-version fields not promoted to columns, avoiding a Platform release for every added SCUM field.
### APIs and console read persisted projections only
Platform dataset endpoints list scoped persisted rows. The console renders the five requested real datasets and uses empty states until a sync exists; it does not invent demo state or query SQLite directly.
## Risks / Trade-offs
- [SCUM schema drift invalidates a SQL asset] -> Version the asset directory, identify its schema version in the plugin manifest, and return a typed sync error rather than corrupting a table.
- [A mapping declares an unexpected relation] -> Manifest validation limits targets to `scum_*`, validates relative asset paths, key names, and declared columns before plugin registration.
- [Initial normalized tables omit a future game field] -> Preserve unmapped source values in row payload JSON and add columns only when they become a first-class console field.
- [Existing fixed projections have callers] -> Retain compatibility responses while migrating callers, then remove string-key dispatch in the same change after tests cover declaration-driven ingestion.
## Migration Plan
1. Register the new manifest schema and v57 package assets alongside existing declarations.
2. Add relational `scum_*` repository models/migrations and generic ingest APIs.
3. Switch SCUM sync result handling and console APIs to the declarations.
4. Verify against fixture rows derived from the supplied SCUM v57 database/log/config corpus.
5. Roll back by deploying the previous Platform and plugin version; existing `scum_*` rows are additive and can be ignored by the old runtime.
## Open Questions
- The first pack uses `pragma user_version = 57`; future versions will be added as plugin package assets when their actual schema is supplied.
@@ -1,29 +0,0 @@
## Why
The current SCUM integration keeps game-version SQL and data-shaping knowledge in Platform projections, which makes a SCUM update require coordinated changes across components. The management console needs to operate on actual SCUM v57 users, squads, activity, gifts, and map data with game-specific knowledge packaged alongside the SCUM plugin.
## What Changes
- Add a plugin-packaged SCUM data plane: versioned SQL files, log parser definitions, and configuration mappings referenced from the plugin manifest.
- Let Platform validate and distribute those declarations, accept typed result rows, and persist them in relational `scum_*` tables without dispatching on SCUM query-name substrings.
- Expose persisted SCUM user, squad, activity, gift, and map datasets through Platform APIs and the first-party game operations console.
- Replace the old hard-coded SCUM projection pathway with declaration-driven target-table and upsert metadata.
- **BREAKING** Plugin query-template declarations gain package-relative SQL references and row-target metadata; inline SQL remains invalid.
## Capabilities
### New Capabilities
- `scum-direct-data-plane`: Plugin-owned versioned SCUM data declarations, generic Platform ingestion, and `scum_*` persistence.
- `scum-operations-console`: First-party views and APIs for persisted SCUM users, squads, activity, gifts, and map points.
### Modified Capabilities
<!-- None. -->
## Impact
- `plugins/`: SCUM manifest/schema/validator/tests and versioned SQL, log, and config packages.
- `platform/`: plugin contracts, generic ingest service, relational repository models/migrations, and SCUM dataset APIs.
- `platform_web/`: server management SCUM data views using existing themed console conventions.
- No `run/` source is added; Run continues to perform only generic plugin-declared SQL and file jobs supplied by Platform.
@@ -1,31 +0,0 @@
## ADDED Requirements
### Requirement: Plugin-declared SCUM data packs
The system SHALL allow a SCUM plugin manifest to reference package-relative versioned SQL, log parser, and configuration mapping assets. Every query declaration that produces persisted SCUM rows MUST declare a `scum_*` target table and non-empty upsert keys; inline SQL and browser-supplied SQL MUST be rejected.
#### Scenario: v57 query declaration resolves a packaged statement
- **WHEN** the SCUM v57 plugin package declares a query with a relative `.sql` reference and row-target metadata
- **THEN** manifest validation accepts the declaration and distribution includes the referenced asset
#### Scenario: inline statement is rejected
- **WHEN** a manifest contains SQL text instead of a package-relative SQL reference
- **THEN** manifest validation rejects the manifest with a declaration error
### Requirement: Generic SCUM row ingestion
The system SHALL ingest rows returned for a registered SCUM data template according to that template's declared target table, upsert keys, and column mappings, without routing by a query-key substring.
#### Scenario: user rows are ingested
- **WHEN** a registered user template returns rows containing its declared key and columns
- **THEN** Platform upserts those rows into `scum_users` and records their plugin payload
#### Scenario: unsupported row target is rejected
- **WHEN** a registered data template names a target outside the allowed `scum_*` tables
- **THEN** Platform rejects the result before any dataset row is written
### Requirement: SCUM v57 source coverage
The initial SCUM pack SHALL include data declarations for users, squads and members, activity, gifts, and map points, plus parser/mapping declarations for supplied SCUM logs and configuration formats.
#### Scenario: operators inspect supplied source families
- **WHEN** the SCUM plugin package is assembled for database version 57
- **THEN** it contains SQL assets and declarations for all five console datasets and log/config parser assets
@@ -1,19 +0,0 @@
## ADDED Requirements
### Requirement: Persisted SCUM operations datasets
The system SHALL expose persisted SCUM users, squads, activity events, gifts, and map points through Platform APIs scoped to a server instance.
#### Scenario: a completed sync is queried
- **WHEN** an operator requests a SCUM dataset for an instance with persisted records
- **THEN** Platform returns only the corresponding persisted `scum_*` rows for that instance
### Requirement: SCUM operations console views
The first-party management console SHALL provide themed views for 用户, 队伍, 活动, 礼包, and 地图 using Platform's persisted SCUM dataset APIs, with an explicit empty state when no sync has completed.
#### Scenario: data is available
- **WHEN** an operator opens a SCUM-enabled server after a data sync
- **THEN** the console displays the returned persisted dataset without browser-side SQLite or log access
#### Scenario: no data is available
- **WHEN** an operator opens a SCUM-enabled server with no completed data sync
- **THEN** each dataset view displays an empty state rather than synthetic records
@@ -1,20 +0,0 @@
## 1. Plugin Data Pack
- [x] 1.1 Extend plugin manifest schema and validator with package-relative SQL references and declared SCUM row targets, keys, and mappings.
- [x] 1.2 Add tested SCUM v57 SQL assets for users, squads/members, activity, gifts, and map data.
- [x] 1.3 Add plugin-declared UTF-16LE log parser and INI/JSON configuration mapping assets for the supplied SCUM formats.
## 2. Platform Data Plane
- [x] 2.1 Replace SCUM query-key projection dispatch with declaration-driven row ingestion contracts and tests.
- [x] 2.2 Add scoped relational `scum_*` repository models/migrations and generic upsert/list operations for the first five datasets.
- [x] 2.3 Expose server-instance APIs for persisted users, squads, activity, gifts, and map points.
## 3. Operations Console
- [x] 3.1 Add themed server-management views and API clients for the five persisted SCUM datasets with real empty states.
## 4. Verification and Delivery
- [x] 4.1 Run manifest, Platform, frontend, OpenSpec strict, and structure checks; record evidence.
- [ ] 4.2 Stage only this change, commit on `main`, and push the configured remote.
@@ -1,2 +1,2 @@
schema: spec-driven
created: 2026-08-13
created: 2026-08-14
@@ -0,0 +1,22 @@
# Design
## Ownership
Platform owns authentication, server-instance authorization, durable storage mechanics, collection scoping, and transaction boundaries. It does not interpret collection payloads.
The SCUM plugin owns collection names such as `scum_users`, schemas, upsert keys, data transformations, gifts, map geometry, and UI behavior. It declares database/file/log work in the manifest; Platform dispatches those declarations to Run, and Run executes on the machine.
## Generic Platform Data Contract
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/get/put/delete generic collection methods to plugin bundles.
## SCUM Data Flow
1. The plugin declares v57 SQLite queries plus config/log parsers in its own versioned assets.
2. Platform dispatches the selected declared operation to Run; no browser or plugin supplies a machine path or SQL string at request time.
3. Plugin-shaped results are stored in scoped `scum_*` collections through the generic store.
4. The SCUM page reads those collections through the generic bridge and applies all SCUM-specific presentation and gift logic locally.
## Compatibility
Recent SCUM-specific Platform routes, types, repository tables, and game-gift APIs are removed. The retained generic bridge remains usable by other game plugins without SCUM imports or switches.
@@ -0,0 +1,18 @@
# Rebuild SCUM Plugin-Owned Data
## Why
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.
## 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.
## Success Criteria
- Platform exposes no SCUM-, squad-, map-, or gift-specific data API/service/model added by this change.
- 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.
@@ -0,0 +1,25 @@
## ADDED Requirements
### Requirement: Generic Plugin Collection Storage
Platform SHALL persist opaque plugin records scoped by plugin identifier, server instance identifier, collection name, and record key.
#### Scenario: SCUM stores a user projection
- **WHEN** the SCUM plugin writes key `7656119...` to its `scum_users` collection for an authorized server instance
- **THEN** Platform stores the opaque record without interpreting SCUM fields
- **AND** another plugin or server instance cannot read the record through the scoped API
### Requirement: Plugin-Owned SCUM Domain
The SCUM plugin SHALL own its collection names, record schemas, gift behavior, map behavior, and version-specific data extraction assets.
#### Scenario: SCUM version changes
- **WHEN** a SCUM database or log format changes
- **THEN** the SCUM plugin updates its versioned query/parser assets
- **AND** Platform does not require a SCUM business-logic change
### Requirement: Machine Data Relay
SCUM machine SQLite, configuration, and log operations SHALL remain plugin-declared and Platform-dispatched to Run.
#### Scenario: Declared SQLite read
- **WHEN** a SCUM page requests a declared data refresh
- **THEN** Platform routes the declared operation through Run
- **AND** neither the page nor Platform's generic collection API accepts a raw host path or arbitrary SQLite statement
@@ -0,0 +1,9 @@
# Tasks
- [x] Revert the direct-data and reference-alignment commits while retaining unrelated local-debug fixes.
- [x] Add a generic scoped plugin data record model, repository, service, DTO, and HTTP API in Platform.
- [x] Add generic collection actions to the plugin-page host and browser API client.
- [ ] Restore SCUM v57 SQL, config, log, and gift assets in the plugin package.
- [ ] Rebuild the SCUM plugin page to use only generic collection bridge actions for users, squads, activity, gifts, and map points.
- [ ] Remove obsolete SCUM-specific Platform/frontend data and gift surfaces that conflict with plugin ownership.
- [ ] Add focused backend, plugin, and frontend tests; run structure and OpenSpec validation.