Implement SCUM direct data plane

This commit is contained in:
npc0-hue
2026-08-13 16:33:11 +08:00
parent b07a792784
commit 8b236d7c15
56 changed files with 1466 additions and 90 deletions
@@ -0,0 +1,57 @@
## 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.