Revert SCUM real data management change

This commit is contained in:
npc0-hue
2026-08-13 15:33:34 +08:00
parent d831e4ade9
commit b07a792784
163 changed files with 5443 additions and 9174 deletions
@@ -1,2 +0,0 @@
schema: spec-driven
created: 2026-08-11
@@ -1,183 +0,0 @@
## Context
The current SCUM implementation has two disconnected local player models and an unimplemented real-data path. Login ingestion can upsert `GamePlayer` only after Run has already supplied synthetic `eventType/playerId/playerName` fields, while the repository's only SCUM parser recognizes an invented `SCUM LOGIN/LOGOUT` console format rather than the game's real login file. The plugin manifest declares six SQLite query keys but contains no query asset, workflow dispatch changes local statuses without creating read jobs, and job completion never calls the SCUM row-ingestion service. The page therefore renders empty local objects, fabricated maintenance/backup references, hard-coded actions, a non-georeferenced dot board, and a hard-coded gift.
The reference `scum_robot` demonstrates the useful direction—tail the current server's login log, create a server-scoped local player, and let a machine-side process query its current SCUM.db—but its static SCUM structs are not migrated or authoritative, its production roster/world refresh mostly parses administrator-command output, and its raw SQL, permissions, XML rewrite, early gift-success recording, and forced player death are unsafe to copy.
This change crosses `platform/`, `platform_web/`, the SCUM plugin and SDK, and the independent Run repository. It must preserve the repository boundary: the SCUM plugin owns game-specific formats and declarations; Platform owns authorization, durable local business data, jobs, and safe APIs; Run owns generic machine-side execution and observed runtime facts. Browser code never receives SQL, raw XML, database paths, credentials, sockets, or raw RCON.
The implementation is blocked from declaring production SQL or `855` semantics until a read-only probe against the current bound service produces evidence. An unbound copied/reference database, historical cache, or generated model is only a hypothesis source. Run may create an execution-time read-only snapshot of the active database only when the snapshot is fenced to the current binding/database identity, timestamped, checksummed, short-lived, and invalidated on rebinding or schema change.
## Goals / Non-Goals
**Goals:**
- Replace SCUM projection/observation/Workflow product concepts with automatic synchronization into dedicated local records.
- Create player identity and session data from authentic SCUM login/logout logs and enrich it only with verified current-service database facts.
- Make the plugin own versioned parsers, SQL, result contracts, map metadata, RCON templates, and controlled mutation metadata while Run remains generic.
- Provide trustworthy user, squad, map, gift, and AI surfaces with explicit effective-user permissions and no fabricated facts or evidence.
- Keep unknown values null/absent, preserve the last successfully synchronized rows after a failed sync, and show ordinary connection/last-sync information without projection/freshness jargon or manual refresh actions.
- Make manual and AI-originated writes use one typed authorization, review, dispatch, and confirmation path.
- Preserve required server deployment, metadata, and administrator controls after removing the `管理` tab.
**Non-Goals:**
- Do not add a `run/` tree, billing, cloud-host sales, agent-provider workflows, or unrelated marketplace behavior.
- Do not use a repository/reference/cached `SCUM.db`, trust `scum_robot/model/scum_server.go` as a production schema, or ship guessed joins, enum values, coordinates, ownership, balances, or default zero values.
- Do not expose arbitrary SQL, raw RCON, host paths, direct sockets, SCUM.db credentials, or raw `template_xml` to Platform Web or AI.
- Do not hardcode SCUM tables, query keys, commands, or lifecycle behavior in Platform or Run.
- Do not provide a Workflow status page, refresh/audit buttons, a manual synchronization API, or product-facing projection/observation terminology.
- Do not automatically kill/respawn a character, invent a missing XML skill, or claim a write/gift succeeded before conclusive execution and confirmation evidence exists.
- Do not promise a sub-second realtime map when the verified database or companion source cannot supply that cadence.
## Decisions
### 1. Bootstrap a generic probe, then treat current-service discovery as a release gate
The first cross-repository prerequisite is to confirm or add the minimal generic, bounded diagnostic probe executor in the independent Run repository and deploy that compatible Run to the current binding. Platform and Run must establish the probe request/result envelope, binding fence, safe limits, and redaction without introducing any SCUM-specific table or path knowledge.
Only then will the production implementation execute bounded, read-only probes through the currently bound Run. For operator-directed discovery, a server-local diagnostic script may read the active database in place on the game server host when it is bounded, query-only, redacted, and recorded as diagnostic evidence rather than a Platform/plugin/browser data path. In both cases, the evidence must include `sqlite_master`, `PRAGMA table_info`, foreign-key/index information for candidate tables, small redacted samples, relevant enum distributions, coordinate ranges/cadence, and read-lock behavior. It must confirm player/profile/entity joins, squad rank meaning, flag ownership relationships, vehicle identity fields, currency types, and whether/where a mutable profile XML payload actually exists.
Current-service schema, log structure, and content-feature baselines are an explicit prerequisite for further adapter or write declarations. The change stores a redacted all-table schema inventory, process-adjacent log pattern inventory, XML tag/attribute/value-shape summaries, and log skeleton marker sets under `evidence/`; capability work must consume those local baselines rather than repeatedly probing piecemeal or asking the operator for raw XML/log/database files.
No production query or mutation asset may be merged until the probe evidence is captured in the change or an explicitly referenced test artifact. The probe is diagnostic-only, is not exposed as a browser action, and performs no write.
Alternative considered: start with the reference structs and fix queries after deployment. Rejected because the reference models are incomplete hypotheses and the current implementation already failed by treating guessed fields as facts.
### 2. Package game-specific behavior as signed plugin assets
The SCUM plugin will contain versioned assets for:
- login/logout parsing and field mapping;
- read-only SQLite queries for player details, squads, squad members, vehicles, flags, and positions;
- result JSON schemas and schema-version compatibility;
- map identity, asset reference, world bounds, and coordinate transform;
- RCON command templates for supported economy and gift operations;
- database/XML mutation declarations for fields without a safe game command.
Manifest declarations will reference each asset and its digest. The generated Run package will contain those immutable assets. Platform queues a template key plus bounded parameters and expected digest; it does not construct SCUM SQL or command text. Run verifies the packaged asset/digest and executes it through a generic capability.
Alternative considered: make Run implement the six `scum.*` keys. Rejected because it makes Run game-aware and requires a Run release for every SCUM schema change. Alternative considered: accept SQL from the browser or a general Platform endpoint. Rejected because it creates an arbitrary database interface.
### 3. Add generic bounded Run contracts instead of SCUM workflows
The external Run contract will support:
- a generic current-target schema probe;
- read-only SQLite template execution with parameter binding, a single SELECT/CTE or approved introspection statement, query-only mode, timeout, row/result-size limits, and no `ATTACH`, extension loading, or mutation;
- plugin-owned typed RCON template execution;
- plugin-owned guarded SQLite/XML mutation execution in a bounded transaction;
- typed result envelopes containing server/plugin binding, template key, asset digest, schema version, observed time, checksum, rows or affected-row count, and a safe error/result code.
Platform will use ordinary durable Run jobs and the existing channel priority/lease/fencing rules. A new terminal-job hook validates the result envelope and schema, then invokes the matching local sync or write-confirmation service. There is no SCUM Workflow instance/step scheduler.
Alternative considered: repair the current SCUM workflow engine. Rejected because synchronization is a background data-ingestion concern, direct resource mutations already have a single target operation, and the workflow layer currently adds user-visible states without performing work.
### 4. Persist SCUM facts in dedicated normalized local stores
The local model will use dedicated repositories for at least:
- `scum_players` with unique `(server_instance_id, external_player_id)`;
- `scum_player_sessions` with durable source-event identity;
- `scum_player_details` for nullable profile/economy/squad facts and source checksum/time;
- `scum_squads` and `scum_squad_members`;
- `scum_vehicles`, `scum_flags`, and `scum_positions`;
- `scum_gift_packages`, `scum_gift_items`, and `scum_gift_deliveries`;
- internal `scum_sync_cursors` and successful sync generations.
High-frequency SCUM data will not be appended to the global metadata snapshot. The `mysql` backend will use normalized MySQL tables and migrations. The default `file` backend will use a platform-owned SQLite sidecar under the configured data directory; the `memory` backend will use an in-memory implementation for tests. The storage interface remains under `platform/repo`, database models/migrations under their fixed platform directories, and domain/API types remain separate.
A full successful resource scan uses a generation marker: rows are upserted transactionally, and records missing from the completed generation can be marked absent. A partial or failed scan never deletes or overwrites the last successful rows. Missing source fields remain `NULL`; zero is stored only when the source explicitly reports zero.
Alternative considered: retain the existing generic snapshot repositories and rename projection types. Rejected because every coordinate update would rewrite the whole metadata snapshot and would preserve the misleading data architecture the change is intended to remove.
### 5. Synchronize automatically from logs, binding state, and declared cadence
Run tails the plugin-declared login source and applies the plugin parser locally. Each typed login/logout event carries both a transport cursor `(source identity, stream generation, sequence)` for acknowledgement/resume and a privacy-safe logical event identity that is native to the log when available or derived from normalized non-network event fields and remains stable across rotation-overlap replay. A successful login atomically upserts the player, updates the current display name and last-seen time, and opens a session; logout closes the matching session without regressing a newer session. The source contract handles file rotation, truncation, Run restart, partial lines, and duplicate/overlapping batches without duplicating a logical event. Malformed lines, failed-login attempts, and events from an obsolete binding never create a player. Raw IP/network material is discarded before durable storage or logical fingerprinting.
The sync scheduler starts an initial bounded database scan when a compatible Run binding becomes ready, schedules resource scans at plugin-declared intervals with jitter and per-server concurrency limits, and may enqueue a bounded player-detail lookup after a new login. Positions use the measured safe cadence. If SCUM.db cannot provide the required map cadence, the plugin must declare a companion position-event source; the product must not compensate with fabricated motion or aggressive unsafe polling.
Platform Web always reads local resource APIs and receives updates through a platform-owned event stream/SSE. Opening a page never dispatches a database query, and there is no user refresh button.
Alternative considered: query Run on every page load. Rejected because it couples browser latency to machine connectivity, multiplies database reads, and makes pagination/filtering dependent on a remote SQLite file.
### 6. Replace the player-intelligence model with a lean roster
The SCUM product flow retains only the server-scoped player identity, current display name, first/last seen times, online session, login history, and verified player details. It removes alias-history, access-attempt, shared-IP, automatic-risk, and player-intelligence features from SCUM manifests, APIs, UI, and persistence when they have no non-SCUM consumer.
List APIs operate on the local store and support bounded pagination, search by name/external ID, online state, squad filter, and allowlisted sorting. Player detail returns nullable verified facts and last synchronized time. The UI uses a table and detail/edit surface rather than a fixed list of cards and hard-coded increments.
Alternative considered: keep the intelligence records hidden. Rejected because the user requested a smaller player model and the hidden ingestion side effects would still complicate login creation and retention.
### 7. Use one controlled-write path for manual and AI requests
Existing permission families remain explicit:
- `server.game-client.read` for local SCUM reads;
- `server.game-client.command` for declared RCON/economy/gift actions;
- `server.game-client.maintenance` plus an explicit synchronous danger confirmation for database/XML mutations.
The plugin page host must receive the current session's effective server permissions, not merely the permissions declared by the plugin/page. The backend reauthorizes every request and remains authoritative. An AI draft records the initiating user and cannot be dispatched unless that same confirming user still has the permission required for a manual request. AI never runs under an independent component write principal.
Fame and currencies use plugin-declared game commands when verified. Character attributes use a version-scoped XML patch declaration only after the active adapter confirms the actual profile XML source: Run reads the current payload, checks the expected row/checksum, changes only allowlisted named attributes or existing skill nodes, preserves all unknown nodes/attributes, updates at most one row with bound parameters, and reads back for confirmation. A real backup reference, verified offline/maintenance condition when required, before values, reason, idempotency key, and explicit confirmation are mandatory. A timestamp-shaped fake backup or maintenance string is invalid. There is no separate platform-admin approval domain, audit-initiation action, or approval queue.
`855` is not a field key. It can be declared only as a preset that expands to explicitly named attributes after its exact mapping is confirmed. Any respawn/death action needed to activate values is a separate explicit destructive operation and is never part of the default attribute save.
Alternative considered: reuse `player.attribute.855.set` and a generic integer field mutation. Rejected because the source is XML containing several named values. Alternative considered: let AI or Platform generate raw SQL/XML. Rejected because it leaks protected content and bypasses plugin version fencing.
### 8. Model gifts as local business data with typed delivery
Gift packages and items are server/plugin-instance scoped and have normal create, read, update, and delete operations, bounded eligibility/quantity rules, and explicit active state. A delivery freezes the target player and item definitions, atomically reserves any period-limited entitlement, uses a server-scoped idempotency key, and dispatches only a plugin-declared typed command. In-progress and unknown outcomes retain their reservation so concurrent requests cannot exceed the limit; only a conclusive non-executed failure may release it. The API reports creation/dispatch separately from delivered success. `delivered` is stored only after conclusive Run success; failed and unknown outcomes retain safe evidence and never auto-redeliver.
Alternative considered: preserve the current hard-coded starter package and notification. Rejected because neither is backed by catalog data. Alternative considered: copy `scum_robot`'s Redis command list. Rejected because it stores success before execution and accepts raw game command strings.
### 9. Make the SCUM surface contain exactly five tabs
The server detail order is `用户管理`, `队伍管理`, `实时地图`, `礼包管理`, `AI 助手`; the first plugin page is the default. `Workflow 状态` is removed from the manifest and the generic `管理` entry is excluded for the SCUM detail view. Deployment remains reachable from server-list actions. Server name and administrator membership move into a server-settings drawer opened from the detail header.
All copy and actions referring to projection, observation, freshness/staleness, refresh projection, refresh real data, initiate audit, pending review counts, or Workflow state are removed. Pages may show ordinary connection status and last synchronized/collected time. Empty states describe the missing business record without offering a manual refresh or implying generated data.
AI configuration keeps the existing reviewable config-diff path. Player-operation AI suggestions produce the same named-field edit draft used by the manual form.
Alternative considered: hide the two tabs without moving their content or changing the default route. Rejected because it would strand required server controls and leave invalid route fallbacks.
### 10. Keep legacy completed changes historical instead of importing obsolete specs
The repository's main OpenSpec baseline currently contains no SCUM capabilities, while the changes that introduced player intelligence, trajectories, the versioned gift catalog, player-state patching, projection/Workflow automation, controlled operations, and the old product surface are complete but unarchived. This replacement therefore declares only uniquely named `ADDED` capabilities. It supersedes those historical artifacts through explicit implementation deletion and acceptance coverage; it does not first archive them into the baseline and then attempt to remove them.
The old completed changes must not later be archived in a way that publishes their obsolete SCUM requirements as current baseline specs. Historical cleanup is a separate reviewed consolidation after this replacement is implemented, using skip-specs or an equivalent approach that preserves history without resurrecting removed behavior.
## Risks / Trade-offs
- [Risk] SCUM schema changes between game versions. → Require live probe evidence, schema-versioned assets, exact result schemas, digest fencing, and a disabled/incompatible state rather than fallback queries.
- [Risk] Reading the live SQLite file can block or observe inconsistent rows. → Use query-only connections, short timeouts, bounded scans, measured cadence, jitter/backoff, and keep the last completed generation on failure.
- [Risk] Game saves may overwrite direct database/XML changes. → Verify offline/maintenance semantics against the current service, require before/checksum guards and backup evidence, and disable unverified mutations.
- [Risk] XML reserialization can destroy fields unknown to the current plugin. → Patch only named attributes/existing nodes while preserving raw document structure, then confirm by readback; never synthesize missing skills.
- [Risk] Cross-repository Run support can lag the browser release. → Gate synchronization and write UI on compatible asset-executor capabilities and deploy Run support before enabling the new pages.
- [Risk] Dedicated local tables add a second persistence path for the file backend. → Keep it behind a narrow `SCUMStore` interface, use explicit migrations and health checks, and fail the SCUM feature closed without affecting core server lifecycle.
- [Risk] Position polling can generate large write volume or still not be realtime. → Measure source cadence, retain only current positions by default, make history explicitly bounded, and use a declared companion event source when database cadence is inadequate.
- [Risk] Removing `管理` can make server settings undiscoverable. → Add header-level server settings and preserve server-list deployment actions before removing the tab.
- [Risk] Old projection/Workflow snapshot data can look real after upgrade. → Never migrate it into the new tables; populate only from post-upgrade authenticated logs/current-service sync.
## Migration Plan
1. Confirm or implement the minimal generic diagnostic probe contract in the independent Run repository, deploy a compatible Run to the active binding, and verify binding fencing/redaction without adding SCUM-specific behavior to Run.
2. Probe the active service database in read-only mode, using either the durable Run path for product acceptance or an explicitly operator-directed server-local diagnostic for discovery only; capture schema/cadence/lock evidence and confirm whether the `855` preset has a real named-attribute mapping. Stop any affected capability if the evidence cannot support safe query or mutation declarations.
3. Add plugin/SDK/validator contracts and immutable SCUM parser/query/map/command/mutation assets backed by that evidence; implement and deploy the remaining compatible generic Run executors in the independent repository.
4. Add the dedicated SCUM store implementations, migrations, health checks, local resource contracts, and automatic sync scheduler behind a disabled-by-default compatibility gate.
5. Wire authentic, rotation-safe login events and terminal Run query results into local transactional upserts; verify initial and periodic sync against the current service without enabling writes.
6. Build the player, squad, map, and gift APIs/pages, effective-permission context, server-settings relocation, and preserved AI configuration flow against the new local records.
7. Enable controlled RCON writes, then separately enable guarded XML mutations only after actual source mapping, backup/offline/readback verification, effective permission, and explicit confirmation succeed on the current service.
8. Cut navigation and clients to the five new tabs; remove Workflow/projection/observation APIs, services, repositories, snapshot fields, page actions, banned copy, fake gifts/map/actions, and obsolete tests/spec assumptions.
9. Run focused backend/frontend/plugin tests, external Run contract acceptance, browser acceptance against real synchronized data, `scripts/check-structure.sh`, and `openspec validate replace-scum-projections-with-real-data-management --strict` before marking tasks complete.
Rollback disables the SCUM compatibility gate and write actions while leaving the new local tables for diagnosis. It must not re-enable fake projection data or migrate new facts back into old Workflow/projection records. Core server lifecycle, logs, jobs, and AI provider management remain available.
## Open Questions
- What are the exact current-service tables, columns, joins, enum values, coordinate cadence, and safe read behavior?
- What exact named attribute mapping does the operator mean by the `855` preset, and what game action—if any—is required for those values to take effect?
- Does the verified current SCUM version support safe RCON readback for fame/currencies, or must confirmation use a database query?
- Which map asset/version and coordinate transform are authorized for first-party redistribution?
- Which gift item aliases and delivery transports can be verified without exposing or accepting arbitrary commands?
- Which pure-Go SQLite driver and migration mechanism will be pinned for the default file-backend sidecar after dependency and build verification?
@@ -1,32 +0,0 @@
# Run Guarded SQLite/XML Mutation Execution Handoff (2026-08-13)
This is a browser-repository handoff for a separately authorized task in the independent Run repository `git@git.npc0.com:admin343/run.git`. It is not Run implementation or deployment evidence, and it does not enable SCUM database/XML write capabilities by itself.
## Positive prompt (正向提示词)
Implement generic plugin-owned guarded single-row SQLite/XML mutation execution for Run's protected SQL capability so Platform can dispatch reviewed SCUM profile-XML writes without sending raw SQL, raw XML, browser mutation text, host paths, sockets, credentials, table/column overrides, raw rows, `fieldKey=855`, or undeclared patch fields. Success means Run accepts only a typed leased `guardedMutation` request containing logical target/template keys, adapter/schema version, immutable asset digest, target identity digest, expected row/value/XML digests, patch digest, backup/offline/danger-confirmation evidence digests, readback expectation digest, idempotency key, bounded scalar payload, safe review reason, and strict limits; applies the packaged preserving patch inside a bounded transaction; rolls back on guard mismatch, malformed XML, zero/multiple affected rows, or failed readback; and returns a typed `sqlite.guarded-mutation` terminal envelope that Platform can validate against the original durable job.
## Directional prompt (方向提示词)
Work only in the independent Run repository. Preserve Run as a generic executor: resolve protected SQLite targets and packaged mutation templates from the generated Run workspace, verify active binding, adapter/schema fingerprint, asset/target/guard/patch/backup/offline/confirmation/readback digests, validate scalar payload against packaged schema, open only the package-declared SQLite target or fenced current-service snapshot as permitted by the generated plan, enforce timeout/busy/readback/payload limits, execute a bounded transaction, use a preserving XML patcher that changes only allowlisted named attributes or existing nodes, preserve unknown XML content, reject absent undeclared nodes instead of synthesizing them, update exactly one guarded row, and read back conclusive digest evidence before success.
Expected Run verification: focused protocol/runtime tests for valid single-row mutation, unknown template, digest mismatch, stale expected row/value/XML guard, missing backup/offline/danger confirmation, malformed XML, absent node, zero-row update rollback, multi-row rollback, timeout/cancellation, readback mismatch/unknown, result-size limit, duplicate/late terminal result behavior, and `go test ./...` from the Run repository root. After implementation, record the tested Run commit, distribution/deployment evidence for the active binding, and safe terminal-envelope evidence back in this browser-repository change before enabling guarded mutation gates or declaring production XML mutation assets.
## Boundary prompt (任务边界)
Do not edit or vendor Run source into this browser repository, add a `run/` tree here, accept raw SQL/XML/browser mutation text, expose host paths/credentials/sockets/raw XML/SQL/IPs/player identities in evidence, add SCUM-specific executor branches, branch on SCUM keys/tables/profile names/`855` semantics, synthesize missing XML nodes, rewrite XML from incomplete structs, update more than one row, skip same-instance backup/offline/danger-confirmation/readback guards, enable `855`, enable production guarded mutation assets, or treat this handoff as product acceptance evidence. Run must remain game-agnostic and execute only package-declared generic assets under the active signed binding and lease.
## Browser-side frozen contract
- Platform domain/DTO contracts define `SCUMGuardedMutationRequest`, `SCUMGuardedMutationResult`, guarded mutation bounds, terminal statuses, mutation readback statuses, and stable safe error codes for guard/readback/rollback failures.
- Job-channel DTOs expose leased `executionInput.guardedMutation` to Run and parse terminal `executionResult.guardedMutation` from Run.
- Validators reject unsafe template keys, protected material, raw XML, SQL/path-like material, `855` field payloads, missing schema/asset/identity/value/XML/patch/backup/offline/danger-confirmation/readback digests, loose affected-row bounds, unsafe review reasons, unsafe summaries, multi-row success, and missing conclusive readback.
- Service job completion accepts `sqlite.guarded-mutation` only for `remote.run.protected.sql` jobs carrying a typed guarded mutation request, requires the typed result on success, checks leased job/binding/template/schema/asset/target/guard/patch/backup/offline/confirmation/readback identity, and includes typed result digests in terminal idempotency fingerprints.
## Remaining evidence required before enabling mutations
- Tested Run commit and `go test ./...` output from the independent Run repository.
- Generated Run package carrying any future packaged mutation template, preserving XML patcher declaration, schema/payload/result/readback schemas, immutable asset digests, and logical SQLite target binding.
- Current-service evidence proving the exact source row/XML payload, named attribute mapping, preserving patch semantics, same-instance backup/restore evidence, offline/maintenance requirements, readback behavior, and safe failure outcomes.
- Active binding deployment evidence showing compatible Run executes `remote.run.protected.sql` through the typed guarded envelope without raw SQL/XML exposure.
- Platform acceptance evidence against isolated test data or an explicitly authorized test player proving permission, explicit confirmation, guards, backup/offline requirements, idempotency, readback, unknown-result handling, XML preservation, and no implicit respawn/death/kick activation.
@@ -1,34 +0,0 @@
# Run Log-Source Tailing Handoff (2026-08-13)
This is a browser-repository handoff for a separately authorized task in the independent Run repository `git@git.npc0.com:admin343/run.git`. It is not Run implementation or deployment evidence, and it does not enable SCUM login-driven player creation by itself.
## Positive prompt (正向提示词)
Implement or extend generic plugin-declared log-source tailing in Run so Platform can consume sanitized parsed login/logout events from the current bound SCUM service without sending or receiving raw log paths, raw log lines, IP/network material, sockets, credentials, SQL, XML, or SCUM-specific executor branches. Success means Run tails only package-declared logical log sources, persists transport cursor state, handles rotation, copy-truncate, restart/resume, zero-byte active files, partial-line buffering, parser digest fencing, logical event fingerprinting, and replay, then returns typed `log.parsed-events` terminal envelopes or later parsed-event ingress payloads that Platform can validate against the active binding and declared parser identity.
## Directional prompt (方向提示词)
Work only in the independent Run repository. Preserve Run as a generic executor: resolve `file.tail` sources from the generated Run package and runtime bindings, keep host paths and globs local to Run, fence every parser by package asset digest and parser digest, decode lines according to the packaged parser declaration, buffer incomplete lines across polling/restart boundaries, detect rotation or truncate by source fingerprint/generation rather than SCUM file names, persist acknowledged cursor state `(source identity digest, stream generation, sequence)`, and emit sanitized logical events whose stable `logicalEventDigest` excludes source identity, stream generation, sequence, IP/network material, and coordinates.
Expected Run verification: focused protocol/runtime tests for zero-byte active file startup, append after empty file, UTF-16LE decoding, partial line buffering, oversized/undecodable/malformed line handling, failed-login discard, rotation, copy-truncate overlap, restart/resume from acknowledged cursor, duplicate transport cursor rejection, duplicate logical event replay, parser digest mismatch, stale binding/source identity rejection, bounded batch limits, safe error codes, and `go test ./...` from the Run repository root. After implementation, record the tested Run commit, distribution/deployment compatibility evidence for the active binding, and a safe redacted terminal-envelope sample back in this browser-repository change before enabling login-event ingestion tasks.
## Boundary prompt (任务边界)
Do not edit or vendor Run source into this browser repository, add a `run/` tree here, expose raw host paths, resolved log names, glob patterns, log lines, IP/network identifiers, sockets, credentials, SQL, XML, raw player identities, or parser-internal source paths in Platform, browser, AI context, or evidence. Do not branch Run behavior on SCUM file names, SCUM table names, SCUM parser keys, or SCUM event semantics; do not treat ordinary log ingest as a parsed-event success path; do not fabricate players/sessions from malformed, failed-login, duplicate, obsolete-binding, or out-of-order events; and do not treat this handoff as product acceptance evidence.
## Browser-side frozen contract
- Platform domain/DTO contracts define `SCUMParsedLogBatchResult`, `SCUMParsedLogEvent`, `SCUMParsedLogCursor`, parsed-log batch limits, tail states (`advanced`, `rotated`, `truncated`, `restarted`, `partial-buffered`, `replayed`), and safe terminal statuses.
- Job-channel DTOs parse terminal `executionResult.parsedLogBatch` from Run when `executionResult.kind` is `log.parsed-events`.
- Validators require request/job/binding identity, source/stream/parser key, adapter version, parser asset digest, parser digest, first/last redacted source identity and generation cursors, bounded event counts, logical event digests, event/payload digests, safe scalar payloads, and applied limits.
- Validators reject raw log/path/IP/network material, raw XML, SQL-like text, unsafe summaries, unsafe safe-error messages, duplicate transport cursors, duplicate logical event digests within a batch, event-count mismatches, loose line/payload/result bounds, parser digest omissions, and cross-generation batch success.
- Service job completion accepts `log.parsed-events` only for `logs.backfill` jobs carrying a leased declared `file.tail` log source, checks server/Run endpoint, declared source/stream key, plugin id/version when frozen, parser key/version/digest/adapter version when frozen in execution inputs, and single source identity/generation boundaries.
- Terminal idempotency fingerprints include parsed-log result digest, asset digest, parser digest, stream generation, event count, and tail state.
## Remaining evidence required before enabling parsed-login ingestion
- Tested Run commit and `go test ./...` output from the independent Run repository.
- Generated Run package evidence carrying the declared `file.tail` source, parser asset, parser digest, max-line limit, cursor policy, and privacy policy.
- Active current-service evidence showing the latest zero-byte login file, non-empty UTF-16LE fixtures, rotation/truncate behavior, and sanitized parser output with no raw network material.
- Platform acceptance evidence proving parsed batches are authenticated, fenced to the current server/Run/plugin/parser binding, idempotent across replay, and rejected for stale parser digest, stale source identity, duplicate transport cursor, and unsafe payloads.
- Follow-on Platform ingestion tests from task 6.1 proving successful login creates one local player/session, logout closes only matching sessions, and malformed/failed/duplicate/out-of-order events do not fabricate state.
@@ -1,31 +0,0 @@
# Run SQLite Template Execution Handoff (2026-08-13)
This is a browser-repository handoff for a separately authorized task in the independent Run repository `git@git.npc0.com:admin343/run.git`. It is not Run implementation or deployment evidence, and it does not enable SCUM database-backed reads by itself.
## Positive prompt (正向提示词)
Implement generic packaged SQLite-template execution for Run's `remote.run.db.sqlite.query` capability so Platform can dispatch current-service SCUM read jobs without sending SQL text, host paths, credentials, sockets, raw XML, raw RCON, or browser-supplied table names. Success means Run accepts only a typed leased `sqliteTemplate` request containing a logical target key, template key, adapter/schema version, immutable asset digest, canonical parameter digest, bounded scalar parameters, and strict limits; executes a query-only package-resolved SQLite template; and returns a typed `sqlite.template-query` terminal envelope that Platform can validate against the original durable job.
## Directional prompt (方向提示词)
Work only in the independent Run repository. Preserve Run as a generic executor: resolve package-scoped logical `databases/...` targets and packaged assets from the generated Run workspace, verify the asset digest and adapter/schema fingerprint, validate canonical bounded parameters, open SQLite in query-only/read-only mode or use a fenced short-lived read-only snapshot, enforce one-statement validation, reject mutation/DDL/`ATTACH`/extension loading/write PRAGMAs/multi-statement input, bind parameters, apply short busy and operation timeouts, honor cancellation, and enforce row/result-byte limits. Return the terminal envelope through the existing signed job-result channel with request/job/binding identity, capability, target/template key, adapter version, schema fingerprint, asset digest, parameter digest, source fingerprint, observed time, result digest, row count, bounded rows, truncation flag, applied limits, status, and stable safe error code.
Expected Run verification: focused protocol/runtime tests for valid template execution, digest mismatch, schema mismatch, parameter validation, cancellation, busy/timeout handling, result limits, one-statement enforcement, mutation/DDL/`ATTACH`/extension/write-PRAGMA rejection, duplicate/late terminal result behavior, and `go test ./...` from the Run repository root. After implementation, record the tested Run commit, distribution/deployment evidence for the active binding, and safe terminal-envelope evidence back in this browser-repository change before enabling DB-backed read gates.
## Boundary prompt (任务边界)
Do not edit or vendor Run source into this browser repository, add a `run/` tree here, download or parse `SCUM.db` on the platform/plugin/browser side, expose raw SQL/RCON/XML/paths/credentials/sockets/IPs/player identities in evidence, accept browser command/query text, add SCUM-specific executor branches, infer SCUM table semantics inside Run, enable write capabilities, enable database-backed read gates before tested Run evidence is recorded, or treat this handoff as product acceptance evidence. Run must remain game-agnostic and execute only package-declared generic assets under the active signed binding and lease.
## Browser-side frozen contract
- Platform domain/DTO contracts define `SCUMSQLiteTemplateRequest`, `SCUMSQLiteTemplateResult`, bounded template limits, scalar parameters/rows, and stable terminal statuses.
- Job-channel DTOs expose leased `executionInput.sqliteTemplate` to Run and parse terminal `executionResult.sqliteTemplate` from Run.
- Validators reject unsafe template keys, protected material, raw SQL/path-like values, unsupported capabilities, invalid digests, loose bounds, mismatched row counts, and unsafe result rows.
- Service job completion accepts `sqlite.template-query` only for `remote.run.db.sqlite.query`, requires the typed result on success, checks leased job/binding/template/schema/asset/parameter identity, and includes typed result digests in terminal idempotency fingerprints.
## Remaining evidence required before enabling reads
- Tested Run commit and `go test ./...` output from the independent Run repository.
- Generated Run package carrying the packaged query assets and immutable digests.
- Active binding deployment evidence showing the compatible Run advertises and executes `remote.run.db.sqlite.query` through the typed envelope.
- Platform acceptance evidence for at least one safe read-only template job with no raw SQL, host paths, credentials, sockets, raw XML, raw RCON, or browser-supplied query material.
@@ -1,32 +0,0 @@
# Run Typed RCON Template Execution Handoff (2026-08-13)
This is a browser-repository handoff for a separately authorized task in the independent Run repository `git@git.npc0.com:admin343/run.git`. It is not Run implementation or deployment evidence, and it does not enable SCUM write capabilities by itself.
## Positive prompt (正向提示词)
Implement generic plugin-owned typed RCON-template execution for Run's protected RCON capability so Platform can dispatch reviewed SCUM command writes without sending browser command text, raw RCON, SQL, XML, host paths, sockets, credentials, or undeclared command keys. Success means Run accepts only a typed leased `rconTemplate` request containing logical transport/target keys, template key, adapter/schema version, immutable asset digest, canonical payload digest, confirmation digest, target identity digest, idempotency key, bounded scalar payload, safe review reason, and strict limits; renders only the packaged template; executes through generic protected RCON; performs the declared confirmation path; and returns a typed `rcon.template-command` terminal envelope that Platform can validate against the original durable job.
## Directional prompt (方向提示词)
Work only in the independent Run repository. Preserve Run as a generic executor: resolve protected RCON transports and packaged command templates from the generated Run workspace, verify asset/payload/confirmation digests and active binding, validate scalar payload against packaged schema, render only the packaged template with bound values, enforce payload/response/confirmation limits, honor timeout and cancellation, redact rendered command text from all result envelopes, and return stable safe error codes. The terminal envelope must contain request/job/binding identity, capability, transport/target/template key, adapter version, schema fingerprint when required, asset digest, payload digest, confirmation digest, target identity digest, observed time, result digest, response digest, confirmation status, confirmation digest id, safe summary, safe error, and applied limits.
Expected Run verification: focused protocol/runtime tests for valid template execution, unknown template, digest mismatch, payload schema rejection, missing protected transport, timeout/cancellation, response limits, confirmation success/failure/unknown, duplicate/late terminal result behavior, and `go test ./...` from the Run repository root. After implementation, record the tested Run commit, distribution/deployment evidence for the active binding, and safe terminal-envelope evidence back in this browser-repository change before enabling typed command or gift gates.
## Boundary prompt (任务边界)
Do not edit or vendor Run source into this browser repository, add a `run/` tree here, accept browser command text, expose rendered RCON text, expose host paths/credentials/sockets/raw XML/SQL/IPs/player identities in evidence, add SCUM-specific executor branches, branch on SCUM keys/commands/tables/gift/economy semantics, enable typed RCON templates or gift catalogs in the production SCUM manifest, enable write gates before current-service command/readback evidence and tested Run evidence are recorded, or treat this handoff as product acceptance evidence. Run must remain game-agnostic and execute only package-declared generic assets under the active signed binding and lease.
## Browser-side frozen contract
- Platform domain/DTO contracts define `SCUMTypedRCONTemplateRequest`, `SCUMTypedRCONTemplateResult`, typed RCON bounds, terminal statuses, and confirmation statuses.
- Job-channel DTOs expose leased `executionInput.rconTemplate` to Run and parse terminal `executionResult.rconTemplate` from Run.
- Validators reject unsafe template keys, protected material, raw command-like payload keys, invalid digests, loose bounds, unsafe review reasons, unsafe summaries, unconfirmed success, and mismatched adapter/binding versions.
- Service job completion accepts `rcon.template-command` only for `remote.run.protected.rcon` jobs carrying a typed template request, requires the typed result on success, checks leased job/binding/transport/template/schema/asset/payload/confirmation/target identity, and includes typed result digests in terminal idempotency fingerprints.
## Remaining evidence required before enabling writes
- Tested Run commit and `go test ./...` output from the independent Run repository.
- Generated Run package carrying any future packaged RCON templates and immutable digests.
- Current-service evidence proving supported command semantics, confirmation/readback behavior, item aliases/transports where relevant, and safe failure outcomes.
- Active binding deployment evidence showing compatible Run executes `remote.run.protected.rcon` through the typed envelope without raw command exposure.
- Platform acceptance evidence for at least one safe typed command job against isolated test data or an explicitly authorized test player.
@@ -1,21 +0,0 @@
# SCUM Capability Negotiation and Run Acceptance Audit (2026-08-13)
This evidence records a browser-repository audit for task 4.7 and the Platform-side implementation evidence for task 4.8.
## Run acceptance audit
- Local independent Run checkout inspected read-only from the ignored nested checkout: it is on `main...origin/main`, latest commit `8fe6f9b` (`Fix SQLite probe data target mapping`), with only ignored local-debug dirt. The visible history covers schema-probe and data-target materialization work (`6cb6ba3`, `9cc9ab3`, `8fe6f9b`) and does not contain the later generic SQLite-template, typed RCON-template, guarded mutation, or parsed-log-source execution acceptance evidence required by task 4.7.
- Browser-repository handoff evidence files for SQLite template execution, typed RCON template execution, guarded SQLite/XML mutation execution, and log-source tailing were re-read. Each is explicitly a contract handoff only and says it is not Run implementation, deployment, or product acceptance evidence.
- Server-management MCP was used for the remote path: `list_devices`, `test_connection` for `枣庄服务器`, then one bounded read-only PowerShell diagnostic. The diagnostic returned only redacted aggregates: connection OK, `runProcessCount=0`, zero scanned Run roots, and zero marker hits for `sqlite.template-query`, `rcon.template-command`, `sqlite.guarded-mutation`, `log.parsed-events`, duplicate/late terminal markers, and protected RCON/SQL capability markers. It emitted no host paths, command lines, log lines, credentials, sockets, IP/network material, database rows, SQL, XML, RCON text, or player identities.
- Conclusion: task 4.7 remains pending. There is still no independent Run acceptance evidence proving channel priorities, leases, fencing, acknowledgements, idempotency, and late/duplicate terminal-result handling for the new generic capabilities. The schema-probe/data-target evidence recorded earlier remains valid only for the probe path and does not enable DB-backed reads, typed commands, gifts, guarded mutations, or parsed-login ingestion.
## Platform capability negotiation
- Added a read-only Platform capability negotiation path for the active server/plugin/Run endpoint/runtime binding: `GET /api/v1/server-instances/{id}/scum/capabilities`.
- The negotiation evaluates each SCUM manifest gate independently against the bound Run capability list and latest accepted typed terminal evidence for the same server, Run binding, Run endpoint, plugin version, adapter version, database identity, schema fingerprint, and asset digest set.
- The route returns only capability, enabled/disabled state, safe reason code, safe reason, binding identifiers, and evaluation time. It never dispatches Run jobs and never returns terminal rows, SQL, XML, RCON text, host paths, DSNs, sockets, credentials, protected payloads, or raw service content.
- Added regression coverage for compatible schema-probe evidence, compatible `players.read` SQLite-template evidence, missing per-capability evidence, missing protected RCON executor support, stale Run binding rejection, unauthorized access, no forbidden-material leakage, and no dispatch from the capabilities read.
## Verification
- Passed: `go test ./domain ./dto ./service ./api -run 'TestSCUMCapabilityNegotiation|TestSCUMSchemaProbeEndpointQueuesPlatformScheduledDurableJob|TestLegacySCUMEndpointsReturnNotFoundWithoutDispatchingJobs'`.
@@ -1,72 +0,0 @@
# SCUM current-service content features baseline (redacted)
- diagnostic: scum-current-service-content-features-v1
- observed_utc: 2026-08-13T03:56:41Z
- target: `枣庄服务器` via server-management MCP
- redaction: type, null, range, length, hash, XML-key, and log-skeleton features only; no raw rows, raw XML, raw log lines, host paths, IPs, credentials, sockets, or player identities
## DB content feature sources
This file complements the full schema inventory in `scum-current-service-db-schema-baseline-2026-08-13.md` and the join/range diagnostic in `scum-current-service-sqlite-diagnostic-2026-08-12.md`. The following previously captured content features remain authoritative inputs for adapter design:
- Identity/profile content: `user` has `74` rows, `user_profile` has `73` rows, all profiles join to `user`, and `72` profiles join to `prisoner` / `prisoner_entity` / `entity`; one profile has no current prisoner/entity.
- XML-bearing columns: `user_profile.template_xml` is non-null for `73/73` profiles with length range `2541-2673`; `prisoner_skill.xml` has `72/1656` non-null values with length `15-65`; `item_entity.xml` has `42304/62844` non-null values with length `136-4781`.
- Squad content: `squad` has `7` rows; `squad_member` has `18` rows; observed rank distribution is `1:6`, `2:2`, `3:4`, `4:6`, but rank meanings remain unknown.
- Economy content: `bank_account_registry` has `73` account rows and `bank_account_registry_currencies` has `146` rows; observed currency types are numeric `1` and `2`, but labels/units and command confirmation remain unknown.
- Coordinate content: joined prisoner positions, vehicle positions, base/base-element positions, and spawn-location coordinates have verified numeric ranges, but DB cadence did not prove sub-10s realtime updates.
## XML content structure
The XML diagnostic sampled only tag names, attribute names, parser success counts, and value-shape digests. It did not emit XML documents or attribute values.
| table | column | sampled | parse_ok | root_tags | element_tags | attribute_names | value_shape_digest |
|---|---|---:|---:|---|---|---|---|
| user_profile | template_xml | 73 | 73 | CharacterTemplate x73 | Skill x1533; CharacterTemplate x73 | Name x1606; Attribute x1533; ClassName x1533; Level x1533; Experience x1533; Strength x73; Constitution x73; Dexterity x73; Intelligence x73; Age x73; Gender x73; AppearanceIndex x73; TattooIndex x73; BodyHairIndex x73; HairStyleIndex x73; MoustacheStyleIndex x73; BeardStyleIndex x73; BreastSize x73; PenisSize x73; GrowOverTime x73; BirthDate x73; ArrestDate x73; FaceType x73; SkinTone x73; HairColor x73 | sha256:9f839093a598edf3 |
| prisoner_skill | xml | 72 | 0 | - | - | - | sha256:e3b0c44298fc1c14 |
| item_entity | xml | 100 | 100 | Item x100 | Item x100; ContinuousFuelConsumption x25; Component x17; Stacks x15; ContainedItemsMetadata x15; ItemComponents x11; Locks x6; ContinuousFuelConsumptions x5; HeatSource_0 x5; HeatSource_1 x5; HeatSource_2 x5; HeatSource_3 x5; HeatSource_4 x5 | _bloodStage x100; _dryBloodStage x100; _isCrafted x100; _uncraftTime x100; _lastAccessTime x100; _healthRatioWhenCrafted x100; UniqueId x25; CurrentEnergyConsumptionRate x25; HeatSourceID x25; DialValue x25; FuelConsumptionCreated x25; Name x17; _radiation x15; _weight x15; _weightUsed x15; _isPartOfEvent x15; WaterWeight x15; StacksCount x15; _owningUserProfileId x6; _activeAccessLevel x6; _pendingContainedItemsRadiationAmount x6; _forbiddenZoneEnterTimestamp x6; _protectingFlagId x6; _colorIndex x6; _name x6 | sha256:5a62ccfa73af3694 |
## XML conclusions
- `user_profile.template_xml` is the only sampled profile-level XML source that parses cleanly and exposes named character attributes plus skill entries.
- The content features support future named-field adapter design for attributes such as `Strength`, `Constitution`, `Dexterity`, `Intelligence`, and existing `Skill` attributes, but they do not by themselves prove safe write semantics, backup/offline requirements, readback behavior, or a `855` preset mapping.
- `prisoner_skill.xml` is not a valid XML document in the sampled current-service rows, so it cannot be treated as the preserving XML mutation source.
- `item_entity.xml` parses as item metadata and is not a profile attribute source.
## Log content skeleton features
The log diagnostic sampled bounded prefixes from process-adjacent logs, grouped by filename pattern. Skeletons replace quoted text, numbers, network-shaped tokens, long hex identifiers, and ASCII words; marker sets record structural tokens only.
| filename_pattern | sampled_files | sampled_lines | bytes | encodings | marker_sets | skeleton_digest | top_skeletons |
|---|---:|---:|---:|---|---|---|---|
| admin_{digits}.log | 15 | 48 | 6816 | utf-16-le x15 | date x18; date,network x15; date,login-event x15 | sha256:ffaf5a692fdcf219 | date/network boilerplate x15; admin-login-event skeleton x15; admin-action skeleton x12 |
| armor_absorption_{digits}.log | 15 | 15 | 1500 | utf-16-le x15 | date,network x15 | sha256:2c509fc280f438aa | shared date/network boilerplate x15 |
| base_building_destruction_{digits}.log | 15 | 15 | 1500 | utf-16-le x15 | date,network x15 | sha256:2c509fc280f438aa | shared date/network boilerplate x15 |
| chat_{digits}.log | 15 | 24 | 2706 | utf-16-le x15 | date,network x15; date x9 | sha256:8e42f8c5ba48c29b | shared date/network boilerplate x15; redacted chat skeleton x9 |
| chest_ownership_{digits}.log | 15 | 15 | 1500 | utf-16-le x15 | date,network x15 | sha256:2c509fc280f438aa | shared date/network boilerplate x15 |
| connection_log.txt | 5 | 100 | 82695 | utf-8-sig x5 | date,time x65; date,time,login-event x35 | sha256:80153240fb51639e | service connection event skeletons x35/x35/x10 |
| connection_log_{n}.txt | 10 | 200 | 1248965 | utf-16-le x5; utf-8-sig x5 | none x100; date,time x90; date,time,network x5; date,time,login-event x5 | sha256:346312bbea656ecd | mixed encoded service connection skeletons |
| economy_{digits}.log | 15 | 15 | 1500 | utf-16-le x15 | date,network x15 | sha256:2c509fc280f438aa | shared date/network boilerplate x15 |
| event_kill_{digits}.log | 12 | 12 | 1200 | utf-16-le x12 | date,network x12 | sha256:2c509fc280f438aa | shared date/network boilerplate x12 |
| famepoints_{digits}.log | 15 | 15 | 1500 | utf-16-le x15 | date,network x15 | sha256:2c509fc280f438aa | shared date/network boilerplate x15 |
| gameplay_{digits}.log | 15 | 159 | 987486 | utf-16-le x15 | date x78; date,coordinates x66; date,network x15 | sha256:b8ae42ecfeb39fad | gameplay header skeleton x33; coordinate event skeletons x18/x18 |
| kill_{digits}.log | 12 | 12 | 1200 | utf-16-le x12 | date,network x12 | sha256:2c509fc280f438aa | shared date/network boilerplate x12 |
| login_{digits}.log | 12 | 21 | 3456 | utf-16-le x12 | date,network x12; date,login-event,coordinates,network x9 | sha256:e4f04da6e2da7470 | shared date/network boilerplate x12; login/logout coordinate skeletons x6/x3 |
| loot_{digits}.log | 15 | 186 | 49164 | utf-16-le x15 | date x171; date,network x15 | sha256:36e500f92b6c82f3 | loot interaction skeletons x108/x18; shared date/network boilerplate x15 |
| network_objects_{digits}.log | 15 | 15 | 1500 | utf-16-le x15 | date,network x15 | sha256:2c509fc280f438aa | shared date/network boilerplate x15 |
| quests_{digits}.log | 15 | 15 | 1500 | utf-16-le x15 | date,network x15 | sha256:2c509fc280f438aa | shared date/network boilerplate x15 |
| raid_protection_{digits}.log | 15 | 33 | 2868 | utf-16-le x15 | date x18; date,network x15 | sha256:80b32ec451bdbd18 | shared date/network boilerplate x15; raid protection status skeletons x9/x9 |
| sentry_{digits}.log | 15 | 15 | 1500 | utf-16-le x15 | date,network x15 | sha256:2c509fc280f438aa | shared date/network boilerplate x15 |
| server_notifications_{digits}.log | 15 | 15 | 1500 | utf-16-le x15 | date,network x15 | sha256:2c509fc280f438aa | shared date/network boilerplate x15 |
| service_log.txt | 5 | 100 | 181445 | utf-8-sig x5 | time,login-event x100 | sha256:096a96f507532516 | service login-state skeletons x35/x35/x30 |
| stats_log.txt | 5 | 100 | 769140 | utf-16-le x5 | none x100 | sha256:3eed2125dbb41774 | encoded/stat payload skeletons x95/x5 |
| vehicle_destruction_{digits}.log | 15 | 72 | 503544 | utf-16-le x15 | date,coordinates x57; date,network x15 | sha256:af9b5eb7bece3c6d | vehicle coordinate event skeletons x18/x15; shared date/network boilerplate x15 |
| violations_{digits}.log | 12 | 12 | 1200 | utf-16-le x12 | date,network x12 | sha256:2c509fc280f438aa | shared date/network boilerplate x12 |
Additional runtime/backup logs (`SCUM.log`, backup SCUM logs, `UE{n}SS.log`, `configstore_log.txt`, `systemmanager.txt`, and empty dispatch test stdout/stderr logs) were observed as separate service/runtime families. Their sampled content either did not decode into useful event skeletons under the bounded text decoder or contained no sampled lines; they are not candidate gameplay/event parsers without a separate parser contract.
## Log conclusions
- `login_{digits}.log` remains the authenticated player-session parser source because it has login/logout, coordinate, date, and network-shaped content markers matching the existing sanitized fixtures.
- `gameplay_{digits}.log` and `vehicle_destruction_{digits}.log` contain coordinate-shaped events, but they are separate parser candidates and must not be conflated with login/session events.
- Many gameplay logs start with a repeated date/network boilerplate shape, so parsers must strip or reject network-shaped tokens before persistence or logical event fingerprinting.
- Service/runtime logs (`connection_log*.txt`, `service_log.txt`, `SCUM.log`, stats/config/system logs) are structurally distinct from gameplay event files and require separate declarations if used.
@@ -1,173 +0,0 @@
# SCUM current-service DB schema baseline (redacted compact)
- diagnostic: scum-current-service-db-schema-compact-v1
- observed_utc: 2026-08-13T03:26:25Z
- db_path_sha256: 7c3880848ad9c049eeb66769a2b4460fa2c56009d0c022a13362aba8686efbd7
- file_size_bytes: 80846848
- mtime_unix: 1786591584
- table_count: 161
- redaction: no raw rows, SQL text, XML, host paths, credentials, sockets, IPs, or player identities
| table | rows | columns | primary_key_columns | foreign_key_count | index_count |
|---|---:|---|---|---:|---:|
| abandoned_bunker | 15 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER NN; location_x INTEGER NN; location_y INTEGER NN; is_day INTEGER NN; time_since_previous_activation_end REAL NN; time_until_activation_start REAL NN; keycard_override_activation_start REAL | id | 2 | 1 |
| abandoned_bunker_alarmed_room | 0 | room_name TEXT NN; bunker_id INTEGER NN; alarm_time_remaining REAL NN | - | 1 | 1 |
| abandoned_bunker_bcu_terminal | 4 | room_name TEXT NN; bunker_id INTEGER NN; last_download_time REAL NN | - | 1 | 2 |
| abandoned_bunker_mesh_instance_bound_to_activation | 0 | abandoned_bunker_id INTEGER PK NN; mesh_instance_name TEXT PK NN; examine_time REAL NN | abandoned_bunker_id, mesh_instance_name | 1 | 1 |
| abandoned_bunker_powered_room | 0 | room_name TEXT NN; bunker_id INTEGER NN | - | 1 | 1 |
| abandoned_bunker_switchboard_fuse | 0 | room_name TEXT NN; bunker_id INTEGER NN; fuse_id INTEGER NN | - | 2 | 2 |
| active_quest | 0 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER NN; quest_data_asset_path TEXT NN; auto_complete BOOLEAN NN; completion_deadline REAL NN; sector TEXT NN; quest_giver_type INTEGER NN; rewards_index INTEGER NN | id | 3 | 1 |
| active_task | 1 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER NN; available_task_id INTEGER NN | id | 4 | 2 |
| ammunition_data | 1673 | id INTEGER PK NN; ammunition_item_entity_class TEXT NN; health REAL NN; max_health REAL NN; default_max_health REAL NN; state INTEGER NN; entity_id INTEGER | id | 1 | 1 |
| ammunition_item_entity | 2754 | entity_id INTEGER PK NN | entity_id | 1 | 0 |
| animal_bait_feeder_item_entity | 67 | entity_id INTEGER PK NN; state INTEGER | entity_id | 1 | 0 |
| available_task | 1 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER NN; task_data_asset_path TEXT NN; was_ever_completed BOOLEAN NN | id | 2 | 1 |
| bank_account_registry | 73 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; account_owner_user_profile_id INTEGER NN; bank_account_number INTEGER NN; save_timestamp INTEGER; used_digital_deluxe_privileges BOOLEAN | id | 3 | 3 |
| bank_account_registry_cards | 92 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; bank_account_id INTEGER NN; card_type TEXT; pin_number INTEGER; wrong_pins_remaining INTEGER; free_renewals_remaining INTEGER; daily_withdraw_amount_remaining INTEGER; daily_deposit_amount_remaining INTEGER; card_entity_id INTEGER | id | 4 | 3 |
| bank_account_registry_currencies | 146 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; bank_account_id INTEGER NN; currency_type INTEGER NN; account_balance INTEGER | id | 3 | 2 |
| bank_general_data | 1 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; last_generated_final_set_of_bank_account_numbers INTEGER; last_withdrawn_amount_reset_timestamp INTEGER | id | 2 | 1 |
| base | 5 | id INTEGER PK; location_x REAL; location_y REAL; size_x NUMERIC; size_y REAL; name TEXT; map_id INTEGER; user_profile_id INTEGER; owner_user_profile_id INTEGER; is_owned_by_player INTEGER; bounds_min_x REAL; bounds_min_y REAL; bounds_max_x REAL; bounds_max_y REAL | id | 2 | 1 |
| base_element | 1533 | element_id INTEGER PK; base_id INTEGER NN; location_x REAL; location_y REAL; location_z REAL; rotation_pitch REAL; rotation_yaw REAL; rotation_roll REAL; scale_x REAL; scale_y REAL; scale_z REAL; asset TEXT; element_health NUMERIC; owner_profile_id INTEGER; quality REAL; creator_prisoner_id INTEGER | element_id | 2 | 2 |
| base_element_coloring | 7 | element_id INTEGER PK; element_part_index INTEGER PK NN; element_color_index INTEGER NN; element_pattern_index INTEGER NN | element_id, element_part_index | 1 | 1 |
| base_element_flag | 5 | element_id INTEGER; overtake_end_time INTEGER; overtaker_user_profile_id INTEGER; expanded_elements INTEGER | - | 2 | 2 |
| base_element_item | 6 | element_id INTEGER PK; item_entity_id INTEGER PK | element_id, item_entity_id | 2 | 2 |
| base_element_shelter_map | 1 | element_id INTEGER PK NN; shelter_id INTEGER PK NN | element_id, shelter_id | 2 | 2 |
| base_raid_protection | 0 | id INTEGER PK NN; manager_id INTEGER NN; base_flag_id INTEGER; data BLOB | id | 1 | 1 |
| base_raid_protection_manager | 1 | id INTEGER PK NN; map_id INTEGER NN; user_profile_id INTEGER; protection_type TINYINT | id | 2 | 1 |
| bcu_lock_registry | 0 | map_id INTEGER NN; user_profile_id INTEGER; server_user_profile_id INTEGER PK NN; bcu_lock_entity_id INTEGER NN; flag_element_id INTEGER NN | server_user_profile_id | 4 | 2 |
| blocked_users | 0 | local_user_id TEXT NN; target_net_id TEXT NN | - | 1 | 1 |
| chest_acquisition | 0 | base_id INTEGER PK NN; entity_id INTEGER PK NN; acquisition_start_time REAL NN; owning_user_profile_id INTEGER | base_id, entity_id | 2 | 2 |
| continuous_usage_entity_component | 21 | entity_component_id INTEGER PK NN; amount FLOAT | entity_component_id | 1 | 0 |
| cooking_instance | 1099 | id INTEGER PK NN; manager_id INTEGER NN; utility_type TEXT; bound_utility INTEGER; bound_recipe INTEGER; ingredients BLOB; temperature REAL; softPeakTemperature REAL; progress REAL; cook_quality INTEGER; owner_utility INTEGER; tag_index INTEGER; internal_coords BLOB; packed_locations BLOB; radius REAL; finished BOOLEAN; can_bound_other BOOLEAN; bounded_to INTEGER; cooked_time REAL; exhaustion_bonus REAL | id | 1 | 2 |
| cooking_manager | 3 | id INTEGER PK NN; map_id INTEGER NN; user_profile_id INTEGER; snapped_keys BLOB; snapped_values BLOB | id | 2 | 1 |
| custom_zone_configuration | 2 | id INTEGER PK NN; map_id INTEGER PK NN; name CHAR(100); color_red REAL; color_green REAL; color_blue REAL; handling_methods BIGINT; settings INTEGER | id, map_id | 1 | 2 |
| custom_zone_configuration_damage_handling_methods | 32 | id INTEGER PK NN; custom_zone_configuration_id INTEGER NN; map_id INTEGER NN; damage_actor_type INTEGER; damage_handling_methods INTEGER | id | 2 | 0 |
| custom_zone_region | 4 | id INTEGER PK NN; map_id INTEGER PK NN; name CHAR(100); location_x REAL; location_y REAL; size_x REAL; size_y REAL; configuration_index TINYINT; default_region_name CHAR(50); default_region_state TINYINT | id, map_id | 1 | 2 |
| db_info | 1 | last_vacuum_time TEXT; next_free_id INTEGER | - | 0 | 0 |
| discrete_amount_entity_component | 13829 | entity_component_id INTEGER PK NN; quantity INTEGER NN | entity_component_id | 1 | 0 |
| dog_tag_item_entity | 0 | entity_id INTEGER PK NN; victim_user_profile_id INTEGER; victim_name TEXT; victim_fame_points INTEGER | entity_id | 2 | 1 |
| door_locking_registry_data | 33 | asset TEXT PK NN; count INTEGER NN; type INTEGER PK NN; map_id INTEGER PK NN; user_profile_id INTEGER PK | asset, type, map_id, user_profile_id | 2 | 1 |
| economy | 1 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; save_timestamp INTEGER; time_since_last_economy_reset INTEGER NN | id | 2 | 1 |
| economy_outpost_gold | 4 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; outpost_id INTEGER NN; gold_buying_capability_funds INTEGER; gold_selling_capability_funds INTEGER; gold_selling_capability_funds_restock_amount REAL | id | 3 | 2 |
| economy_outposts | 4 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; outpost_runtime_id TEXT; buying_capability REAL; outpost_bank_funds REAL; economy_reset_elapsed_time REAL; prices_randomization_elapsed_time REAL; save_timestamp INTEGER; price_delta_seed REAL; tradeable_rotation_elapsed_time REAL | id | 2 | 1 |
| economy_special_deals | 85 | id INTEGER PK NN; map_id INTEGER NN; user_profile_id INTEGER NN; sector TEXT NN; tradeable_asset TEXT NN; base_purchase_price INTEGER; amount_in_store INTEGER; override_purchase_ability BOOLEAN; can_be_purchased_by_player BOOLEAN; required_fame_points INTEGER; trader TEXT NN | id | 2 | 1 |
| economy_tradeables_info | 12453 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; trader_id INTEGER NN; tradeable_asset TEXT; amount_in_store INTEGER NN; restock_amount REAL; is_omitted_from_current_rotation BOOLEAN; partial_amount_in_store REAL | id | 3 | 2 |
| economy_traders | 36 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; trader_runtime_id TEXT; available_funds INTEGER | id | 2 | 1 |
| elevated_users | 4 | user_id TEXT PK NN | user_id | 0 | 1 |
| entity | 63379 | id INTEGER PK NN; entity_system_id INTEGER NN; class TEXT NN; owning_entity_id INTEGER; parent_entity_id INTEGER; location_x REAL NN; location_y REAL NN; location_z REAL NN; rotation_x REAL NN; rotation_y REAL NN; rotation_z REAL NN; scale_x REAL NN; scale_y REAL NN; scale_z REAL NN; flags INTEGER NN; data BLOB; reason TEXT | id | 3 | 3 |
| entity_character_inventory_component | 72 | entity_component_id INTEGER NN; last_entity_on_lshoulder INTEGER; last_entity_on_rshoulder INTEGER | - | 3 | 0 |
| entity_component | 62174 | id INTEGER PK NN; entity_id INTEGER NN; name TEXT NN; class TEXT NN; flags INTEGER NN; data BLOB | id | 1 | 1 |
| entity_component_to_delete_on_startup | 0 | entity_component_id INTEGER PK NN | entity_component_id | 1 | 0 |
| entity_decay_manager_entry | 41286 | entity_id INTEGER PK NN; timestamp REAL NN; damage_per_day REAL NN | entity_id | 1 | 0 |
| entity_inventory_component_entry | 2034 | entity_component_id INTEGER PK NN; entity_id INTEGER PK NN; data INTEGER NN | entity_component_id, entity_id | 2 | 2 |
| entity_system | 1 | id INTEGER PK NN; map_id INTEGER NN; user_profile_id INTEGER; timestamp REAL NN | id | 2 | 1 |
| entity_to_delete_on_startup | 6 | entity_id INTEGER PK NN | entity_id | 1 | 0 |
| event | 0 | id INTEGER PK NN | id | 0 | 0 |
| event_participant | 0 | event_id INTEGER PK NN; user_profile_id INTEGER PK NN | event_id, user_profile_id | 2 | 2 |
| event_rankings_cached | 73 | user_id TEXT NN; user_profile_id INTEGER PK NN; name TEXT NN; is_banned INTEGER NN; fame_points REAL NN; score REAL NN; enemy_kills INTEGER NN; team_kills INTEGER NN; deaths INTEGER NN; suicides INTEGER NN; assists INTEGER NN; headshots INTEGER NN; ctf_pickups INTEGER NN; ctf_captures INTEGER NN; ctf_returns INTEGER NN; dm_longest_headshot REAL NN; dm_melee_kills INTEGER NN; dm_longest_life REAL NN; dz_activations INTEGER NN | user_profile_id | 2 | 1 |
| event_round | 0 | id INTEGER PK NN; event_id INTEGER NN; start_time TEXT; end_time TEXT | id | 1 | 1 |
| event_round_stats | 0 | round_id INTEGER PK NN; user_profile_id INTEGER PK NN; score REAL; enemy_kills INTEGER; team_kills INTEGER; deaths INTEGER; suicides INTEGER; assists INTEGER; headshots INTEGER | round_id, user_profile_id | 2 | 2 |
| event_round_stats_ctf | 0 | round_id INTEGER PK NN; user_profile_id INTEGER PK NN; pickups INTEGER; captures INTEGER; returns INTEGER | round_id, user_profile_id | 2 | 2 |
| event_round_stats_dm | 0 | round_id INTEGER PK NN; user_profile_id INTEGER PK NN; longest_headshot REAL; melee_kills INTEGER; longest_life REAL | round_id, user_profile_id | 2 | 2 |
| event_round_stats_dz | 0 | round_id INTEGER PK NN; user_profile_id INTEGER PK NN; activations INTEGER | round_id, user_profile_id | 2 | 2 |
| events_stats | 73 | user_profile_id INTEGER PK NN; events_won INTEGER; events_lost INTEGER; enemy_kills INTEGER; deaths INTEGER; ctf_captures INTEGER; team_kills INTEGER | user_profile_id | 1 | 0 |
| expirable_entity_component | 71 | entity_component_id INTEGER PK NN; start_play_time REAL; duration REAL | entity_component_id | 1 | 0 |
| expirable_vehicle_spawner_info | 0 | map_id INTEGER PK; user_profile_id INTEGER PK; spawner_name TEXT PK; num_spawners_created INTEGER | map_id, user_profile_id, spawner_name | 2 | 1 |
| finished_timed_gift_spawner | 2 | map_id INTEGER PK; user_profile_id INTEGER PK; spawn_time INTEGER PK | map_id, user_profile_id, spawn_time | 2 | 1 |
| fishing_stats | 73 | user_profile_id INTEGER PK NN; fish_caught INTEGER; fish_kept INTEGER; fish_released INTEGER; lines_broken INTEGER; heaviest_fish_caught REAL; longest_fish_caught REAL; bass_caught INTEGER; catfish_caught INTEGER; pike_caught INTEGER; carp_caught INTEGER; amur_caught INTEGER; bleak_caught INTEGER; chub_caught INTEGER; ruffe_caught INTEGER; prussian_carp_caught INTEGER; crucian_carp_caught INTEGER; sardine_caught INTEGER; dentex_caught INTEGER; orata_caught INTEGER; tuna_caught INTEGER | user_profile_id | 1 | 0 |
| food_item_entity | 5693 | entity_id INTEGER PK NN; damage_over_time_outside_refrigerator REAL; is_opened INTEGER | entity_id | 1 | 0 |
| garden | 2 | id INTEGER PK NN; garden_manager_id INTEGER NN; owner_user_profile_id INTEGER; owner_skill_level INTEGER; num_slots_x INTEGER; num_slots_y INTEGER; location_x REAL; location_y REAL; location_z REAL; rotation_r REAL; rotation_p REAL; rotation_y REAL; crafted_age REAL; has_greenhouse BOOL; pest_disease_check_timer REAL; health REAL NN | id | 2 | 2 |
| garden_manager | 1 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER NN; sim_data_sun_irradiance REAL; sim_data_rain_average REAL; sim_data_time_range REAL | id | 2 | 1 |
| garden_manager_height_relative_sim_data | 16 | id INTEGER PK NN; garden_manager_id INTEGER NN; height REAL; temperature REAL; water_evaporation REAL | id | 1 | 1 |
| garden_slot | 110 | id INTEGER PK NN; garden_id INTEGER NN; planter_user_profile_id INTEGER; planter_skill_level INTEGER; slot_position_x INTEGER; slot_position_y INTEGER; species TEXT; stage INTEGER; growth_percentage REAL; water REAL; organic_fertilizer BOOL; industrial_fertilizer BOOL; weed_intenstiy REAL; pesticide_timer REAL; fungicide_timer REAL; weed_repellent_timer REAL; health REAL; dehidration_death_timer REAL; freezing_death_timer REAL; pest_death_timer REAL; disease_death_timer REAL; old_age_death_timer REAL; weed_check_timer REAL; dead BOOL | id | 2 | 2 |
| garden_slot_pest | 330 | id INTEGER PK NN; garden_slot_id INTEGER NN; pest_species TEXT; pest_intensity REAL; disease_species TEXT; disease_intensity REAL | id | 1 | 1 |
| global_aquatic_life_manager | 6 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER NN | id | 2 | 0 |
| global_aquatic_life_manager_special_volume_types | 6 | id INTEGER PK NN; global_aquatic_life_manager_id INTEGER_NOT_NULL; volume_type TEXT; activation_timestamp REAL | id | 1 | 0 |
| global_aquatic_life_manager_special_volumes | 54 | id INTEGER PK NN; global_aquatic_life_manager_special_volume_type_id INTEGER_NOT_NULL; persistent_id TEXT | id | 1 | 0 |
| global_encounter_manager | 1 | id INTEGER PK NN; map_id INTEGER NN; user_profile_id INTEGER; max_group_id INTEGER | id | 2 | 1 |
| global_encounter_manager_bb_data | 0 | id INTEGER PK NN; global_encounter_manager_id INTEGER NN; base_id INTEGER NN; at_least_one_base_member_present_time REAL; encounter_cooldown REAL; base_lifetime REAL | id | 1 | 2 |
| global_encounter_manager_bb_data_flags | 0 | id INTEGER PK NN; global_encounter_manager_id INTEGER NN; global_encounter_manager_bb_data_id INTEGER NN; flag_id INTEGER NN | id | 2 | 2 |
| global_encounter_manager_rogue_characters | 0 | id INTEGER PK NN; global_encounter_manager_id INTEGER NN; character_class STRING; character_location_x REAL; character_location_y REAL; character_location_z REAL; character_rotation_yaw REAL; character_data BLOB; preset_type TEXT; despawn_lifetime REAL; despawn_lifetime_remaining REAL | id | 1 | 1 |
| global_encounter_manager_visited_points | 0 | id INTEGER PK NN; global_encounter_manager_id INTEGER NN; location_x REAL; location_y REAL; location_z REAL; xy_size REAL; z_size REAL; stay_alive_timestamp REAL; remove_time REAL; is_subzone_point BOOLEAN | id | 1 | 1 |
| global_encounter_manager_zone_cooldown | 0 | id INTEGER PK NN; global_encounter_manager_id INTEGER NN; zone_location_x REAL; zone_location_y REAL; zone_location_z REAL; sub_zone_index INTEGER; cooldown REAL | id | 1 | 1 |
| global_radiation_data | 1 | map_id INTEGER PK NN; user_profile_id INTEGER PK; timestamp INTEGER NN | map_id, user_profile_id | 2 | 1 |
| gold_price_master_multipliers | 0 | id INTEGER PK NN; date INTEGER; multiplier REAL | id | 0 | 0 |
| heat_source | 4769 | id INTEGER PK NN; map_id INTEGER; user_profile_id INTEGER; location_x REAL; location_y REAL; location_z REAL; temperature REAL; burning_speed REAL; distance_scale REAL; inner_radius REAL; outer_radius REAL; fuel_capacity REAL; temperature_curve_path TEXT; fuel BLOB; uses_fuel_simulation BOOL NN; operating_temperature REAL | id | 2 | 1 |
| ignitable_component_entry | 4 | entity_component_id INTEGER PK NN; was_ever_ignited INTEGER | entity_component_id | 1 | 0 |
| item_container_upgrades | 0 | id INTEGER PK NN; item_container_id INTEGER NN; asset TEXT; num_tries INTEGER | id | 1 | 1 |
| item_containers | 0 | id INTEGER PK NN; map_id INTEGER NN; user_profile_id INTEGER; runtime_id TEXT NN; lock_reset_time INTEGER | id | 2 | 1 |
| item_entity | 62853 | entity_id INTEGER PK NN; health REAL; max_health REAL; radiation_amount REAL; xml TEXT; weight REAL; water_weight REAL; external_weight REAL; total_weight REAL; max_uses INTEGER; flags INTEGER; body_damage_data BLOB | entity_id | 1 | 0 |
| item_entity_spawner | 136794 | id INTEGER PK NN; name TEXT NN; entity_system_id INTEGER NN; evaluation_time REAL NN; num_evaluations INTEGER | id | 1 | 1 |
| item_entity_spawner_cooldown | 17 | item_entity_spawner_id INTEGER PK NN; key INTEGER PK NN; value REAL NN | item_entity_spawner_id, key | 1 | 2 |
| item_entity_spawner_entry | 155893 | item_entity_spawner_id INTEGER PK NN; idx INTEGER PK NN; entity_id INTEGER | item_entity_spawner_id, idx | 2 | 3 |
| item_radiation_exposure_data | 0 | item_id_1 INTEGER PK NN; item_id_2 INTEGER PK NN; map_id INTEGER PK NN; user_profile_id INTEGER PK; radiation_amount REAL NN; pending_radiation_amount REAL NN; modified_timestamp INTEGER NN | item_id_1, item_id_2, map_id, user_profile_id | 2 | 1 |
| item_spawner_evaluation_result_entity_component | 20522 | entity_component_id INTEGER PK NN; usage_ratio REAL NN; health_ratio REAL NN | entity_component_id | 1 | 0 |
| item_spawner_evaluation_result_entity_component_post_spawn_action | 30782 | entity_component_id INTEGER PK NN; idx INTEGER PK NN; action TEXT NN | entity_component_id, idx | 1 | 1 |
| item_spawning_cooldown_groups | 18 | entity_system_id INTEGER NN; idx INTEGER NN; cooldown_min INTEGER NN; cooldown_max INTEGER NN | - | 1 | 1 |
| key_card_item_entity | 4 | entity_id INTEGER PK NN; spawn_reason TEXT | entity_id | 1 | 0 |
| killbox | 12 | name TEXT PK NN; map_id INTEGER PK NN; user_profile_id INTEGER PK; is_active BOOL; is_finale BOOL; remaining_time REAL; rooms_difficulty_packed INTEGER; rooms_state_packed INTEGER | name, map_id, user_profile_id | 2 | 1 |
| local_chat_history | 0 | chat_line TEXT NN | - | 0 | 0 |
| map | 1 | id INTEGER PK NN; name TEXT | id | 0 | 0 |
| muted_users | 0 | user_id_hashed TEXT PK; user_profile_name TEXT | user_id_hashed | 0 | 1 |
| notification | 0 | id INTEGER PK NN; user_profile_id INTEGER NN; data BLOB; timestamp INTEGER | id | 1 | 1 |
| penalty_squad_leave_info | 0 | user_id TEXT PK; squadmates_left INTEGER NN | user_id | 1 | 1 |
| placeable | 16 | id INTEGER PK NN; prisoner_id INTEGER NN; map_id INTEGER NN; asset TEXT; location_x REAL; location_y REAL; location_z REAL; rotation_pitch REAL; rotation_yaw REAL; rotation_roll REAL; placement_location_x REAL; placement_location_y REAL; placement_location_z REAL; process BLOB | id | 2 | 1 |
| placeable_basebuilding | 16 | placeable_id INTEGER NN; first_point_location_x REAL; first_point_location_y REAL; first_point_location_z REAL; state_flags INTEGER; first_point_rotation_pitch REAL; first_point_rotation_yaw REAL; first_point_rotation_roll REAL | - | 1 | 1 |
| placeable_garden | 0 | id INTEGER PK NN; placeable_id INTEGER NN; x_min INTEGER; y_min INTEGER; x_max INTEGER; y_max INTEGER | id | 1 | 1 |
| placeable_upgrade | 0 | placeable_id INTEGER NN; element_base_id INTEGER NN; element_id INTEGER NN; element_location_x REAL; element_location_y REAL; element_location_z REAL | - | 1 | 1 |
| prisoner | 72 | id INTEGER PK NN; user_profile_id INTEGER; is_alive INTEGER; time_of_death TEXT; team_index INTEGER; appearance_index INTEGER; gender INTEGER; head_tattoo_index INTEGER; body_tattoo_index INTEGER; stance INTEGER; melee_target_selection_mode INTEGER; head_water_weight REAL; upper_body_water_weight REAL; lower_body_water_weight REAL; feet_water_weight REAL; penis_size REAL; breast_size INTEGER; time_of_revive TEXT; body_simulation BLOB; should_play_intro_cinematic BOOLEAN; has_open_parachute BOOLEAN; eligible_for_free_plastic_surgery BOOLEAN; last_character_dlcs_owned BOOLEAN; age TINYINT; appearance_hair_style_index TINYINT; appearance_face_type_index TINYINT; appearance_skin_tone_index TINYINT; appearance_hair_color_index TINYINT; appearance_eye_color_index TINYINT; appearance_iris_type_index TINYINT; appearance_eye_makeup_metalness TINYINT; appearance_eye_makeup_intensity TINYINT; appearance_lipstick_roughness TINYINT; appearance_lipstick_intensity TINYINT; appearance_eyeshadow_color_r TINYINT; appearance_eyeshadow_color_g TINYINT; appearance_eyeshadow_color_b TINYINT; appearance_eyeliner_color_r TINYINT; appearance_eyeliner_color_g TINYINT; appearance_eyeliner_color_b TINYINT; appearance_lipstick_color_r TINYINT; appearance_lipstick_color_g TINYINT; appearance_lipstick_color_b TINYINT; awarded_character_dlc_plastic_surgeries BOOLEAN; should_spawn_default_equipment INTEGER; last_save_time INTEGER; is_in_bed BOOLEAN; appearance_moustache_style_index INTEGER; appearance_beard_style_index INTEGER; appearance_facial_hair_color_index INTEGER; appearance_has_body_hair BOOLEAN; appearance_tattoo_indexes BLOB | id | 1 | 2 |
| prisoner_bondage | 0 | prisoner_id INTEGER PK NN; body_part INTEGER PK NN; tightness REAL; item_entity_id INTEGER NN | prisoner_id, body_part | 2 | 2 |
| prisoner_consumed_items | 205 | prisoner_id INTEGER PK NN; item_name TEXT PK NN; last_consumed_time INTEGER; consumed_amount REAL | prisoner_id, item_name | 1 | 1 |
| prisoner_disease_immunities | 26 | prisoner_id INTEGER PK NN; disease_name TEXT PK NN; last_recovered_play_time INTEGER | prisoner_id, disease_name | 1 | 1 |
| prisoner_entity | 72 | entity_id INTEGER PK NN; prisoner_id INTEGER | entity_id | 2 | 1 |
| prisoner_inventory_quick_access_slot | 31 | prisoner_entity_id INTEGER PK NN; slot_index INTEGER PK NN; item_entity_setup TEXT NN; item_entity_id INTEGER; is_in_throwing_mode INTEGER NN | prisoner_entity_id, slot_index | 2 | 2 |
| prisoner_prison_wallet | 17 | prisoner_entity_id INTEGER PK NN; is_deluxe_item_pending INTEGER NN | prisoner_entity_id | 1 | 0 |
| prisoner_respawn_info | 70 | prisoner_id INTEGER PK; penalty_random INTEGER; penalty_sector INTEGER; penalty_shelter INTEGER; penalty_squad INTEGER; last_use_random TEXT; last_use_sector TEXT; last_use_shelter TEXT; last_use_squad TEXT; commit_suicide_penalty INTEGER; commit_suicide_last_use TEXT; commit_suicide_cooldown_left FLOAT | prisoner_id | 1 | 0 |
| prisoner_skill | 1656 | prisoner_id INTEGER NN; name TEXT; level INTEGER; experience REAL; xml TEXT | - | 1 | 1 |
| prisoner_spawn_location | 78 | prisoner_id INTEGER PK NN; map_id INTEGER PK NN; type INTEGER PK NN; shelter_id INTEGER; location_x REAL; location_y REAL; location_z REAL; rotation_pitch REAL; rotation_yaw REAL; rotation_roll REAL; velocity_x REAL; velocity_y REAL; velocity_z REAL | prisoner_id, map_id, type | 3 | 1 |
| prisoner_stats_tracking_info | 1 | prisoner_id INTEGER PK NN; has_ever_maxed_out_core_attributes INTEGER | prisoner_id | 1 | 0 |
| prisoner_vehicle_mountee_info | 0 | prisoner_id INTEGER PK NN; vehicle_entity_id INTEGER PK NN; mount_slot_index INTEGER | prisoner_id, vehicle_entity_id | 2 | 2 |
| probation_squad_leave_info | 0 | user_id TEXT PK; start_timestamp INTEGER NN; squadmates_left INTEGER NN | user_id | 1 | 1 |
| quest_cycle_stats | 0 | id INTEGER PK NN; user_profile_id INTEGER NN; map_id INTEGER NN; associated_npc TEXT; sector TEXT; num_completed_quests INTEGER NN | id | 2 | 1 |
| quest_in_pool | 0 | id INTEGER PK NN; quest_pool_id INTEGER NN; quest_mapping_key TEXT NN; sector TEXT; rewards_index INTEGER NN; random_seed INTEGER NN | id | 1 | 1 |
| quest_lifetime_stats | 63 | id INTEGER PK NN; user_profile_id INTEGER NN; map_id INTEGER NN; associated_npc TEXT; tier INTEGER NN; sector TEXT NN; total_num_completed_quests INTEGER NN | id | 2 | 1 |
| quest_pool | 0 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER NN; quest_giver_hash INTEGER NN; quest_giver_bound_user_id INTEGER; quest_giver_type TEXT NN | id | 2 | 2 |
| quest_refresh | 1 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER NN; next_reset_timestamp REAL NN | id | 2 | 1 |
| quest_unlocked_tag | 30 | id INTEGER PK NN; user_profile_id INTEGER NN; map_id INTEGER NN; tag TEXT NN | id | 2 | 1 |
| rain_collector | 5637 | id INTEGER PK NN; map_id INTEGER PK NN; user_profile_id INTEGER PK; amount REAL; fill_rate REAL; max_amount REAL | id, map_id, user_profile_id | 2 | 1 |
| remote_sensor_registry_key_codes_to_unpair | 1 | map_id INTEGER NN; user_profile_id INTEGER; key_code TEXT NN | - | 2 | 1 |
| replenishable_resource | 584 | id INTEGER PK NN; map_id INTEGER NN; user_profile_id INTEGER; desc BLOB; amount REAL; timer REAL; save_time INTEGER | id | 2 | 1 |
| restorable_mesh_instance | 0 | id INTEGER PK NN; map_id INTEGER NN; user_profile_id INTEGER; component_name TEXT; packed_location INTEGER; location_x REAL; location_y REAL; location_z REAL; rotation_x REAL; rotation_y REAL; rotation_z REAL; rotation_w REAL; scale_x REAL; scale_y REAL; scale_z REAL; restore_interval REAL; restore_timer REAL; save_time INTEGER | id | 2 | 1 |
| sentries | 0 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER; sentry_location_x REAL; sentry_location_y REAL; sentry_location_z REAL; sentry_rotation_yaw REAL; sentry_health REAL; sentry_longrangeweapon_ammo INTEGER | id | 2 | 1 |
| sentry_ai_controllers | 0 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER; sentry_id INTEGER; sentry_state INTEGER; player_last_known_location_x REAL; player_last_known_location_y REAL; player_last_known_location_z REAL; player_last_known_direction_x REAL; player_last_known_direction_y REAL; player_last_known_direction_z REAL; player_threat_level REAL; player_has_entered_hot_zone BOOL | id | 3 | 2 |
| sentry_spawners | 0 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER; spawner_location_x REAL; spawner_location_y REAL; spawner_location_z REAL; sentry_id INTEGER | id | 3 | 2 |
| server_settings | 1 | enable_item_cooldown_groups INTEGER NN; is_radiation_enabled INTEGER | - | 0 | 0 |
| shelter | 817 | id INTEGER PK NN | id | 0 | 0 |
| shown_dialogues | 0 | map_id INTEGER PK NN; user_profile_id INTEGER PK; dialogue_name TEXT PK NN | map_id, user_profile_id, dialogue_name | 2 | 1 |
| shown_survival_tips | 0 | map_id INTEGER PK NN; user_profile_id INTEGER PK; survival_tip_name TEXT PK NN; seen_in_codex BOOLEAN | map_id, user_profile_id, survival_tip_name | 2 | 1 |
| spawned_item_expiration_data | 23 | id INTEGER PK NN; map_id INTEGER NN; user_profile_id INTEGER; examiner_user_id TEXT NN; item_asset TEXT NN; item_expiration_timestamp INTEGER NN | id | 3 | 2 |
| squad | 7 | id INTEGER PK NN; name TEXT; message TEXT; emblem INTEGER; information TEXT; score REAL; member_limit INTEGER; last_member_login_time TEXT; last_member_logout_time TEXT | id | 0 | 1 |
| squad_member | 18 | id INTEGER PK NN; squad_id INTEGER NN; user_profile_id INTEGER NN; rank INTEGER | id | 2 | 2 |
| stackable_component_entry | 5120 | entity_component_id INTEGER PK NN; foreign_classes_blob BLOB | entity_component_id | 1 | 0 |
| survival_stats | 73 | user_profile_id INTEGER PK NN; highest_positive_fame_points REAL; doors_claimed INTEGER; animals_killed INTEGER; minutes_survived REAL; kills INTEGER; deaths INTEGER; locks_picked INTEGER; puppets_killed INTEGER; guns_crafted INTEGER; bullets_crafted INTEGER; arrows_crafted INTEGER; clothing_crafted INTEGER; longest_kill_distance REAL; melee_kills INTEGER; archery_kills INTEGER; players_knocked_out INTEGER; total_defecations INTEGER; total_urinations INTEGER; lights_fired INTEGER; containers_looted INTEGER; items_put_into_containers INTEGER; deaths_by_prisoners INTEGER; animals_skinned INTEGER; food_eaten REAL; distance_travelled_by_foot REAL; wounds_patched INTEGER; items_picked_up INTEGER; liquid_drank REAL; teeth_lost INTEGER; total_calories_intake INTEGER; shots_fired INTEGER; shots_hit INTEGER; headshots INTEGER; melee_weapon_swings INTEGER; melee_weapon_hits INTEGER; melee_weapons_crafted INTEGER; drone_kills INTEGER; sentry_kills INTEGER; prisoner_kills INTEGER; puppets_knocked_out INTEGER; diarrheas INTEGER; vomits INTEGER; distance_travelled_in_vehicle REAL; mushrooms_eaten INTEGER; highest_muscle_mass REAL; highest_fat REAL; heart_attacks INTEGER; overdose INTEGER; starvation INTEGER; highest_damage_taken REAL; highest_weight_carried REAL; lowest_negative_fame_points REAL; distance_travelled_swimming REAL; crows_killed INTEGER; seagulls_killed INTEGER; horses_killed INTEGER; boars_killed INTEGER; bears_killed INTEGER; goats_killed INTEGER; deers_killed INTEGER; chickens_killed INTEGER; rabbits_killed INTEGER; donkeys_killed INTEGER; times_mauled_by_bear INTEGER; longest_animal_kill_distance REAL; alcohol_drank INTEGER NN; foliage_cut INTEGER NN; distance_travel_by_boat REAL NN; distance_sailed REAL NN; times_caught_by_shark INTEGER NN; times_escaped_shark_bite INTEGER NN; wolves_killed INTEGER; last_fame_point_award_consecutive_days INTEGER; firearm_kills INTEGER; bare_handed_kills INTEGER | user_profile_id | 1 | 0 |
| tracked_quest | 37 | id INTEGER PK NN; user_profile_id INTEGER NN; map_id INTEGER NN; quest_id INTEGER NN; type INTEGER NN | id | 3 | 2 |
| tracking_data | 194 | id INTEGER PK NN; tracking_data_set_id INTEGER NN; data BLOB; version INTEGER; random_seed INTEGER NN | id | 1 | 1 |
| tracking_data_set | 38 | id INTEGER PK NN; user_profile_id INTEGER; map_id INTEGER NN; sequence_index INTEGER | id | 2 | 1 |
| user | 74 | id TEXT PK NN; name TEXT; provider TEXT; last_login_time TEXT; last_direct_connection_address TEXT; is_banned INTEGER; has_used_new_player_protection BOOLEAN; creation_time TEXT; id_type TEXT | id | 0 | 1 |
| user_accepted_policies | 0 | user_id TEXT PK NN; policy_id TEXT PK NN; accepted_version INTEGER NN | user_id, policy_id | 1 | 1 |
| user_favorite_server | 0 | user_id TEXT NN; name TEXT; host TEXT; port INTEGER | - | 1 | 1 |
| user_profile | 73 | id INTEGER PK NN; user_id TEXT; template_xml TEXT; name TEXT; type INTEGER; authority_name TEXT; authority_ip TEXT; authority_response_port INTEGER; authority_gameplay_port INTEGER; authority_user_profile_id INTEGER; authority_auth_token TEXT; last_login_time TEXT; prisoner_id INTEGER; fame_points REAL; fake_name TEXT; last_logout_time TEXT; money_balance INTEGER; global_spam_protection_state BLOB; local_spam_protection_state BLOB; last_name_change TEXT; favorite_crafting_recipes BLOB; deluxe_version BLOB; play_time INTEGER; has_used_new_player_protection BOOLEAN; creation_time TEXT | id | 2 | 3 |
| user_profiles_marked_for_deletion | 0 | id INTEGER PK NN; user_id INTEGER NN; user_profile_id INTEGER NN | id | 2 | 3 |
| user_recent_server | 0 | user_id TEXT NN; name TEXT; host TEXT; port INTEGER | - | 1 | 1 |
| vehicle_entity | 313 | entity_id INTEGER PK NN; item_container_entity_id INTEGER; data BLOB | entity_id | 2 | 1 |
| vehicle_service | 0 | map_id INTEGER PK NN; user_profile_id INTEGER PK; vehicle_id INTEGER PK NN; initiator_id INTEGER; service_station_data BLOB | map_id, user_profile_id, vehicle_id | 3 | 2 |
| vehicle_spawner | 313 | vehicle_entity_id INTEGER PK NN; vehicle_asset_id TEXT NN; vehicle_alias TEXT NN; vehicle_last_access_time INTEGER NN; is_vehicle_automatically_created BOOL NN; time_spent_in_forbidden_zone REAL NN; is_vehicle_functional BOOL NN | vehicle_entity_id | 1 | 0 |
| virtualized_encounters | 318 | id INTEGER PK NN; global_encounter_manager_id INTEGER NN; virutalized_encounter_data BLOB; reset_time REAL | id | 1 | 1 |
| virtualized_item | 3943 | item_entity_id INTEGER PK; expiration_time INTEGER; item_name TEXT; can_expire INTEGER; save_time INTEGER; bounds_size REAL; queued_visit_time INTEGER; item_user_data BLOB; owner_user_profile_id INTEGER | item_entity_id | 2 | 1 |
| weapon_attachment_item_entity | 1212 | entity_id INTEGER PK NN | entity_id | 1 | 0 |
| weapon_attachment_magazine_item_entity | 1060 | entity_id INTEGER PK NN | entity_id | 1 | 0 |
| weapon_attachment_magazine_item_entity_ammo_data | 1613 | weapon_attachment_magazine_item_entity_id INTEGER PK NN; ammunition_data_id INTEGER PK NN | weapon_attachment_magazine_item_entity_id, ammunition_data_id | 2 | 2 |
| weapon_item_entity | 432 | entity_id INTEGER PK NN | entity_id | 1 | 0 |
| weapon_item_entity_internal_magazine_ammo_data | 34 | weapon_item_entity_id INTEGER PK NN; ammunition_data_id INTEGER PK NN | weapon_item_entity_id, ammunition_data_id | 2 | 2 |
| weapon_item_entity_loaded_ammo_data | 26 | weapon_item_entity_id INTEGER PK NN; ammunition_data_id INTEGER PK NN | weapon_item_entity_id, ammunition_data_id | 2 | 2 |
| weather_parameters | 1 | map_id INTEGER PK NN; user_profile_id INTEGER PK; time_of_day REAL; moon_rotation REAL; base_air_temperature REAL; water_temperature REAL; should_cumulonimbus_cause_fog INTEGER; fog_density REAL; data BLOB | map_id, user_profile_id | 2 | 1 |
@@ -1,68 +0,0 @@
# SCUM current-service log structure baseline (redacted)
- diagnostic: scum-current-service-log-structure-v4
- observed_utc: 2026-08-13T03:24:34Z
- root_strategy: running-process-adjacent plus common profile roots
- roots_scanned: 9
- log_file_count: 1200
- redaction: no host paths, raw log lines, credentials, sockets, IPs, or player identities
## Directory fingerprints
| directory_sha256 | files | bytes | oldest_mtime | newest_mtime | filename_patterns |
|---|---:|---:|---|---|---|
| 8f7b4724b579a891c9208f9a67116925f66b4c4ed9de67024a76bc846ecbfad2 | 1136 | 23425208 | 2026-03-27T19:37:41Z | 2026-08-13T03:19:26Z | admin_{digits}.log x60; armor_absorption_{digits}.log x60; base_building_destruction_{digits}.log x60; chat_{digits}.log x60; chest_ownership_{digits}.log x60; economy_{digits}.log x60; event_kill_{digits}.log x60; famepoints_{digits}.log x60; gameplay_{digits}.log x60; kill_{digits}.log x60; login_{digits}.log x60; loot_{digits}.log x60; quests_{digits}.log x60; raid_protection_{digits}.log x60; sentry_{digits}.log x60; server_notifications_{digits}.log x60 |
| 3f15fc215272bffbd13ec0381693a72c88bd2506542387b441ea5f26c9537d29 | 52 | 7002932 | 2025-08-27T04:07:52Z | 2026-08-13T00:18:24Z | connection_log_{n}.txt x16; connection_log_{n}.previous.txt x8; configstore_log.txt x4; connection_log.previous.txt x4; connection_log.txt x4; service_log.txt x4; stats_log.previous.txt x4; stats_log.txt x4; systemmanager.txt x4 |
| 03976d194b46bbb5ec3e755c9d73dd4e3240ea209ebccf7f6d399281e590f867 | 6 | 13660622 | 2026-03-24T03:31:36Z | 2026-08-13T03:24:33Z | SCUM_{n}.log x4; SCUM.log x2 |
| 74e7a2b6564768eab96dafeb19297a6b0c8400eeeff30fc88c5a03162898b5db | 4 | 24 | 2025-07-29T16:16:59Z | 2025-07-29T16:16:59Z | steam_appid.txt x4 |
| 152191e5251dd1d77824d1ffe4726eca62e2a647205c36cf4ea153bb0b6b4e90 | 2 | 35815054 | 2025-11-21T21:37:44Z | 2025-11-21T21:37:44Z | SCUM.log x2 |
## Filename pattern inventory
| filename_pattern | files | bytes | oldest_mtime | newest_mtime | encodings_seen |
|---|---:|---:|---|---|---|
| SCUM.log | 4 | 48218920 | 2025-11-21T21:37:44Z | 2026-08-13T03:24:33Z | utf-8-sig x4 |
| SCUM_{n}.log | 4 | 1256756 | 2026-03-24T03:31:36Z | 2026-05-29T11:51:50Z | utf-8-sig x4 |
| admin_{digits}.log | 60 | 87840 | 2026-03-27T19:37:41Z | 2026-08-12T23:56:42Z | unknown x60 |
| armor_absorption_{digits}.log | 60 | 6000 | 2026-03-27T19:37:41Z | 2026-08-12T01:18:15Z | unknown x60 |
| base_building_destruction_{digits}.log | 60 | 19264 | 2026-03-27T19:37:41Z | 2026-08-12T01:18:15Z | unknown x60 |
| chat_{digits}.log | 60 | 215608 | 2026-04-02T21:46:35Z | 2026-08-12T23:45:22Z | unknown x60 |
| chest_ownership_{digits}.log | 60 | 179952 | 2026-03-27T20:59:30Z | 2026-08-12T01:18:15Z | unknown x60 |
| configstore_log.txt | 4 | 699044 | 2026-08-13T00:18:01Z | 2026-08-13T00:18:01Z | unknown x4 |
| connection_log.previous.txt | 4 | 1048280 | 2026-06-15T07:06:40Z | 2026-06-15T07:06:40Z | unknown x4 |
| connection_log.txt | 4 | 66156 | 2026-08-12T01:18:13Z | 2026-08-12T01:18:13Z | unknown x4 |
| connection_log_{n}.previous.txt | 8 | 2096872 | 2025-08-27T04:07:52Z | 2026-06-23T22:09:49Z | unknown x8 |
| connection_log_{n}.txt | 16 | 1189424 | 2026-05-27T00:15:29Z | 2026-08-13T00:18:24Z | unknown x16 |
| economy_{digits}.log | 60 | 11669828 | 2026-03-29T20:22:15Z | 2026-08-12T01:18:15Z | unknown x60 |
| event_kill_{digits}.log | 60 | 6000 | 2026-03-27T19:37:41Z | 2026-08-12T01:18:15Z | unknown x60 |
| famepoints_{digits}.log | 60 | 311680 | 2026-04-03T02:00:13Z | 2026-08-12T01:18:15Z | unknown x60 |
| gameplay_{digits}.log | 60 | 4727592 | 2026-04-06T17:39:14Z | 2026-08-13T03:19:26Z | unknown x60 |
| kill_{digits}.log | 60 | 321132 | 2026-04-05T02:33:31Z | 2026-08-12T01:18:15Z | unknown x60 |
| login_{digits}.log | 60 | 528916 | 2026-04-05T02:33:44Z | 2026-08-12T23:43:03Z | unknown x60 |
| loot_{digits}.log | 60 | 1519888 | 2026-03-27T19:37:51Z | 2026-08-12T01:18:23Z | unknown x60 |
| network_objects_{digits}.log | 56 | 5600 | 2026-05-06T02:24:44Z | 2026-08-12T01:18:15Z | unknown x56 |
| quests_{digits}.log | 60 | 50320 | 2026-03-27T19:37:41Z | 2026-08-12T01:18:15Z | unknown x60 |
| raid_protection_{digits}.log | 60 | 13600 | 2026-03-27T19:37:52Z | 2026-08-12T01:18:24Z | unknown x60 |
| sentry_{digits}.log | 60 | 6000 | 2026-03-27T19:37:41Z | 2026-08-12T01:18:15Z | unknown x60 |
| server_notifications_{digits}.log | 60 | 6000 | 2026-03-27T19:37:41Z | 2026-08-12T01:18:15Z | unknown x60 |
| service_log.txt | 4 | 145156 | 2026-08-12T01:18:13Z | 2026-08-12T01:18:13Z | unknown x4 |
| stats_log.previous.txt | 4 | 1048448 | 2026-05-08T00:23:23Z | 2026-05-08T00:23:23Z | unknown x4 |
| stats_log.txt | 4 | 615312 | 2026-08-12T23:43:24Z | 2026-08-12T23:43:24Z | unknown x4 |
| steam_appid.txt | 4 | 24 | 2025-07-29T16:16:59Z | 2025-07-29T16:16:59Z | unknown x4 |
| systemmanager.txt | 4 | 94240 | 2026-08-12T01:18:13Z | 2026-08-12T01:18:13Z | unknown x4 |
| vehicle_destruction_{digits}.log | 60 | 3446040 | 2026-04-05T02:21:34Z | 2026-08-12T01:18:24Z | unknown x60 |
| violations_{digits}.log | 60 | 303948 | 2026-03-27T19:37:41Z | 2026-08-12T01:18:15Z | unknown x60 |
## Representative sanitized line-shape observations
The first line-shape diagnostic successfully discovered the same process-adjacent log set and emitted redacted ASCII skeletons before Windows stdout encoding aborted the tail of that diagnostic. The authoritative file inventory above comes from the successful v4 diagnostic. The v2 prefix showed these structural properties without raw lines:
- `login_{digits}.log`, `admin_{digits}.log`, `gameplay_{digits}.log`, `loot_{digits}.log`, and related SCUM event logs are readable as text samples and include date-like prefixes.
- `gameplay_{digits}.log`, `vehicle_destruction_{digits}.log`, and login fixtures carry coordinate-shaped `X=/Y=/Z=` tokens in some lines.
- Several operational logs contain network-shaped tokens; parsers must strip or avoid network material before durable storage and logical fingerprints.
- `connection_log*.txt`, `service_log.txt`, `stats_log.txt`, and `systemmanager.txt` are separate service/runtime log families and must not be conflated with SCUM gameplay event files.
## Read-safety notes
- Diagnostic only grouped file metadata and BOM fingerprints; no raw log line was emitted in the committed inventory.
- Existing `scum-login-log-fixtures-2026-08-13.md` remains the source for redacted parser fixtures; this baseline records broader log inventory and structure.
@@ -1,66 +0,0 @@
# SCUM Current-Service SQLite Diagnostic Evidence — 2026-08-12
## Scope
- Evidence kind: operator-directed, server-local, read-only diagnostic discovery.
- Execution target: `枣庄服务器` through the personal server-management MCP (`list_devices`, `test_connection`, `ssh_exec`).
- Product boundary: Platform/plugin did not download or parse `SCUM.db`. The diagnostic script executed on the game server host and emitted only schema metadata, aggregates, hashes, and redacted samples.
- Release boundary: this evidence supports adapter discovery. It does not replace the Platform durable Run job / typed Run envelope required before enabling database-backed production capabilities.
## Database Identity and Read Behavior
- One active `SCUM.db` candidate was found beside the running SCUM service metadata; no host path is recorded in this artifact.
- Read mode: Python `sqlite3` URI `mode=ro`, `PRAGMA query_only=ON`; initial probes used a 2s timeout, and the cadence/lock probe used a 0.75s connection timeout plus `busy_timeout=250ms`.
- Database size: initial schema probe `80,805,888` bytes; cadence probe `80,846,848` bytes.
- SQLite metadata: `schema_version=765`, `user_version=57`, `journal_mode=wal`, `page_size=4096`, `page_count=19728`, `freelist_count=1`.
- Object inventory: `293` schema objects, `161` tables.
- Safe-read timing observed: full schema inventory `61ms`; focused groups `3ms`, `13ms`, `3ms`; join/range metrics `25ms`; follow-up join/meaning probes `27.3ms` and `5.68ms`; cadence probe p95 timings were `15.576ms` for all-entity coordinate range, `0.603ms` for player coordinate range, `0.438ms` for bounded player-position fingerprint, `0.316ms` for vehicle coordinate range, and `0.069ms` for spawn-location range. No read lock/busy failure was observed during these diagnostics.
- Fingerprints: full schema objects `57e34ee72660d7e4334644ee70cd6d285ac7961a3964fafdc3956d74e88dfa4f`; focused table groups `12a34e49f851879ae71ba287719c8d95019909f3060e823be4ce0973ce764841`, `a856bc4e105ab0a5e34b758237d3f96cff0ba5a65b38e7cf1eb81ab16b40caf4`, `60c97a8c782086c4b2600eb3a9b29c3074b971d5fdc6cf54137ce48e0970b26e`; join/range metrics `4905d09b70303b42cfb8e7fc936fe0df2065d7100c43e92ef79a464958249af4`.
## Coordinate Cadence, Snapshot, and Safe Limits
- Cadence probe: `10` read-only samples over `27.175s` against the same single active database candidate; the database file modification time changed during `5` samples, but `schema_version`, `data_version`, all-entity coordinate range, player coordinate range, player position fingerprint, vehicle coordinate range, and spawn range remained stable. Aggregate digest: `59fe6dfd8c2dc41d3533a9a4d860e82c6a5486edf079049f5c66436d67d7b100`.
- Snapshot consistency: a repeated player coordinate aggregate inside one read transaction returned identical results (`repeat_equal=true`, digest `38b1865f062aa27181f4fb5c2301b2f52a5e312bd9b4f085c62b1df6d27284eb`).
- Current coordinate ranges in the cadence probe: all `entity` rows `63370`, x `-901009.4375..612580.0625`, y `-883992.5625..615977.375`, z `-3573.64990234375..102111.6640625`, null coordinate count `0`; joined prisoners `72`, x `-872217.6875..567603.0625`, y `-843655.8125..554482.125`, z `221.87356567382812..82958.546875`, `prisoner.last_save_time` `1773202437..1786549259`; vehicle entities `313`, x `-898438..601692.3125`, y `-881533.25..605226.5`, z `-84.04053497314453..98312.640625`, functional vehicles `303`, distinct asset IDs `15`.
- Base/flag coordinate support: `base` has `5` rows with x `-381908.21875..349512.28125` and y `-565472..538980.75`; `base_element` has `1533` rows with x `-382911.5..349512.28125`, y `-566506.125..538980.75`, and z `570.5759887695312..37294.0078125`; `base_element_flag` has `5` rows and no direct coordinate columns, so a flag/territory adapter must use the verified base/base-element relationship rather than inventing separate flag coordinates.
- Spawn-location range remains non-current-position evidence: `78` rows, x `-872218..567603`, y `-843656..554482`, z `223..115567`, `2` distinct observed types.
- Safe polling limits derived for adapter design: SQLite reads should use `mode=ro`, `PRAGMA query_only=ON`, `busy_timeout<=250ms`, operation timeout `<=2000ms`, single-query target `<=750ms`, result bytes `<=262144`, and initial row limits of `500` player positions, `1000` vehicle positions, and `200` flags/base rows unless a versioned adapter proves tighter or broader bounds.
- Realtime-map conclusion: SCUM.db writes occurred during the sample window, but the verified position aggregates/fingerprints did not change. The database source does not currently prove a sub-10s realtime-map cadence; any sub-10s claim requires a separately declared and verified companion position source. Until then, the product must present the measured database cadence honestly and avoid fabricated intermediate motion or unsafe polling.
- Non-blocking probe warnings: optional exploratory fingerprint/ownership subqueries that assumed unverified vehicle row and flag-owner column names were rejected safely. Those warnings did not affect the successful coordinate/cadence aggregates and do not enable vehicle ownership, flag ownership, or write capabilities.
## Evidence Matrix
| Area | Current-service evidence | Remaining ambiguity |
| --- | --- | --- |
| External player identity | `user` has `74` rows with `id TEXT` primary key, `id_type`, `provider`, `last_login_time`, `creation_time`, `is_banned`, and network-address field present but not persisted in this artifact. Follow-up aggregates show all `74` users have `id_type=Steam`, provider `Server`, and non-null identity/login/banned fields. | Product APIs must hash or fence external IDs where appropriate and must never expose IP/network material. |
| Player profile join | `user_profile` has `73` rows; all `73` join to `user` through `user_profile.user_id -> user.id`; all profiles have `type=1`. `user_profile.prisoner_id -> prisoner.id` and `prisoner.user_profile_id -> user_profile.id` both resolve `72` profiles. Indexes on `(user_id,type,name)`, `type`, and `prisoner_id` were observed. | Profile `type=1` is observed but not independently named; adapter labels must stay version-scoped rather than using reference-project meanings. |
| Character/prisoner join | `prisoner` has `72` rows and `prisoner_entity` has `72` rows mapping `prisoner_id -> prisoner.id` and `entity_id -> entity.id`. Join metrics: `73` profiles, `73` with user, `72` with prisoner, `72` with prisoner entity, `72` with entity; exactly one profile has null `prisoner_id`. | One profile has no current prisoner/entity. Online state must still come from authenticated login/session evidence, not database timestamps alone. |
| Character XML / payload | `user_profile.template_xml` is present and non-null for `73/73` profiles, length range `25412673`; samples were hash+length only. `prisoner_skill.xml` has `72/1656` non-null rows, length `1565`; `item_entity.xml` has `42304/62844` non-null rows, length `1364781`. | `user_profile.template_xml` is the verified profile-level XML source candidate, but write semantics, named attributes, and `855` mapping remain unverified. |
| Player coordinates | `entity` has `63364+` rows with `location_x/y/z`, `rotation_x/y/z`, scale, flags, class, and optional BLOB data. The cadence probe observed `72` joined prisoners with x `-872217.6875..567603.0625`, y `-843655.8125..554482.125`, z `221.87356567382812..82958.546875`; `prisoner.last_save_time` range `1773202437..1786549259`. | Database writes occurred during the cadence window, but verified player coordinates did not change; do not claim sub-10s realtime from SCUM.db without a companion source. |
| Squad | `squad` has `7` rows; `squad_member` has `18` rows with `squad_id`, `user_profile_id`, `rank`; all members join to both squad and profile. Rank distribution: `1:6`, `2:2`, `3:4`, `4:6`; squad sizes are `1` member for `3` squads, `2` members for `2` squads, `3` members for `1` squad, and `8` members for `1` squad. | Rank meanings / leader semantics are not present in the probed schema. Keep rank labels neutral and leader unknown unless a versioned adapter proves the mapping. |
| Vehicles | `vehicle_spawner.vehicle_entity_id -> vehicle_entity.entity_id -> entity.id` resolves all `313` vehicle spawners; `15` distinct `vehicle_asset_id` values and one redacted alias value were observed. `is_vehicle_functional` distribution is `303` true / `10` false and all spawners are marked automatically created. Vehicle entity coordinate range: x `-898438..601692.3125`, y `-881533.25..605226.5`, z `-84.04053497314453..98312.640625`. | Vehicle ownership meanings are absent from the verified join. Status can be limited to the probed functional/automatic-created fields; owner stays null. |
| Flags / bases | `base_element_flag.element_id -> base_element.element_id -> base.id` resolves all `5` flags. All `5` flags have an owner profile through the verified flag/base join from the join-meaning probe; the coordinate-cadence probe separately confirmed `base` and `base_element` coordinate ranges while `base_element_flag` itself has no direct coordinate columns. | Profile ownership and coordinate support are verified only through the probed joins. Squad territory ownership remains separately gated because one owner has no squad membership and membership may not be the same fact as base ownership. |
| Economy / balances | `bank_account_registry.account_owner_user_profile_id -> user_profile.id` resolves all `73` accounts; `bank_account_registry_currencies.bank_account_id -> bank_account_registry.id -> account_owner_user_profile_id` resolves all `146` currency rows. The nullable `user_profile_id` columns in both bank tables are entirely null. Currency distribution: type `1` has `73` rows, `account_balance` range `-3000..830328`; type `2` has `73` rows, range `0..14636`. | Currency type meanings, units, safe command/readback semantics, and gift item aliases remain unverified. Query adapters may expose numeric type only behind version-scoped labels until commands/readback are proven. |
| Spawn/location table | `prisoner_spawn_location` has `78` rows with `location_x/y/z`, rotation, velocity, `type`, optional `shelter_id`; coordinate range roughly matches player entity bounds. | This is spawn-location evidence, not current position evidence. |
## Redaction Notes
- Player names, squad names/messages, map names, aliases, XML, BLOB payloads, tokens, and network-address material were represented only as hash+type+length when sampled.
- Three player join samples were retained only as hash of external player id plus numeric profile/prisoner/entity IDs, timestamps, fame points, and coordinates.
- Follow-up probes returned only aggregate counts, distributions, nullable counts, column names, coordinate ranges, and timing; no raw rows, host paths, XML, player/squad names, IP/network material, commands, credentials, or sockets were recorded.
- No raw SQL, host database path, credentials, direct sockets, raw XML, raw player names, or raw IP/network identifiers are recorded here.
## Task 2.8 Confirmation Pass — 2026-08-13
- Economy command confirmation: no Fame, normal-currency, or gold command is confirmed safe for the new adapter contract. The current SCUM live-data manifest contains only `schemaVersion`, `probe`, and `capabilityGates`; it declares no `typedRconTemplates` asset, no digest-referenced economy command, and no confirmation schema. The `economy-command.write` gate remains `disabled` / `missing` with the safe reason that Fame/currency command and readback confirmation are still awaiting verification. The current-service database evidence proves only bank-account numeric rows and currency type distributions; it does not prove currency labels, units, command execution, or readback semantics. The read-only reference project contains command-shaped hypotheses (`#SetCurrencyBalance Normal`, `#SetCurrencyBalance Gold`, `#setFamePoints`), but those are queued command strings without current-service confirmation evidence and SHALL NOT be shipped as verified typed assets.
- Gift aliases and transports: no gift item alias or executable gift transport is confirmed real for this change. The live-data manifest declares no `giftCatalogs`, no gift transport template, and no digest-referenced catalog/transport pair. The existing bridge surface still lists legacy `reward.deliver` / `player.notify` handlers, and the platform domain contains a small hard-coded catalog (`bandage`, `water-bottle`, `improvised-spear`), but those declarations are not versioned live-data assets, have no current-service alias evidence, no generated Run package digest, and no conclusive per-item receipt contract. The read-only reference project stores arbitrary gift code JSON and queues free-form `#<code><!{[]}>...` commands before conclusive game-effect confirmation; it is therefore a hypothesis source only, not verified alias or transport evidence.
- Map asset and transform authorization: no distributable SCUM map asset or coordinate transform is authorized yet. The live-data manifest declares no `mapAssets`, no map image digest, no transform asset path/digest, and no metadata schema reference. The cadence probe verifies world coordinate ranges, and the read-only reference project contains a 256-grid area transform using observed bounds, but neither proves a first-party redistributable map image, tested transform fixtures, or adapter-compatible asset identity. The realtime map SHALL remain unavailable for verified rendering until a digest-referenced map asset and transform are packaged and tested.
- `855` preset mapping: no operator-confirmed `855` mapping exists. The current-service evidence confirms `user_profile.template_xml` as the profile-level XML source candidate, and the read-only reference parser names XML attributes such as `Strength`, `Constitution`, `Dexterity`, `Intelligence`, cosmetic attributes, and skill nodes. However, neither the current-service probe, repository manifest, nor reference search produced a reviewed `855` label mapping to named attributes/values. Reference behavior also indicates attribute changes may be activated by killing the prisoner, which remains explicitly forbidden as an implicit chained action. The `profile-xml.write` gate remains disabled; `855` SHALL stay absent until an operator-confirmed preset expands into explicit before/after named attributes with separate activation evidence if any.
## Resulting Gates
- Task 2.5 schema capture is satisfied for discovery: `sqlite_schema`, read-only PRAGMA metadata, indexes, foreign keys, declared types, cardinalities, and redacted samples were captured for the candidate sources.
- Task 2.6 join/meaning verification is satisfied for discovery: external identity, profile/prisoner/entity joins, flag/base joins, vehicle identity joins, bank-account joins, nullable fields, and the profile XML source candidate are recorded. Unproven rank leader semantics, squad-territory ownership, currency labels/units, and write meanings remain explicitly gated rather than guessed.
- Task 2.7 cadence/safe-read discovery is satisfied: repeated read-only sampling measured coordinate ranges, latency, lock/busy behavior, snapshot consistency, safe limits, and the need for a companion position source before any sub-10s realtime-map claim.
- Task 2.8 confirmation is satisfied as a negative gate: economy commands, gift aliases/transports, map asset/transform authorization, and the `855` preset mapping were checked separately and none is verified enough to enable. The corresponding write/map capabilities remain disabled until explicit operator/current-service and digest-referenced adapter evidence exists.
- Database-backed SCUM read/write capabilities remain disabled until the corresponding versioned adapters and Run durable execution envelopes are implemented and accepted.
@@ -1,51 +0,0 @@
# SCUM Durable Run Schema Probe Evidence — 2026-08-12
## Scope
- Evidence kind: product-path durable Run job result accepted by Platform.
- Target server: `枣庄服务器` via the active authenticated Run binding `server-run-server-scum-1785923898033`.
- Boundary: Platform/plugin/browser did not download or parse `SCUM.db`; the database probe was produced by Run as a typed, redacted `sqlite.schema-probe` envelope and then persisted by Platform.
- Redaction: this artifact intentionally omits host paths, database paths, credentials, sockets, raw SQL, raw rows, raw XML, raw player names, and network material.
## External Run Deployment Evidence
- Independent Run repository: `git@git.npc0.com:admin343/run.git`.
- Tested Run fix: commit `8fe6f9b` (`Fix SQLite probe data target mapping`).
- Run verification performed in the independent Run repository: focused data-target/runtime tests and `go test ./...` passed before deployment.
- Installed distribution on `枣庄服务器`: `run-dist-server-scum-1785923898033-windows-amd64-1-zao-zhuang-data-target-run-fix-2026081-6988495348508259730`.
- Distribution checksum: `sha256:a5ac9fe31ed0e0f595e70e3d3322f44aa81bd165183530e4be6939aff81c3016`.
- Runtime capability evidence: the active endpoint advertises `remote.run.db.sqlite.probe` and `remote.run.db.sqlite.query` after installation.
## Platform Acceptance Evidence
- Durable job: `job-remote-adapter-server-scum-1785923898033-7249327407638289501`.
- Platform terminal state: `succeeded` with progress `100` and message `SQLite schema probe completed`.
- Terminal time: `2026-08-12T12:29:24.857542Z`.
- Probe observed time: `2026-08-12T12:17:39.0088015Z`.
- Probe status: `succeeded`.
- Source fingerprint: `sha256:d8f3e2f5e9c8241f55b931008309a7ab5f241118a82cbd3620ddedf233e74c13`.
- Schema fingerprint: `sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0`.
- Result digest: `sha256:ef13678df4add731c758bba157627dc8af80138a69476facd81bbe354c31d7f1`.
- Schema object count: `161`.
- Safe error: empty / not retryable.
## Platform Decode Fix
- Run emits `sourceFingerprint` in successful SQLite schema-probe results.
- Platform DTO/domain/validator handling now accepts and persists `sourceFingerprint` only when it is a safe digest/fingerprint.
- Validator coverage rejects raw path-shaped values such as a host database path and permits bounded generic Run `data_target_*` safe error codes without allowing path material.
## Server-Management SSH Verification
- The personal server-management MCP inventory found `枣庄服务器` with device id `FyBDIohqPhRx7Cia`.
- `test_connection` succeeded for `枣庄服务器`.
- `ssh_exec` was used for bounded, read-only PowerShell status checks only; no SCUM database query or file copy was performed.
- Remote process summary at `2026-08-12T14:13:56.4937358Z`: `SCUMServer.exe` process count `1`.
- Run journal summary: scanned `1` job journal, target job active count `0`, target pending result count `0`, total active count `0`, total pending count `1`.
- Interpretation: the durable schema-probe job is not stuck in the remote Run active queue or pending-results spool after Platform accepted the typed result. The remaining unrelated pending result, if any, is outside this evidence item.
## Resulting Gates
- This proves the product acceptance path for schema probing: Platform durable job → authenticated active Run binding → Run-side typed/redacted SQLite schema-probe envelope → Platform validation and persistence.
- This does not prove player/squad/vehicle/flag/position query adapter compatibility, rank meanings, currency semantics, map transform, gift aliases/transports, or `855` named-attribute mapping.
- Database-backed player/squad/map/gift/write capabilities remain disabled until the versioned adapters and query/mutation contracts in later task groups are implemented and matched against this evidence matrix.
@@ -1,83 +0,0 @@
# SCUM Login Log Fixture Evidence - 2026-08-13
## Scope
- Change: `replace-scum-projections-with-real-data-management`
- Task: 3.3, sanitized authentic login-log fixtures from the active service
- Device: `枣庄服务器` (`FyBDIohqPhRx7Cia`)
- Server instance: `server-scum-1785923898033`
- Run binding: `server-run-server-scum-1785923898033`
- Plugin: `game.scum` `0.1.6`
- Probe path: personal server-management MCP `list_devices`, `test_connection`, then bounded `ssh_exec`
- Observed time: `2026-08-12T23:44:07.9106530Z`
The diagnostic ran only on the configured active server through the server-management MCP. It returned no host paths, raw IP addresses, raw player names, raw Steam IDs, raw coordinates, credentials, sockets, SQL, RCON, or database content. Source and file identities are SHA-256 fingerprints of server-local paths and file metadata.
## Source Discovery
- `test_connection` succeeded for `枣庄服务器`.
- `SCUMServer.exe` was observed running during the diagnostic window.
- Recursive log discovery found SCUM `login_{date}{digits}.log` files under the active service log root.
- The newest login log is currently empty, so the next Run log-source tail must handle a zero-byte active file and later append/rotation cleanly.
```json
{
"latestLoginLog": {
"sourceIdentity": "sha256:752c3ee3789fe73b80245dfcb97776db27f977c4350c3b50516278afbecb9dad",
"streamGeneration": "sha256:57b5be4818757e4d64070e5e0f026dbd471bdba189d0426a38b618423f7e1439",
"nameTemplate": "login_{date}{digits}.log",
"bytes": 0,
"lastWriteUtc": "2026-08-12T01:18:15.6090680Z"
},
"loginFilesSeen": 30,
"filesRead": 10,
"linesRead": 30,
"encoding": "utf-16le"
}
```
## Parser Binding
The production parser asset is not implemented yet. These fixtures bind the pending parser profile that task 3.4 must implement and digest-reference before the parser can create durable players.
```json
{
"parserKey": "scum-login-log-parser.pending-real-fixture-v1",
"parserVersion": "pending-scum-login-log-v1",
"parserDigest": "sha256:5bb528cb9f6e04d8d8b819db3a71f855569c78a5135f22a982301301ae1da50a",
"lineEncoding": "utf-16le",
"acceptedTemplate": "{timestamp}: '{network_redacted} {external_player_id}:{display_name}({profile_local_id})' logged {in|out} at: X={coordinate} Y={coordinate} Z={coordinate}",
"privacyRules": {
"networkMaterial": "strip before durable storage and logical fingerprinting",
"externalPlayerId": "hash in evidence; store only through the later typed ingestion contract",
"displayName": "hash in evidence; parser may emit display name only through the safe event schema",
"coordinates": "redact in parser fixture evidence; map capability remains separately gated"
}
}
```
The logical event identity is derived from server ID, event type, and the normalized non-network event line. It intentionally excludes `sourceIdentity`, `streamGeneration`, and `sequence`, so replaying the same logical line under a later copy-truncate or rotation generation remains idempotent.
## Fixtures
All fixture rows are from active-service `login_{date}{digits}.log` files. Values below are already sanitized; the original line content was not written to the repository.
| # | Event | Source Identity | Generation | Seq | Line Digest | External Player Hash | Logical Event Identity | Occurrence Local Time |
|---|---|---|---|---:|---|---|---|---|
| 1 | `scum.login` | `sha256:485b0e95ad608bb5f1dd2a6dfe74856526ec3a0c2f7eaa80b64ce31aadd06331` | `sha256:99e8e26fb62ea9b143024dc78e87b6727c87c32d79c11a4e482ec7157b57fd30` | 3 | `sha256:4450a172273ba476f9e472ff3afcdf6a8b6e069c37e274ed95fa23a8a94b0d2e` | `sha256:2a740d7265b07f2b886e7a0f1f249321d040557f42b19c83759ffbb620bfb6e7` | `sha256:8a93cfb9deb8f82528bae3bc2273d0e0f89ffe2d4761277f994cedda84533225` | `2026.07.05-05.39.10` |
| 2 | `scum.logout` | `sha256:485b0e95ad608bb5f1dd2a6dfe74856526ec3a0c2f7eaa80b64ce31aadd06331` | `sha256:99e8e26fb62ea9b143024dc78e87b6727c87c32d79c11a4e482ec7157b57fd30` | 4 | `sha256:2e7d6690260854d3f38c7c2fd97bc8b297d718a55ca192e3e14ed79268425dde` | `sha256:2a740d7265b07f2b886e7a0f1f249321d040557f42b19c83759ffbb620bfb6e7` | `sha256:ee80c7b4b5e1176c11d4c0a3b3393182ab971bc8bb50f92ac9384b26255a6e2d` | `2026.07.05-07.21.15` |
| 3 | `scum.login` | `sha256:5b1630d3747f317fb0d2000f3c7072cd202e358e59ec43f4efff9d192164210c` | `sha256:6aed8ccee83260b16e771ed8a8d49fd26d581a9307b5c01b8294ddcc5906624f` | 3 | `sha256:450b0e4cd4e24c3f9e21b6812103214936b3b58c61e8a887d3458c9a03b2ea6d` | `sha256:f2d4c03c66c9ef6cf9339fa983ddb86ec64a2d41f4756e0831a522c604f87845` | `sha256:b35fc0e99ed878f47514bf368c472bc137a109b4ca1f7dfc84529717e1cb1f02` | `2026.06.19-12.30.45` |
| 4 | `scum.logout` | `sha256:5b1630d3747f317fb0d2000f3c7072cd202e358e59ec43f4efff9d192164210c` | `sha256:6aed8ccee83260b16e771ed8a8d49fd26d581a9307b5c01b8294ddcc5906624f` | 4 | `sha256:442994383d47561339be31149d0c6836430f528aedf0cf72ba51788658f24832` | `sha256:f2d4c03c66c9ef6cf9339fa983ddb86ec64a2d41f4756e0831a522c604f87845` | `sha256:362e7f05ac8015ea7fdf58c5c5f9709154b331c1d15ca56fff0121058e4d3f59` | `2026.06.19-16.36.22` |
| 5 | `scum.login` | `sha256:5b1630d3747f317fb0d2000f3c7072cd202e358e59ec43f4efff9d192164210c` | `sha256:6aed8ccee83260b16e771ed8a8d49fd26d581a9307b5c01b8294ddcc5906624f` | 5 | `sha256:853ded422a039c697cb88760b3bf5292810dbac887e4464d84959f92afcc3a82` | `sha256:a6a353c4223497d1a43631104b31c20884a4cf0ce8cbb972398e885682c7b538` | `sha256:dd93eb0f7e4455708b2defdab69a39814bfb84efb84c99a17306715f6597258a` | `2026.06.20-06.36.46` |
| 6 | `scum.logout` | `sha256:5b1630d3747f317fb0d2000f3c7072cd202e358e59ec43f4efff9d192164210c` | `sha256:6aed8ccee83260b16e771ed8a8d49fd26d581a9307b5c01b8294ddcc5906624f` | 6 | `sha256:18a014c7e3dccdd1a3b5179fa49bd1fb88d47bab1f1c9ce1ff3114c908999d61` | `sha256:a6a353c4223497d1a43631104b31c20884a4cf0ce8cbb972398e885682c7b538` | `sha256:a1a8a46507b6cabf03a94220ddbe1437c181b7f6ba306117594acf095ba3d7cf` | `2026.06.20-06.44.55` |
| 7 | `scum.login` | `sha256:5b1630d3747f317fb0d2000f3c7072cd202e358e59ec43f4efff9d192164210c` | `sha256:6aed8ccee83260b16e771ed8a8d49fd26d581a9307b5c01b8294ddcc5906624f` | 7 | `sha256:1d03f4ea4ef8acbb3aeab390215e15be03fb7c4563956827ab933dbf4ba66139` | `sha256:2f260f8e697d93c26fda3ec9858c8b9e03a7a95f36378c58d579030f9c2914df` | `sha256:6cd52f703336f4ba63011a1711e6fcd0cd5839a577f178337f9170475bf25219` | `2026.06.20-12.30.26` |
| 8 | `scum.logout` | `sha256:5b1630d3747f317fb0d2000f3c7072cd202e358e59ec43f4efff9d192164210c` | `sha256:6aed8ccee83260b16e771ed8a8d49fd26d581a9307b5c01b8294ddcc5906624f` | 8 | `sha256:9ba905e6a1b352aa8489ee3be2476e525f3888fbad05240e772d163bb22a517a` | `sha256:2f260f8e697d93c26fda3ec9858c8b9e03a7a95f36378c58d579030f9c2914df` | `sha256:943962513b85365cd5cd276e70b01c6882f203037e3a3eb6195d56cfbb0a936d` | `2026.06.20-12.32.40` |
## Fixture Conclusions
- Authentic login files are UTF-16LE and use the `logged in/out at` template shown above.
- A single fixture row contains raw network material, external player ID, display name, local profile ID, and coordinates; fixture evidence stores only hashes/placeholders for those values.
- Transport cursor identity is `(sourceIdentity, streamGeneration, sequence)`.
- Logical event identity is separate and stable across rotation overlap because it excludes source identity, stream generation, sequence, and network material.
- The newest active login file is empty; Run tailing must begin from a complete-line boundary and handle later appends without creating events from the header-only or zero-byte files.
- Existing `companion/events.go` still parses only the invented stdout/stderr `SCUM LOGIN/LOGOUT` format; task 3.4 must replace/add a versioned parser for these authentic UTF-16LE file-tail fixtures before enabling login-driven player creation.
@@ -1,45 +0,0 @@
## Why
The current SCUM plugin presents projection and Workflow concepts as if they were real operations, but its declared SCUM.db queries contain no SQL, its read workflows do not dispatch Run jobs, its login parser does not understand the real SCUM login-log format, and several player, map, gift, and `855` controls fabricate data or evidence. The product needs a smaller SCUM management surface backed only by current-server login logs, verified SCUM.db facts, durable local records, and permission-checked writes.
## What Changes
- **BREAKING**: Supersede the projection/observation/Workflow architecture introduced by `integrate-real-scum-ops-workflows`; remove SCUM Workflow/status product APIs, repositories, services, page actions, refresh/audit controls, freshness terminology, and the `Workflow 状态` page.
- **BREAKING**: Remove the built-in `管理` tab from the SCUM server detail navigation, make the first SCUM plugin page the default, and relocate necessary deployment, metadata, and administrator controls to existing server-list actions and a server-settings drawer.
- Discover the schema of the current bound service through a read-only Run probe before defining production queries; do not treat an unbound copied/reference `SCUM.db`, `scum_robot/model/scum_server.go`, historical cache, or guessed joins/enums as authoritative. A Run-created execution snapshot is acceptable only when it is fenced to the active binding/database identity, timestamped, checksummed, and invalidated on rebinding or schema change.
- Make the SCUM plugin own versioned login-log parsers, SQLite query assets, result schemas, coordinate metadata, RCON command templates, and controlled mutation declarations. Run remains a generic bounded executor and never hardcodes SCUM keys, tables, commands, or paths.
- Store players, sessions, squads, squad members, vehicles, flags, current positions, gifts, deliveries, and sync cursors in dedicated platform-owned local records rather than a monolithic metadata snapshot or fabricated product projection.
- Automatically create/update players and login sessions from authentic login/logout log events, and automatically synchronize verified SCUM.db facts in the background without user-facing refresh, projection, or audit buttons.
- Rebuild user management as a searchable, filterable, paginated player roster with detail and explicit edits; remove player-intelligence, shared-IP, automatic-risk, alias-history, fake values, and hard-coded increment actions from the SCUM product flow.
- Rebuild squad management and the realtime map from verified squad/member/vehicle/flag/coordinate data, a declared SCUM map asset, and a tested coordinate transform; never infer ownership or coordinates that the source cannot prove.
- Rebuild gift management as server-scoped local CRUD plus bounded, idempotent delivery records whose success is recorded only after a conclusive Run result.
- Preserve the AI assistant for plugin configuration and player-operation drafts. Manual and AI-originated writes use the same effective-user permissions, reviewable before/after diff, allowlisted plugin action, Run execution path, and read-after-write confirmation.
- Replace the fake `player.attribute.855.set` integer column with named, version-scoped character attributes backed only by a targeted patch of the profile XML source confirmed by the current-service adapter; the patch preserves unknown XML content, and `855` may remain only as a user-confirmed preset label.
- Remove all product copy and controls for projection, observation, stale projection, refresh real data, refresh projection, initiate audit, pending-review counters, and Workflow status while retaining non-product authorization, idempotency, safety, and internal audit evidence for writes.
## Capabilities
### New Capabilities
- `scum-live-data-sync`: Authentic login-log ingestion, current-service schema discovery, plugin-owned SQL assets, generic Run execution, automatic synchronization, and dedicated local SCUM records.
- `scum-player-management`: Lean player roster/session management, search/filter/pagination/detail contracts, null-for-unknown semantics, and explicit player editing surfaces.
- `scum-squad-management`: Verified squad, member, leader/rank, flag, territory, search, pagination, and detail behavior without inferred relationships.
- `scum-realtime-map`: Verified player, vehicle, flag/territory coordinates, a distributable map asset, tested transforms, and automatically updated layers without fabricated positions.
- `scum-gift-management`: Server-scoped gift package CRUD, eligibility, bounded delivery, idempotency, result handling, and delivery history.
- `scum-controlled-writes`: Plugin-owned RCON and database/XML mutation declarations, effective-user permissions, manual/AI parity, safety guards, and confirmation requirements.
- `scum-real-data-management-surface`: The exact SCUM navigation, AI-assistant preservation, server-settings relocation, and removal of projection/Workflow/audit-refresh product concepts.
### Modified Capabilities
- None. The main baseline contains no SCUM capability that can validly receive a `MODIFIED` or `REMOVED` delta. The completed-but-unarchived SCUM change artifacts remain historical implementation records: this change uses unique `ADDED` capability names and explicitly supersedes those old projection/Workflow/product requirements. They must not later be synchronized into the main baseline as current requirements; any history consolidation is a separate reviewed archival task using skip-specs or an equivalent non-resurrection path.
Supersession mapping: `scum-real-data-projections` is replaced by live sync plus the player/squad/map stores; `scum-workflow-automation` is retired; `scum-controlled-operations` and `scum-player-state-patch` are replaced by `scum-controlled-writes`; the old `scum-product-surface` is replaced by `scum-real-data-management-surface`; `scum-game-player-intelligence` is reduced to the lean player capability; `scum-map-trajectories` is replaced by current-position map behavior with trajectories removed; and `scum-versioned-gift-catalog` is replaced by server-local gift management and conclusive delivery receipts.
## Impact
- `platform/`: new SCUM data models and normalized repositories/migrations, automatic sync services, Run job completion handling, typed resource and mutation APIs, authorization checks, removal of projection/Workflow domains and endpoints, and migration away from SCUM snapshot fields.
- `platform_web/`: SCUM navigation/default section, server-settings relocation, plugin host contracts, API types/clients, player/squad/map/gift pages, permission-aware edit flows, AI drafts, and removal of banned copy/actions.
- `plugins/examples/scum-server-plugin/` and plugin SDK/schema validation: versioned log parser/query/mutation/command assets, result schemas, permissions, map metadata, page bundles, and removal of Workflow declarations.
- External `git@git.npc0.com:admin343/run.git`: generic read-only SQLite template execution, safe result envelopes, plugin-owned mutation execution, and current-service schema-probe support. No `run/` source tree is added to this repository.
- Persistence and deployment: dedicated local tables require explicit migration/rollback handling; old SCUM projection/Workflow snapshot data is not authoritative and is not migrated as real game facts.
- Security: browser APIs continue to exclude SQL, raw XML, database paths, credentials, sockets, raw RCON, and host paths; AI gains no independent execution authority.
@@ -1,117 +0,0 @@
## ADDED Requirements
### Requirement: Effective-user permission enforcement
Every SCUM state-changing request SHALL be authorized against the current user's effective target-server permission at UI presentation, request creation, review/confirmation, and dispatch, with the backend as the authoritative enforcement point.
#### Scenario: Read-only operator opens a writable surface
- **WHEN** a user has `server.game-client.read` but lacks the required write permission
- **THEN** data remains readable, write controls are hidden or disabled with a textual reason, and a direct API attempt is forbidden
#### Scenario: Economy command is requested
- **WHEN** a user edits Fame, cash, or gold
- **THEN** Platform requires `server.game-client.command` and target-server access before accepting the named-field request
#### Scenario: Gift delivery is requested
- **WHEN** a user sends a declared gift package to a server-local player
- **THEN** Platform requires `server.game-client.command`, target-server access, and the gift capability's eligibility/idempotency checks before dispatch
#### Scenario: Database/XML attribute edit is requested
- **WHEN** a user edits a maintenance-level character attribute or preset
- **THEN** Platform requires `server.game-client.maintenance`, target-server access, a synchronous explicit danger confirmation, and the declared safety gates before dispatch; it SHALL NOT create a separate platform-admin approval domain or approval queue
#### Scenario: Plugin page receives permissions
- **WHEN** Platform Web constructs the plugin page host context
- **THEN** it supplies the current session's effective permissions rather than treating manifest-declared permissions or callback presence as proof of authority
### Requirement: Manual and AI write-path parity
Manual forms and AI/Agent-originated SCUM changes SHALL create the same named-field draft and SHALL use the same allowlist, validation, effective-user authorization, review, dispatch, and confirmation service.
#### Scenario: AI suggests an allowed player change
- **WHEN** a user with the required write permission asks AI to change a declared player field
- **THEN** AI produces a reviewable target/player/field/current/proposed diff and no execution occurs until the user explicitly confirms it
#### Scenario: AI requester lacks write permission
- **WHEN** AI can generate or display a suggestion for a user who lacks the field's write permission
- **THEN** the apply action remains unavailable and an API attempt is forbidden; AI receives no component-principal bypass
#### Scenario: AI invents a field or protected payload
- **WHEN** an AI response contains an undeclared field, raw SQL, raw XML, raw RCON, path, credential, or arbitrary command
- **THEN** Platform rejects the draft and stores no executable protected payload from it
### Requirement: Plugin-owned immutable write assets
The SCUM plugin SHALL own versioned typed command templates and guarded mutation declarations, and every executable write asset SHALL be digest-referenced by the plugin manifest and generated Run package.
#### Scenario: Declared write is dispatched
- **WHEN** Platform dispatches a confirmed named-field command or mutation draft
- **THEN** Run executes only the packaged asset whose plugin ID/version, adapter/schema version, action key, server binding, and digest all match the reviewed draft
#### Scenario: Write asset identity changed
- **WHEN** an action key, adapter version, packaged asset, or digest no longer matches the reviewed draft
- **THEN** Platform or Run rejects the write before any game command or database mutation executes
### Requirement: Plugin-owned command execution
SCUM writes with a verified game command SHALL use plugin-owned typed command templates, and Platform and Run SHALL NOT hardcode SCUM command strings.
#### Scenario: Fame or currency is changed
- **WHEN** the compatible plugin adapter declares a supported Fame, normal-currency, or gold command
- **THEN** Platform dispatches its template key and validated parameters through the generic Run/RCON transport and performs the declared confirmation read
#### Scenario: Command template is not compatible
- **WHEN** the current plugin/game adapter cannot verify the command and confirmation contract
- **THEN** the write capability is disabled and SHALL NOT fall back to direct SQLite mutation or Platform-built command text
### Requirement: Named and preserving XML attribute mutation
Character attribute writes SHALL target version-scoped named attributes or existing skill nodes in the profile XML source verified by the active current-service adapter and SHALL preserve all untargeted XML content.
#### Scenario: One allowed attribute changes
- **WHEN** Run reads a valid current XML document and applies an authorized and explicitly confirmed named-field change
- **THEN** only the targeted allowlisted attribute/node changes and unknown attributes, nodes, ordering-sensitive extensions, and all other values remain semantically intact
#### Scenario: Unknown field or missing skill is requested
- **WHEN** a requested attribute/skill is absent from the version adapter or the XML lacks the targeted existing skill node
- **THEN** Run rejects the mutation and SHALL NOT invent a node, default an `Attribute` value, or rewrite the document from an incomplete struct
#### Scenario: XML is malformed
- **WHEN** the current adapter-confirmed profile XML payload cannot be parsed by the preserving patcher
- **THEN** no database write occurs and Platform receives a bounded safe failure
### Requirement: `855` is an explicit preset, not a database field
The system SHALL NOT declare or execute `855` as a table column or generic integer field; it MAY expose `855` only after an operator-confirmed preset maps it to explicit version-scoped named character attributes and values.
#### Scenario: Preset meaning is not confirmed
- **WHEN** the plugin adapter has no reviewed mapping for the `855` label
- **THEN** the preset is absent/disabled and no `fieldKey=855`, `prisoner.value`, or `0..100000` mutation can be created
#### Scenario: Confirmed preset is reviewed
- **WHEN** a compatible adapter declares the preset and an authorized user selects it
- **THEN** the review shows every named attribute's current and proposed value rather than a single opaque `855` value
### Requirement: Guarded single-row database mutation
Every database/XML mutation SHALL require a current compatible probe, target identity, expected before values/checksum, reason, idempotency key, genuine same-server backup evidence, required offline/maintenance evidence, a single-row bound, and read-after-write confirmation.
#### Scenario: Safety evidence is missing or fabricated
- **WHEN** the player's online state is unknown/unsafe, maintenance is unverified, the backup reference is absent/not restorable/not for the same database instance, or a timestamp-shaped placeholder is supplied
- **THEN** Platform rejects dispatch and no mutation job is created
#### Scenario: Current value changed
- **WHEN** the row identity, current value, XML digest, or schema fingerprint no longer matches the reviewed before state
- **THEN** Run aborts the transaction as a conflict without applying the requested value
#### Scenario: Affected row count is not one
- **WHEN** a mutation would affect zero or more than one row
- **THEN** Run rolls back and reports failure
#### Scenario: Readback does not confirm the target values
- **WHEN** execution may have occurred but the confirmation read is missing or mismatched
- **THEN** Platform SHALL NOT report success and SHALL require confirmation before any explicit retry
#### Scenario: Attribute save completes
- **WHEN** the single-row mutation and readback confirm every named target value and new digest
- **THEN** Platform records the safe result and updates local verified details without exposing the raw XML
### Requirement: No implicit destructive activation
Saving character attributes SHALL NOT implicitly kill, respawn, kick, or otherwise disrupt the player.
#### Scenario: Game requires respawn for new values
- **WHEN** current-service verification shows a respawn/death action is necessary for activation
- **THEN** that action is a separate explicitly named destructive command with its own permission and fresh user confirmation and is not automatically chained to attribute save
@@ -1,95 +0,0 @@
## ADDED Requirements
### Requirement: Server-scoped gift package CRUD
The system SHALL provide effective-user-authorized create, read, update, enable/disable, and delete operations for gift packages and typed items scoped to one server instance and compatible plugin/game version.
#### Scenario: User has gift read access only
- **WHEN** the current session has `server.game-client.read` but lacks `server.game-client.maintenance`
- **THEN** package data and delivery history remain readable while create/edit/enable/delete controls are unavailable and direct mutation requests are forbidden
#### Scenario: Operator creates a valid package
- **WHEN** an operator with effective `server.game-client.maintenance` submits a name, classification, eligibility/limit rules, and bounded quantities of plugin-catalogued item keys
- **THEN** Platform stores the package and items for the target server without storing raw RCON, shell, SQL, or arbitrary command strings
#### Scenario: Package item is invalid
- **WHEN** a package contains an unknown or incompatible item key, duplicate item, out-of-range quantity, or game-version mismatch
- **THEN** Platform rejects the change and preserves the previous package
#### Scenario: Package is deleted
- **WHEN** an authorized operator confirms deletion of a package not protected by an active delivery
- **THEN** Platform removes or retires the package without deleting immutable completed delivery facts
### Requirement: Plugin-owned immutable gift catalog and transport
Gift item aliases, compatibility rules, quantities, and delivery transport declarations SHALL come only from versioned digest-referenced assets in the plugin package and, where executable, the generated Run package.
#### Scenario: Catalog or transport digest changed
- **WHEN** a package or frozen delivery references a catalog/transport version or digest that no longer matches the active compatible plugin package
- **THEN** Platform rejects creation or dispatch and SHALL NOT translate the item into an arbitrary command or newer unreviewed alias
### Requirement: Validated gift eligibility and limits
The system SHALL evaluate package eligibility and atomically reserve database-backed per-player, per-server, and configured period limits in the server's declared timezone before a delivery can dispatch.
#### Scenario: Player belongs to another server
- **WHEN** a caller attempts to deliver a package to a player record outside the package's server instance
- **THEN** Platform rejects the request before creating a delivery or Run job
#### Scenario: Period limit is reached
- **WHEN** a player already has the allowed number of reserved, in-progress, partial, unknown, or delivered grants in the active daily/weekly or declared period boundary
- **THEN** Platform rejects another delivery without relying on an in-memory count
#### Scenario: Concurrent eligibility requests occur
- **WHEN** two workers request the same limited package for the same player and period concurrently
- **THEN** a server-scoped uniqueness/idempotency constraint allows at most one request to reserve the remaining entitlement
#### Scenario: Delivery conclusively did not execute
- **WHEN** Run returns a conclusive failure proving that no gift effect occurred
- **THEN** Platform may release the reserved period entitlement transactionally; partial or unknown outcomes SHALL continue to hold it until reconciled
### Requirement: Frozen and idempotent gift delivery
The system SHALL freeze the target player, package/item definitions, plugin/game version, and delivery parameters before dispatch and SHALL use a stable server-scoped delivery ID and idempotency key.
#### Scenario: Package changes after delivery request
- **WHEN** an operator edits or disables a package after a delivery has been created
- **THEN** the existing delivery retains its frozen target/items/version and the edit does not mutate an in-flight or completed delivery
#### Scenario: Same idempotency key is submitted again
- **WHEN** the same scoped delivery request is repeated or submitted concurrently
- **THEN** Platform returns the original delivery and queues no duplicate effect
#### Scenario: Run receives a delivery
- **WHEN** a user with current effective `server.game-client.command` confirms an eligible frozen delivery
- **THEN** Run receives only the plugin-declared typed item aliases/quantities and stable delivery identity, not arbitrary browser commands
### Requirement: Conclusive delivery outcomes
The system SHALL record a gift as delivered only after conclusive Run execution evidence, and ambiguous or partial outcomes SHALL not trigger automatic whole-package redelivery.
#### Scenario: Job is queued or accepted
- **WHEN** Run has only claimed, acknowledged, or begun the delivery job
- **THEN** Platform records the delivery as in progress and SHALL NOT create a successful claim/receipt
#### Scenario: Delivery succeeds conclusively
- **WHEN** Run returns a schema-valid success receipt for every required item under the delivery idempotency key
- **THEN** Platform records the delivery as delivered exactly once
#### Scenario: Connection is lost after possible execution
- **WHEN** delivery may have executed but the result is missing, timed out, cancelled, or cannot be confirmed
- **THEN** Platform records an unknown outcome, performs confirmation before any explicit retry, and never automatically queues the entire delivery again
#### Scenario: Multi-item delivery is partial
- **WHEN** the transport cannot guarantee atomic delivery and only some item receipts are conclusive
- **THEN** Platform records per-item receipts and a partial/unknown package outcome and SHALL NOT label the whole package delivered or blindly redeliver confirmed items
#### Scenario: Notification fails after delivery
- **WHEN** all items are confirmed delivered but a post-delivery notification fails
- **THEN** Platform preserves the delivered fact, records the notification failure separately, and SHALL NOT redeliver the package
### Requirement: Gift management surface and history
The gift page SHALL provide statistics, a searchable/filterable paginated package table, package create/edit/detail/delete controls, a real player selector, a reviewed send dialog, and server-scoped delivery history without Workflow terminology.
#### Scenario: Operator opens gift management
- **WHEN** local gift data is available
- **THEN** the page shows package totals/enabled counts/delivery statistics, package contents and limits, and compact row actions without a hard-coded `starter-pack`, fixed player cards, or fixed notification text
#### Scenario: Operator reviews delivery result
- **WHEN** a delivery is in progress, delivered, failed, unknown, partial, or has a notification failure
- **THEN** the page shows the ordinary gift-delivery result and safe reason without exposing a Workflow instance, Workflow step, raw command, or audit-initiation action
@@ -1,174 +0,0 @@
## ADDED Requirements
### Requirement: Current-service schema compatibility gate
The system SHALL enable each SCUM database-backed capability only after the bound Run has performed a read-only probe against the current server database and the result matches a versioned plugin schema adapter for that capability.
#### Scenario: Supported current schema is detected
- **WHEN** the bound Run reports a schema fingerprint whose required tables, columns, types, joins, and cardinality match the plugin adapter for player reads
- **THEN** Platform enables the player-read capability for that server and records the adapter version, fingerprint, probe time, and safe capability result
#### Scenario: A current binding has no valid probe evidence
- **WHEN** a compatible Run binding becomes ready, reconnects, or reports a changed database/plugin identity without current probe evidence
- **THEN** Platform automatically schedules the bounded read-only probe before any affected query or write and exposes no browser action for starting it
#### Scenario: Generic probe execution is unavailable
- **WHEN** the bound Run lacks the required generic diagnostic-probe contract
- **THEN** database-backed SCUM capabilities remain disabled with a safe connection/capability reason and SHALL NOT fall back to a copied database, cached schema, reference model, or guessed query
#### Scenario: One world-data requirement is incompatible
- **WHEN** a required vehicle column is missing, has an incompatible type, or the declared join is not unique while player and squad requirements still match
- **THEN** Platform disables only the affected vehicle capability and SHALL NOT treat an empty vehicle list as a successful current-server result
#### Scenario: Compatibility evidence becomes invalid
- **WHEN** the game version, database instance identity, Run binding, plugin adapter version, or schema fingerprint changes
- **THEN** Platform invalidates the affected capability evidence and requires a new successful probe before another query or write uses that evidence
#### Scenario: Probe result is exposed safely
- **WHEN** Platform stores or returns schema compatibility status
- **THEN** the result excludes the database path, DSN, socket, credentials, raw SQL, raw row content, and host identity
#### Scenario: Run snapshots the active database for a safe read
- **WHEN** Run must use an execution-time read-only snapshot to avoid locking the active SQLite database
- **THEN** the snapshot is bound to the current server/Run/database identity, timestamped, checksummed, short-lived, and rejected after rebinding or source-identity change
### Requirement: Plugin-owned immutable parser and query assets
The SCUM plugin SHALL own versioned login parsers, SQLite query assets, and parameter/result schemas, and each executable data asset SHALL be referenced by an integrity digest in the plugin manifest and generated Run package.
#### Scenario: Declared query is dispatched
- **WHEN** Platform schedules the declared player query with schema-valid bounded parameters
- **THEN** Run executes the matching packaged asset only after the plugin ID, version, template key, server binding, and asset digest all match
#### Scenario: Caller supplies arbitrary query material
- **WHEN** a browser, AI request, Platform API caller, or job payload supplies raw SQL, an unknown template key, extra parameters, or a different asset digest
- **THEN** the request is rejected before SQLite execution and no protected query content is stored in a browser-visible response
#### Scenario: SCUM behavior is absent from Run
- **WHEN** Run selects an executor for a SCUM plugin query
- **THEN** it uses generic SQLite and packaged-asset contracts and contains no branch keyed by SCUM, a `scum.*` template name, a SCUM table, or a SCUM command
### Requirement: Bounded and correlated SQLite reads
Run SHALL execute plugin query assets with bound parameters and query-only restrictions, and Platform SHALL correlate every result to its original durable job before validating and storing it.
#### Scenario: Query violates the read boundary
- **WHEN** an asset or parameter expansion attempts multiple statements, DDL, mutation, `ATTACH`, extension loading, a write PRAGMA, or string-concatenated parameter injection
- **THEN** Run rejects execution with a stable safe error and returns no rows
#### Scenario: Query exceeds a declared bound
- **WHEN** execution times out, the database remains locked, or rows/result bytes exceed the template limits
- **THEN** Run stops the read and returns a bounded safe error without converting the failure into an empty successful result
#### Scenario: Fast, duplicate, or late result arrives
- **WHEN** a result arrives immediately, is delivered more than once, or arrives after a newer scan
- **THEN** the pre-existing job correlation prevents loss or cross-server association, duplicate delivery is idempotent, and an older result cannot replace a newer completed generation
#### Scenario: Result envelope is malformed
- **WHEN** the server/plugin binding, template key, schema version, asset digest, checksum, observed time, or row schema does not match the queued job
- **THEN** Platform rejects the result before any local SCUM record changes
### Requirement: Authentic login-driven player and session records
The system SHALL parse the plugin-declared current SCUM login/logout format and atomically maintain a player and session uniquely scoped by server instance and external player identifier.
#### Scenario: Parser version is enabled
- **WHEN** a plugin login parser is registered for a SCUM/game version
- **THEN** sanitized fixtures captured from the active service prove its successful login/logout mapping and parser digest before it can create durable players
#### Scenario: Unknown player logs in successfully
- **WHEN** an authentic successful login event contains a valid external player ID, display name, event identity, and occurrence time
- **THEN** Platform atomically creates or updates exactly one `(server_instance_id, external_player_id)` player and opens one matching local session
#### Scenario: Concurrent first-login delivery occurs
- **WHEN** two workers process the same new player's first successful login concurrently
- **THEN** a database unique constraint and idempotent event identity produce one player and one session without a duplicate-key user-visible failure
#### Scenario: Duplicate or older event arrives
- **WHEN** an acknowledged login/logout event is replayed or an older logout arrives after a later login
- **THEN** Platform creates no duplicate session and does not regress the player's current display name, last-seen time, or newer online session
#### Scenario: Source format has no native session identifier
- **WHEN** a valid login line has a transport cursor and player identity but no game-provided event/session ID
- **THEN** Platform derives a privacy-safe logical event fingerprint and deterministic server-scoped session identity from normalized non-network event fields, independent of stream generation, so replaying that logical line cannot create a second session
#### Scenario: Line is malformed or login did not succeed
- **WHEN** a partial, malformed, undecodable, or oversized line, failed authentication attempt, disconnect without a matching identity, or unrelated log message is received
- **THEN** the parser emits no successful-login event and Platform creates no player or fabricated session
#### Scenario: Logout has no matching session
- **WHEN** a valid logout event has no matching open session under the same server/player/source epoch
- **THEN** Platform records no fabricated login session and does not close a different or newer session
#### Scenario: Network material is present
- **WHEN** the source login line includes an IP address or another network identifier
- **THEN** raw network material is discarded before durable player/session storage and is absent from SCUM APIs
#### Scenario: Database save time changes
- **WHEN** a SCUM.db row reports `last_login_time`, `last_save_time`, or another persistence timestamp without a corresponding current login session event
- **THEN** Platform SHALL NOT mark the player online from that database timestamp alone
### Requirement: Login stream continuity and binding fences
The login source SHALL keep transport cursor identity separate from stable logical event identity and preserve current-binding isolation across batch replay, file rotation/truncation, Run restart, reconnect, and partial-line boundaries.
#### Scenario: Log file rotates or truncates
- **WHEN** the declared login file is replaced, rotated, or truncated
- **THEN** Run starts a new durable transport generation and resumes only at a complete-line boundary while any overlapped logical event retains the same privacy-safe fingerprint
#### Scenario: Rotation overlap replays an acknowledged login
- **WHEN** a previously acknowledged logical login line is observed again under a new stream generation during copy-truncate or rotation overlap
- **THEN** the new transport event is acknowledged idempotently and Platform creates no second player or session
#### Scenario: Run restarts with an acknowledged cursor
- **WHEN** Run restarts or reconnects after Platform acknowledged a source sequence
- **THEN** replay begins from a safe acknowledged boundary and duplicate batches remain idempotent
#### Scenario: Event belongs to an obsolete binding
- **WHEN** a typed login/logout event carries a Run binding, server instance, plugin version, stream generation, or source identity that no longer matches the active binding
- **THEN** Platform rejects it before changing a player or session
#### Scenario: Online session loses authoritative log continuity
- **WHEN** the binding is replaced, the server stops, or log continuity is lost without a matching logout event
- **THEN** Platform closes or marks the affected session unknown with a bounded terminal reason and SHALL NOT continue presenting it as a confirmed current login
### Requirement: Automatic server-bound synchronization
The system SHALL synchronize verified SCUM.db resources automatically when a compatible Run binding becomes ready and at plugin-declared bounded cadences, without a user-facing manual data-refresh operation.
#### Scenario: Compatible Run becomes ready
- **WHEN** a server obtains a current Run binding and successful capability probe
- **THEN** Platform schedules an initial bounded scan and later jittered resource scans within per-server concurrency limits
#### Scenario: New login needs enrichment
- **WHEN** login ingestion creates a player whose database details are not yet known
- **THEN** Platform may schedule a bounded player-detail lookup without delaying player creation or filling unknown values with defaults
#### Scenario: Page is opened
- **WHEN** an operator opens users, squads, map, or gifts
- **THEN** the page reads the platform-local data API and SHALL NOT dispatch a Run query, schema probe, projection refresh, audit, or synchronization command
#### Scenario: A later scan fails
- **WHEN** a resource previously synchronized successfully and a later scan fails or is partial
- **THEN** Platform retains the last completed local generation, records the safe connection/sync failure internally, and does not delete rows or present generated replacements
#### Scenario: Resource synchronization status is requested
- **WHEN** a local resource API reports its availability
- **THEN** it distinguishes not-yet-synchronized, successfully-synchronized-empty, schema-incompatible, current/last-complete data, and connection/read failure with concrete collection time and a safe reason
#### Scenario: No completed local generation exists
- **WHEN** a current scan has not completed successfully
- **THEN** Platform returns the appropriate unavailable/not-yet-synchronized state and SHALL NOT fall back to a legacy projection, sample record, reference database, cached unbound row, or fabricated empty success
### Requirement: Dedicated local SCUM database records
The system SHALL persist SCUM identities, sessions, details, squads, squad members, vehicles, flags, positions, gifts, deliveries, and sync cursors in dedicated queryable local stores rather than in SCUM projection/Workflow snapshot fields.
#### Scenario: File storage backend is active
- **WHEN** Platform runs with the default file metadata backend
- **THEN** SCUM records use a platform-owned local database under the configured data directory and a position update does not rewrite the global metadata snapshot
#### Scenario: MySQL storage backend is active
- **WHEN** Platform runs with the MySQL backend
- **THEN** explicit migrations create normalized SCUM tables with server-scoped indexes and uniqueness constraints instead of storing SCUM collections only inside `platform_metadata_snapshots.snapshot_json`
#### Scenario: Source omits a numeric fact
- **WHEN** a verified row omits fame, currency, a coordinate, an owner, or another fact
- **THEN** the corresponding local field remains null/absent and SHALL NOT be set to zero, an inferred owner, a generated coordinate, or an unrelated identifier
#### Scenario: Full scan completes
- **WHEN** every page of a bounded full resource scan passes schema and checksum validation
- **THEN** Platform transactionally commits that generation and may mark records absent only from that completed generation
@@ -1,68 +0,0 @@
## ADDED Requirements
### Requirement: Lean SCUM player record
The SCUM product SHALL maintain only server-scoped player identity, current display name, first/last seen times, online session/login history, and verified current-server player details required for management.
#### Scenario: Player changes display name
- **WHEN** a newer authentic login event reports a different display name for an existing server-scoped player
- **THEN** Platform updates the current display name and SHALL NOT create alias-intelligence, shared-IP, access-risk, or automatic-enforcement records
#### Scenario: SCUM player model is migrated
- **WHEN** the new player store becomes authoritative
- **THEN** SCUM page/API/manifest/log-ingestion flows no longer create, update, read, or expose player-intelligence, access-attempt, shared-fingerprint, security-signal, alias-history, projection, observation, or Workflow records; a shared non-SCUM domain may remain only for a proven non-SCUM consumer
### Requirement: Searchable and paginated player roster
The system SHALL provide a server-authorized local player-list API and full-width table with server-side pagination, bounded search, online-state and squad filters, and allowlisted sorting.
#### Scenario: Operator searches the roster
- **WHEN** an authorized operator searches by display name or external player ID and selects online or squad filters
- **THEN** Platform returns only matching players from the target server with total/page information and deterministic ordering
#### Scenario: Cross-server player identifier is supplied
- **WHEN** the same external player ID exists on another server or a filter references another server's squad
- **THEN** the response includes no cross-server row and reveals no other server association
#### Scenario: Unauthorized user requests players
- **WHEN** the session lacks effective read access to the target server
- **THEN** Platform denies the request without revealing whether any player exists
### Requirement: Trustworthy roster values
The player roster SHALL display current stored business fields without fabricating defaults and SHALL distinguish online-session evidence from database details.
#### Scenario: Verified player details exist
- **WHEN** local records contain verified fame, cash, gold, squad, and last activity facts
- **THEN** the roster shows player name, unique identifier, online state, those verified facts, and their last synchronized time
#### Scenario: Database details are not yet known
- **WHEN** a login-created player has no successful detail row yet
- **THEN** the roster shows the player identity/session with unknown detail fields and SHALL NOT substitute zero, `1`, sample data, or a guessed profile identifier
#### Scenario: No players have been recorded
- **WHEN** the local player table is confirmed empty
- **THEN** the page shows a normal player-data empty state without projection/Workflow terminology, sample players, or an action that starts data collection
### Requirement: Player detail and login history
The system SHALL provide a player detail surface containing server-scoped identity, current verified facts, current known coordinate, login history, and last synchronized/collected times.
#### Scenario: Operator opens player detail
- **WHEN** an authorized operator selects a roster row
- **THEN** a drawer, dialog, or detail route shows the player's known fields and bounded login history without exposing raw logs, IP addresses, database rows, SQL, XML, paths, or credentials
#### Scenario: Coordinate is unavailable
- **WHEN** no verified current coordinate exists for the player
- **THEN** the detail surface states that the coordinate is unavailable and SHALL NOT calculate or render a default map point
### Requirement: Explicit player edit form
The user-management surface SHALL edit player values through a named-field form that shows current and proposed values and delegates execution to the controlled-write capability.
#### Scenario: Operator edits an economy field
- **WHEN** an operator opens the Fame, cash, or gold edit control
- **THEN** the form requires an explicit target value and reason and SHALL NOT use hard-coded `+100`, `+1000`, or other fixed increment behavior
#### Scenario: Attribute current value is unknown
- **WHEN** an operator opens an attribute or `855` preset edit without verified current named values
- **THEN** the UI prevents submission and explains that current values must be known; it SHALL NOT default the before or after value to `0` or `1`
#### Scenario: User has read but not write access
- **WHEN** the current session may read players but lacks the effective permission for the selected field
- **THEN** the roster and detail remain available while the edit action is hidden or disabled with a readable permission explanation
@@ -1,95 +0,0 @@
## ADDED Requirements
### Requirement: Exact SCUM detail navigation
The SCUM server detail view SHALL contain exactly five tabs in this order: `用户管理`, `队伍管理`, `实时地图`, `礼包管理`, `AI 助手`.
#### Scenario: SCUM detail opens normally
- **WHEN** an operator opens a SCUM server detail without a valid section selector
- **THEN** the page selects `用户管理` as the default and renders no standalone `管理` or `Workflow 状态` tab
#### Scenario: Legacy section is requested
- **WHEN** a legacy `manage`, `workflows`, or otherwise invalid SCUM section is requested
- **THEN** the page replaces/falls back to `用户管理` without an empty screen or a Workflow/management placeholder
#### Scenario: Non-SCUM server detail is rendered
- **WHEN** another plugin/server type legitimately declares different navigation
- **THEN** the SCUM-only five-tab restriction does not silently remove that plugin's declared pages
### Requirement: Required management controls are relocated
Removing the SCUM `管理` tab SHALL NOT remove server deployment, metadata, or administrator-membership capabilities.
#### Scenario: Operator edits deployment
- **WHEN** an authorized operator needs to change the SCUM deployment definition
- **THEN** the existing server-list deployment action remains available and no replacement permanent detail tab is introduced
#### Scenario: Server owner opens settings
- **WHEN** the server owner selects the compact settings action in the detail header
- **THEN** a drawer or dialog permits display-name and administrator membership changes with the existing ownership authorization
#### Scenario: Non-owner opens server settings
- **WHEN** a server member who is not the owner views the settings surface
- **THEN** owner-only membership mutations are unavailable and a direct API attempt remains forbidden
### Requirement: Projection and Workflow concepts are removed from the product
SCUM pages and browser contracts SHALL NOT render or offer projection, observation, manual synchronization, audit-initiation, pending-review counter, or Workflow product concepts.
#### Scenario: Any retained SCUM page renders
- **WHEN** users, squads, map, gifts, or AI content is displayed
- **THEN** it contains none of `Workflow 状态`, `投影`, `真实投影`, `玩家投影`, `刷新投影`, `刷新世界投影`, `刷新真实数据`, `发起审计`, `创建发放 workflow`, `typed workflow`, `typed observation`, `typed operation`, `待审操作`, `审批/确认队列`, `清理旧入口`, `目前暂无真实投影数据`, `暂无真实投影数据`, `暂无玩家投影`, or `Companion 可用`
#### Scenario: Plugin page loads data
- **WHEN** any of the four SCUM management pages initializes or retries a failed local read
- **THEN** it calls only its local resource API and does not list/create Workflow instances/steps or start a query, projection refresh, real-data refresh, or audit
#### Scenario: Removed endpoint is requested
- **WHEN** a browser requests the removed SCUM Workflow, Workflow-step, observation, operation-list/approve, projection/real-data refresh, or audit-initiation endpoint
- **THEN** Platform returns not found or a stable removal response without dispatching a job or exposing a replacement raw execution path
#### Scenario: Legacy operation approval route is requested
- **WHEN** a caller invokes a legacy SCUM operation-list, `/scum/operations/{id}/approve`, pending-review, or confirmation-queue route
- **THEN** Platform returns not found or a stable removal response and SHALL NOT create an approval record, dispatch a write, or revive an approval product domain
#### Scenario: Internal write safety is recorded
- **WHEN** Platform records authorization, idempotency, backup, execution, or confirmation evidence for a write
- **THEN** the record remains internal/safe and does not create a user-facing audit-start action or Workflow status page
### Requirement: Trustworthy management page layouts
The user, squad, map, and gift pages SHALL use full-width business data layouts and shared theme-aware table, drawer, dialog, and status patterns without placeholder product data.
#### Scenario: Management page is implemented
- **WHEN** a first-party SCUM page adds or changes styles
- **THEN** it preserves black-mecha and magical-girl theme readability, reuses shared tokens/components, keeps CSS declarations compact, and does not add unrelated opaque SaaS cards or page-local fixed decorative effects
#### Scenario: Data load fails
- **WHEN** a local API request fails
- **THEN** the page shows a readable error and may retry only the local read; it does not generate sample players, squads, vehicles, flags, positions, gifts, maintenance evidence, backups, or operation results
### Requirement: AI assistant is preserved with reviewable effects
The `AI 助手` SHALL remain the final SCUM tab and SHALL support plugin-declared configuration suggestions and controlled player-operation drafts without receiving provider secrets or independent write authority.
#### Scenario: AI suggests plugin configuration
- **WHEN** an authorized operator requests SCUM plugin configuration assistance
- **THEN** AI proposes only plugin-declared fields, Platform validates and displays a reviewable diff, and the authorized review-and-confirm config-write path applies the change only after explicit confirmation
#### Scenario: User can view but cannot apply a suggestion
- **WHEN** the user may invoke/read an AI suggestion but lacks the permission required for the proposed config or player write
- **THEN** the suggestion remains reviewable while the apply action is disabled and backend application is forbidden
#### Scenario: AI provider is invoked
- **WHEN** Platform sends the allowed prompt/context to the configured AI provider
- **THEN** raw AI keys, database credentials, SCUM.db paths, raw XML, and protected Run material never reach the plugin page/browser
### Requirement: Obsolete UI actions and placeholders are removed
The SCUM product SHALL replace hard-coded actions and placeholder map/gift behavior with the declared business flows.
#### Scenario: Player actions render
- **WHEN** a player has writable verified fields
- **THEN** the UI offers explicit named-field editing and contains no `Fame +100`, `现金 +1000`, `855 审批`, fake before value, fake maintenance ID, or fake backup reference
#### Scenario: Map renders
- **WHEN** the map page is available
- **THEN** it uses the verified map capability and contains no gradient-only board or arbitrary percentage-dot transform
#### Scenario: Gift page renders
- **WHEN** gift management is available
- **THEN** it reads local gift packages and contains no hard-coded `starter-pack`, fixed player-card delivery, or fixed notification text
@@ -1,69 +0,0 @@
## ADDED Requirements
### Requirement: Independently verified current map facts
The system SHALL store and present current player, vehicle, flag, and squad-territory coordinates only when each resource's plugin adapter maps a compatible current-service source, identity, coordinate, and observation time.
#### Scenario: One position resource is incompatible
- **WHEN** player and flag positions are compatible but the vehicle query lacks a required column, type, identity, or unique join
- **THEN** Platform keeps the verified player/flag layers available, disables only the vehicle layer, and SHALL NOT return an empty vehicle list as a successful current result
#### Scenario: Vehicle ownership is unverified
- **WHEN** the source proves a vehicle identity/class and coordinate but does not prove a player or squad owner
- **THEN** Platform stores the verified fields and leaves ownership null instead of inferring it from nearby players, movement history, or an expiry heuristic
#### Scenario: Position scan later fails
- **WHEN** verified positions were previously stored and a later current-service scan fails or is partial
- **THEN** the map may retain the last completed rows with their concrete collection time and connection interruption, but SHALL NOT call them current or replace them with empty/generated points
### Requirement: Declared SCUM map asset and coordinate transform
The realtime map SHALL use a plugin-declared distributable map asset/version and integrity digest, verified world bounds, and a tested coordinate transform version/digest compatible with the current SCUM adapter.
#### Scenario: Verified coordinate is rendered
- **WHEN** a player, vehicle, flag, or territory coordinate falls within the declared bounds and transform version
- **THEN** the map places the marker at the tested map position and shows object type, name/ID, source coordinate, and collection time
#### Scenario: Map metadata is incompatible or absent
- **WHEN** the map asset, version, bounds, or transform does not match the current server adapter
- **THEN** the map shows a readable unavailable/error state and SHALL NOT fall back to a gradient board, arbitrary percentage transform, fake points, or sample routes
#### Scenario: Map asset digest does not match
- **WHEN** the packaged/browser-served map asset or transform contract fails its plugin-declared integrity check
- **THEN** the map is unavailable and SHALL NOT render coordinates against an unverified replacement asset
#### Scenario: Coordinate is outside bounds
- **WHEN** a source coordinate is non-finite or outside the declared world bounds
- **THEN** Platform rejects it from the current map dataset and records a bounded validation failure
### Requirement: Automatically updated and distinguishable map layers
The realtime map SHALL consume platform-local data automatically and provide distinguishable player, vehicle, and flag/squad-territory layers with player/squad filtering.
#### Scenario: Operator changes layer visibility
- **WHEN** an operator toggles players, vehicles, or flags/territory or applies a player/squad filter
- **THEN** the map updates the visible verified markers without dispatching a Run query or manual refresh operation
#### Scenario: Platform receives a newer coordinate
- **WHEN** a verified automatic sync or declared companion position event updates a current position
- **THEN** Platform publishes a safe local update and the open map can update through the platform event stream
#### Scenario: Source cadence is insufficient
- **WHEN** measured SCUM.db updates cannot support the declared realtime threshold
- **THEN** the plugin uses a declared verified companion position source or the feature presents the measured cadence honestly; it SHALL NOT increase unsafe polling or fabricate intermediate movement
#### Scenario: Map legend is rendered
- **WHEN** multiple entity types are visible
- **THEN** the UI provides icons or textual legend labels so entity meaning does not rely only on color
#### Scenario: Historical movement was not requested
- **WHEN** only current positions are available under this change
- **THEN** the product SHALL NOT fabricate trajectories, 24-hour trails, ride associations, sampling history, or playback controls to satisfy realtime-map acceptance
### Requirement: Server-isolated realtime-map API
The realtime-map API SHALL authorize the target server and return only bounded local current-position and safe object-summary fields needed by the map.
#### Scenario: Foreign map selector is supplied
- **WHEN** a player, squad, vehicle, flag, or territory selector belongs only to another server
- **THEN** Platform returns no foreign marker and does not reveal its existence or server identity
#### Scenario: Browser requests protected source material
- **WHEN** a browser attempts to request raw database rows, SQL, host paths, database identifiers, map-source credentials, or Run connection details
- **THEN** the API rejects the request and returns only named safe map fields
@@ -1,53 +0,0 @@
## ADDED Requirements
### Requirement: Independently gated squad, member, flag, and territory facts
The system SHALL store and present squads, squad members, leader/rank meaning, flags, territories, and their relationships only from current-service rows validated by the matching per-resource plugin adapter capability.
#### Scenario: Squad and member adapters are compatible
- **WHEN** squad and member queries complete successfully with verified identifiers, ranks, and player/profile relationships
- **THEN** Platform transactionally stores server-scoped squads and members and exposes only the leader/rank meaning declared by that adapter
#### Scenario: One squad resource is incompatible
- **WHEN** squad/member queries are compatible but flag ownership or territory coordinates are not
- **THEN** Platform keeps the verified squad/member capability available, disables only the incompatible resource, and SHALL NOT treat its absence as a verified empty list
#### Scenario: Leader meaning is unverified
- **WHEN** the current schema contains a rank value but the adapter cannot prove which value represents leader
- **THEN** Platform keeps leader unknown and SHALL NOT assume that a reference-project constant such as rank `4` is authoritative
#### Scenario: Flag ownership join is ambiguous
- **WHEN** a flag/base/profile relationship yields multiple possible squad owners or no verified squad link
- **THEN** Platform records no squad owner for that flag and exposes no inferred confidence label as fact
### Requirement: Searchable and paginated squad roster
The system SHALL provide a server-authorized local squad-list API and full-width table with bounded name/identifier search, server-side pagination, allowlisted sorting, and deterministic results.
#### Scenario: Operator searches squads
- **WHEN** an authorized operator searches or pages the target server's squads
- **THEN** Platform returns only matching server-local rows with total/page information, and the table shows squad ID, name, verified leader, member count, flag/territory status, known coordinate, and collection time
#### Scenario: No completed squad generation exists
- **WHEN** squads have not synchronized successfully or the squad adapter is incompatible
- **THEN** the page shows the corresponding not-yet-available/error state and SHALL NOT render reference, sample, projection, or generated squads
### Requirement: Semantic squad detail
The squad surface SHALL provide a drawer, dialog, or detail route that separates leader, members/ranks, flags, and territory instead of merging unrelated rows into one list.
#### Scenario: Operator opens a squad
- **WHEN** a server-authorized operator selects a squad
- **THEN** the detail shows only verified leader/member/rank and flag/territory facts with collection times and nullable unknown fields
#### Scenario: Verified territory coordinate is selected
- **WHEN** a squad or flag has a compatible verified coordinate and the realtime-map capability is available
- **THEN** the detail may navigate to that coordinate on the map without dispatching a new Run query or inventing a fallback point
### Requirement: Server-isolated squad APIs
Squad APIs SHALL authorize the target server and return only bounded local squad, member, flag, and territory fields needed by the management surface.
#### Scenario: Foreign selector is supplied
- **WHEN** a squad, player/member, flag, or territory selector belongs only to another server
- **THEN** Platform returns no foreign record and does not reveal its existence or server identity
#### Scenario: Browser requests protected source material
- **WHEN** a browser attempts to request raw SCUM.db rows, query text, host paths, database identifiers, or Run connection details
- **THEN** the API rejects the request and returns only named safe resource fields
@@ -1,278 +0,0 @@
## 1. Prompt Boundaries
- [x] 1.1 正向提示词 (Positive prompt): Rebuild the SCUM portion of the first-party `服务器管理` area around authentic current-server login events, verified current-service database facts, dedicated local records, trustworthy user/squad/map/gift management, and a preserved AI assistant. Success requires exactly five SCUM tabs, automatic player creation and synchronization, no fabricated values, and permission-checked reviewable writes.
- [x] 1.2 方向提示词 (Directional prompt): Work in `platform/`, `platform_web/`, `plugins/`, and explicit browser-repository protocol contracts while coordinating a separately authorized task in the independent `git@git.npc0.com:admin343/run.git` repository. Use `/Users/tasia/Desktop/code/go/scum/scum_robot` only as a read-only behavioral reference for login ingestion and user/squad/map/gift interactions; derive schema, joins, commands, coordinates, and mutation semantics exclusively from the active bound service. Preserve durable jobs, channel isolation, plugin ownership, API/type directory boundaries, and the black-mecha/magical-girl visual system. Required evidence includes Platform/Plugins/Web and SCUM companion tests, the external Run task's own tests/commit/deployment evidence, current-service and browser acceptance, `scripts/check-structure.sh`, and strict OpenSpec validation.
- [x] 1.3 任务边界 (Boundary prompt): Do not add a `run/` source tree to this repository; modify `/Users/tasia/Desktop/code/go/scum/scum_robot`; edit the independent Run repository except inside its own separately authorized/rooted task; touch unrelated roots; use an unbound repository/reference/cached `SCUM.db` as current-service evidence; trust generated/reference structs as production schema; expose raw SQL/RCON/XML/paths/credentials/sockets to browser or AI; add billing/cloud-host/agent-provider workflows; fabricate players/world facts/backups/results; create a platform-admin approval queue; or reintroduce projection, observation, audit-initiation, manual-refresh, pending-review, or Workflow product concepts. A short-lived read-only snapshot created by Run is allowed only when fenced to the active binding/database identity, timestamped, checksummed, and invalidated on source change.
- [x] 1.4 Before implementation, confirm the browser repository is on `main` and record existing dirty files; if the branch is not `main` or local changes block a safe switch, stop without creating another branch or editing files.
## 2. Minimal Run Probe and Current-Service Evidence Gate
### External Run evidence (2026-08-12)
- The separately rooted Run task implemented and pushed generic schema-probe support at `git@git.npc0.com:admin343/run.git` commit `6cb6ba3` (`add bounded sqlite schema probe`); its focused protocol/runtime tests and `go test ./...` passed.
- The executor advertises `remote.run.db.sqlite.probe`, accepts only package-scoped logical `databases/...` SQLite targets, applies query-only fixed introspection plus binding/job/fence and output bounds, and returns SHA-256-fingerprinted redacted envelopes without SCUM-specific branches or raw database content.
- The active binding `server-run-server-scum-1785923898033` on `枣庄服务器` has been updated and reports `remote.run.db.sqlite.probe`; the endpoint was observed online through the Platform API at `2026-08-12T08:21:27Z` with 28 capabilities including the schema-probe capability.
- A follow-up separately rooted Run task fixed logical SQLite data-target materialization at commit `8fe6f9b` (`Fix SQLite probe data target mapping`); focused runtime/data-target tests and `go test ./...` passed in the independent Run repository before deployment.
- The fixed Run distribution `run-dist-server-scum-1785923898033-windows-amd64-1-zao-zhuang-data-target-run-fix-2026081-6988495348508259730` with checksum `sha256:a5ac9fe31ed0e0f595e70e3d3322f44aa81bd165183530e4be6939aff81c3016` was installed on `枣庄服务器`, and the active endpoint advertises both `remote.run.db.sqlite.probe` and `remote.run.db.sqlite.query`.
### Server-management diagnostic evidence (2026-08-12)
- Per operator direction, the Run install target is `枣庄服务器` (`FyBDIohqPhRx7Cia`); personal server-management MCP inventory and `test_connection` both succeeded for that device.
- Bounded SSH diagnostics checked only process/service/capability metadata and emitted no raw SQL, database content, credentials, SCUM rows, or database reads. The server has a Windows Run process for `server-run-server-scum-1785923898033`, the current SCUM server process is running, and `https://scum.npc0.com/healthz` returned `200` from the server side; per operator clarification, `scum.npc0.com` is the NAT entry back to the local Platform.
- Platform durable probe job `job-remote-adapter-server-scum-1785923898033-3442596095552254276` was queued through `POST /api/v1/server-instances/server-scum-1785923898033/scum/schema-probe` with idempotency key `zao-zhuang-schema-probe-20260812-1632`, claimed by the authenticated active Run binding, acknowledged, and executed with target `databases/scum-database`, `MaxAttempts=1`, and a nonzero fencing token.
- The probe terminal result was accepted by Platform as a typed `sqlite.schema-probe` result with safe status `failed`, safe error code `target_unavailable`, result digest `sha256:41624741855866ce10b3143edba66c3a6b771029256b9489a30f395885526b61`, and observed time `2026-08-12T08:31:45Z`. This proves the Platform durable job path and active Run probe executor are wired, but it does not prove current SCUM schema compatibility.
- The first generated Run workspace contained lifecycle package assets but no `databases/scum-database` logical database target, so current-service schema capture was initially blocked at the package/database-target mapping layer. That failure stayed closed and kept database-backed SCUM read/write gates disabled until the later Run data-target fix produced successful schema metadata.
- Follow-up bounded SSH diagnostics on `2026-08-12` located exactly one active `SCUM.db` candidate by process-relative metadata only, with no SQL execution or row reads; the live file was locked for direct hashing/copying. This supports the package-target diagnosis but is not current-service schema evidence for tasks 2.5-2.9.
- Platform/plugin contracts now declare a plugin-owned `runtimeProfiles.dataTargets` sqlite snapshot target for `scum-database` that materializes to `databases/scum-database` inside the generated Run workspace; SCUM schema-probe dispatch fails closed when that data target is absent. The later independent Run materializer fix supplied the matching generic data-target behavior required for the successful durable probe.
- Operator clarification on `2026-08-12` narrowed the architecture boundary: Platform/plugin must not download or parse `SCUM.db`, but an operator-directed, server-local Python diagnostic on `枣庄服务器` is acceptable discovery evidence when it is read-only, bounded, redacted, and not treated as the product execution path. The diagnostic captured schema metadata in place and is recorded in `evidence/scum-current-service-sqlite-diagnostic-2026-08-12.md`; database-backed product gates remain disabled until durable Run envelopes and versioned adapters are accepted.
- After the Run data-target fix and Platform `sourceFingerprint` decode fix, durable probe job `job-remote-adapter-server-scum-1785923898033-7249327407638289501` succeeded through the product path. Platform persisted probe status `succeeded`, source fingerprint `sha256:d8f3e2f5e9c8241f55b931008309a7ab5f241118a82cbd3620ddedf233e74c13`, schema fingerprint `sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0`, result digest `sha256:ef13678df4add731c758bba157627dc8af80138a69476facd81bbe354c31d7f1`, `161` schema objects, observed time `2026-08-12T12:17:39.0088015Z`, and terminal time `2026-08-12T12:29:24.857542Z`.
- Server-management MCP verification on `2026-08-12` confirmed `test_connection` succeeded for `枣庄服务器`, `SCUMServer.exe` was running, and the target durable probe job had `0` active entries and `0` pending-result entries in the remote Run journal after Platform accepted the typed result. The redacted evidence is stored in `evidence/scum-durable-run-schema-probe-2026-08-12.md`.
- Follow-up server-local read-only Python probes on `2026-08-12` verified the actual current-service joins and nullable fields for external identity, profile/prisoner/entity relationships, squad members, flag/base ownership candidates, vehicle identity, bank-account balances, and XML payload candidates. The results are recorded in `evidence/scum-current-service-sqlite-diagnostic-2026-08-12.md`; unproven rank leader semantics, squad-territory ownership, currency labels/units, command confirmation, and `855` mapping remain gated rather than guessed.
- A task 2.8 confirmation pass on `2026-08-13` separately checked the SCUM live-data manifest, platform/plugin declarations, and read-only `scum_robot` reference behavior for economy commands, gift aliases/transports, map asset/transform authorization, and `855`. No economy command, gift catalog/transport, distributable map asset/transform, or `855` preset mapping is verified enough to enable; the old bridge/domain/reference declarations remain hypothesis or legacy facade material only, and the affected capabilities stay disabled until digest-referenced current-service adapter evidence exists.
- [x] 2.1 Add a release gate that keeps every database-backed SCUM read and write capability disabled until capability-specific current-service evidence matches a versioned plugin adapter; do not add production SQL or mutation assets before this group is complete.
- [x] 2.2 Define the minimal generic schema-probe request/result contract, safe error model, binding identity, bounds, and redacted evidence DTO needed by Platform and the plugin without embedding SCUM table names or host paths in Run-facing generic code.
- [x] 2.3 If the active binding lacks the minimal bounded query-only probe executor, create/hand off a separately authorized task rooted in the independent Run repository, wait for its tests/commit/deployment evidence, and record that evidence here; do not edit or vendor Run source from this change.
- [x] 2.4 Use the personal server-management MCP (`list_devices`, `test_connection`, then `ssh_exec` only when needed) for device inventory, connectivity checks, and bounded diagnostics. Execute product/acceptance schema probes only as Platform durable jobs through the active authenticated Run binding; an operator-directed server-local Python diagnostic may inspect the active database in place for discovery but must not become a Platform/plugin/browser data path.
- [x] 2.5 Capture `sqlite_master`, applicable read-only PRAGMA metadata, indexes, foreign keys, declared types, cardinalities, and small redacted samples for candidate player, profile/entity, squad/member, vehicle, flag/base, economy, coordinate, and character-profile payload sources.
- [x] 2.6 Verify actual joins and meanings for external player identity, profiles/entities, squad ranks/leaders, flag ownership, vehicle identity, currency units/types, nullable fields, and the real table/column containing character XML; do not assume that `user_profile.template_xml` or any reference-project field exists.
- [x] 2.7 Measure coordinate ranges and update cadence, query latency, lock/busy behavior, snapshot consistency, safe timeout/row limits, and whether a verified companion position source is needed for the advertised realtime-map cadence.
- [x] 2.8 Confirm separately which economy commands support safe confirmation, which gift item aliases/transports are real, which distributable map asset/transform is authorized, and what named attributes—if any—the operator means by the `855` preset.
- [x] 2.9 Store sanitized probe evidence or an immutable referenced test artifact and derive the observed schema fingerprint/evidence matrix; do not claim final adapter compatibility until the versioned adapters and query contracts in group 3 exist.
## 3. Plugin SDK, Manifest, and Immutable SCUM Assets
### Login-log fixture evidence (2026-08-13)
- Server-management MCP `list_devices`/`test_connection` confirmed `枣庄服务器` (`FyBDIohqPhRx7Cia`) was reachable, and bounded `ssh_exec` diagnostics observed the active `SCUMServer.exe` process without returning host paths or raw protected values.
- Recursive active-service log discovery found `30` `login_{date}{digits}.log` files under the current service log root. The newest active login log fingerprint is `sha256:752c3ee3789fe73b80245dfcb97776db27f977c4350c3b50516278afbecb9dad`, generation `sha256:57b5be4818757e4d64070e5e0f026dbd471bdba189d0426a38b618423f7e1439`, `0` bytes, last written `2026-08-12T01:18:15.6090680Z`; Run tailing must handle zero-byte active files and later append/rotation boundaries.
- Authentic non-empty login fixtures are UTF-16LE and match `{timestamp}: '{network_redacted} {external_player_id}:{display_name}({profile_local_id})' logged {in|out} at: X={coordinate} Y={coordinate} Z={coordinate}`. Sanitized fixture rows bind expected `scum.login`/`scum.logout` events to server `server-scum-1785923898033`, Run binding `server-run-server-scum-1785923898033`, plugin `game.scum` `0.1.6`, pending parser key `scum-login-log-parser.pending-real-fixture-v1`, parser version `pending-scum-login-log-v1`, parser digest `sha256:5bb528cb9f6e04d8d8b819db3a71f855569c78a5135f22a982301301ae1da50a`, transport cursor `(sourceIdentity, streamGeneration, sequence)`, and separate privacy-safe logical event identities. Evidence is stored in `evidence/scum-login-log-fixtures-2026-08-13.md`.
### Login-log parser implementation evidence (2026-08-13)
- Added plugin-owned parser asset `assets/scum-live/login-log-parser.json` and manifest declarations for `scum.login`/`scum.logout` under `scumLiveData.logParsers`, digest-referenced as `sha256:264835fb36255071fed46dd50724ec511986db901ac8056b08ddafb10f5f0056` while keeping database/write capability gates disabled.
- Implemented versioned companion parser `scum-login-log-parser-v1` / `scum-login-log-v1` for UTF-16LE `login_{date}{digits}.log` lines with transport cursor `(sourceIdentity, streamGeneration, sequence)` and a privacy-safe logical identity that excludes network material, coordinates, source identity, stream generation, and sequence.
- Added focused companion tests for successful login/logout, failed login, partial, undecodable, oversized, malformed lines, rotation/copy-truncate overlap across a new generation, restart/resume acknowledgements, duplicate transport/logical delivery, out-of-order delivery, and absence of network/coordinate material in parsed event storage/fingerprints.
- Verification passed: `(cd plugins/examples/scum-server-plugin/companion && go test ./...)` and `(cd plugins && npm run validate:manifest)`.
### Map asset implementation evidence (2026-08-13)
- Added plugin-owned SCUM current-service coordinate-map metadata and transform assets under `assets/scum-live/map/`, digest-referenced from `scumLiveData.mapAssets` as `sha256:74800836553c7e4372a0747c5e9511adcee940b057194488bbf65bf164df372b` and `sha256:f1941109167a86818e9e71996821884aeb8bd7e863584454b891e525695ba478`.
- The packaged asset is explicitly limited to first-party-generated coordinate metadata and the observed current-service coordinate envelope from `evidence/scum-current-service-sqlite-diagnostic-2026-08-12.md`; no unauthorized SCUM base-map artwork is shipped, and `positions.read` remains disabled until compatible evidence enables it.
- Added manifest-validator checks and fixture tests for map metadata/schema compatibility, transform adapter/schema fingerprint matching, declared bounds/image consistency, known-point projection fixtures, non-finite/out-of-bounds rejection, and digest-preserving adapter incompatibility.
- Verification passed: `(cd plugins && npm test -- manifest-validation.test.ts)` and `(cd plugins && npm run validate:manifest)`.
### Typed RCON and gift catalog gate evidence (2026-08-13)
- Reviewed current-service evidence in `evidence/scum-current-service-sqlite-diagnostic-2026-08-12.md`: Fame/currency commands, notification-as-RCON semantics, gift aliases/transports, conclusive per-item receipts, and catalog aliases remain unverified. Therefore the production SCUM manifest continues to declare no `scumLiveData.typedRconTemplates`, no `scumLiveData.giftCatalogs`, and no digest-referenced RCON/gift assets.
- Kept `economy-command.write` and `gift-command.write` disabled with `missing` evidence status; no command text, gift alias, starter-pack catalog, legacy hard-coded gift, or notification transport is exposed through live-data assets.
- Tightened SDK/schema/validator contracts so any future SCUM typed RCON template must carry a bounded `confirmationSchemaRef` in addition to payload/result schemas, contained asset paths, immutable digests, protected RCON transport, and `server.game-client.command` permission.
- Added manifest tests proving production omits unverified typed RCON templates and gift catalogs, and rejects any SCUM typed RCON declaration without a conclusive confirmation schema.
- Verification passed: `(cd plugins && npm test -- manifest-validation.test.ts)`.
### Current-service baseline refresh (2026-08-13)
- Per operator correction, the change now stores current-service structure baselines before attempting further capability declarations. `evidence/scum-current-service-db-schema-baseline-2026-08-13.md` records the full `161`-table compact schema inventory from a server-local read-only Python diagnostic, including row counts, columns, primary-key columns, foreign-key counts, and index counts without raw rows, SQL, XML, paths, credentials, sockets, IPs, or player identities.
- `evidence/scum-current-service-log-structure-baseline-2026-08-13.md` records the process-adjacent log inventory from a successful server-local diagnostic: `1200` log/text files across hashed directories, including `login_{digits}.log`, `admin_{digits}.log`, `gameplay_{digits}.log`, `economy_{digits}.log`, `chat_{digits}.log`, `vehicle_destruction_{digits}.log`, `SCUM.log`, and service/runtime log families. Raw log lines and paths were not emitted or stored.
- `evidence/scum-current-service-content-features-baseline-2026-08-13.md` records redacted content features from the current service: XML tag/attribute/value-shape summaries, selected DB content distributions, and log skeleton marker sets. It confirms `user_profile.template_xml` parses as `CharacterTemplate` with named character attributes and `Skill` entries, confirms sampled `prisoner_skill.xml` values are not parseable XML documents, and classifies `item_entity.xml` as item metadata rather than a profile attribute source.
- A broader line-shape diagnostic confirmed coordinate-shaped and network-shaped tokens exist in multiple log families, so parser assets must stay per-file-pattern and strip network material before durable storage. The authoritative file inventory remains the successful v4 evidence file.
- Task 3.10 remains unchecked: the refreshed content-feature baseline confirms `user_profile.template_xml` is the parseable named-attribute source candidate, but it still does not prove preserving patch semantics, offline/backup/readback requirements, activation semantics, write safety, or an operator-confirmed `855` preset mapping.
### Adapter evidence matrix and release gates (2026-08-13)
- Matched the production SCUM live-data adapter gates to the current-service schema fingerprint `sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0` and packaged query/map asset digests. The schema-probe gate is now `enabled` / `compatible` because the product durable Run schema-probe path succeeded, while the database-backed read gates remain `disabled` / `missing` until the group 4 SQLite-template terminal envelope is implemented and accepted.
- Added manifest-validator enforcement that every declared SCUM SQLite query, typed command, guarded mutation, map asset, and gift catalog must have a matching capability gate with the same adapter version, schema fingerprint where applicable, and immutable asset digest. This prevents future assets from bypassing the release gate matrix.
- Kept unsupported or ambiguous write capabilities disabled: no typed RCON templates, no gift catalogs, no guarded XML mutations, no `855` preset, and no command/readback claims were added. Squad rank/leader, vehicle ownership, territory semantics, and sub-10s map cadence remain nullable/gated instead of invented.
- Verification passed: `(cd plugins && npm test -- manifest-validation.test.ts)`, `(cd plugins && npm run validate:manifest)`, and `(cd platform && go test ./validator ./domain)`.
- [x] 3.1 Add SDK and manifest types for versioned log parsers, SQLite query assets, parameter/result schemas, capability-specific schema fingerprints, sync cadence/limits, map metadata, typed RCON templates, gift item catalogs, and guarded mutation declarations.
- [x] 3.2 Extend plugin validation to require asset digests, contained package paths, unique template keys, bounded parameters/results, compatible adapter versions, and explicit permission bindings, and to reject raw caller-supplied SQL, RCON, XML, paths, or undeclared parameters.
- [x] 3.3 Capture sanitized authentic login-log fixtures from the active service and bind their expected events to server, Run binding, plugin version, parser version/digest, a transport cursor `(source identity, stream generation, sequence)`, and a separate privacy-safe logical event identity stable across rotation overlap.
- [x] 3.4 Implement the versioned SCUM login/logout parser and tests for successful login/logout, failed login, partial/undecodable/oversized/malformed lines, copy-truncate/rotation overlap under a new generation, Run restart/resume, duplicate delivery, and out-of-order delivery while discarding IP/network material before storage or logical fingerprinting.
- [x] 3.5 Add parameterized, read-only player identity/detail/economy/session-enrichment query assets and exact result schemas only for joins and fields proven by the probe.
- [x] 3.6 Add parameterized squad/member, vehicle, flag/territory, and position query assets and exact result schemas, keeping ambiguous ranks, ownership, coordinates, and missing numeric values null.
- [x] 3.7 Add query-asset tests for single SELECT/CTE or approved introspection boundaries, parameter binding, pagination/cursors, timeout/row/byte limits, schema-version matching, and rejection of DDL, mutation, `ATTACH`, extension loading, write PRAGMAs, and multi-statement input.
- [x] 3.8 Package the authorized SCUM map asset, identity/version, verified world bounds, layer metadata, and coordinate transform, with fixture tests for known points, out-of-bounds/non-finite coordinates, and adapter incompatibility.
- [x] 3.9 Declare only verified typed RCON templates for supported Fame/currency/notification/gift operations and a version-scoped gift item catalog; omit any command whose execution and confirmation semantics remain unknown.
- [ ] 3.10 Declare a guarded preserving XML mutation only after the real XML source and named attributes are proven; expose `855` only as a reviewed named-attribute preset and never as a database column, generic integer field, or guessed mapping.
- [x] 3.11 Add immutable asset/digest declarations and plugin package validation; defer generated Run-package execution wiring until the complete protocol/result envelope and independent Run capability evidence in group 4 are frozen.
- [x] 3.12 Remove SCUM Workflow/projection declarations and obsolete page/action declarations from the plugin manifest while preserving the five required pages and AI configuration assistance.
- [x] 3.13 Match the observed fingerprint/evidence matrix against each completed adapter, add per-capability compatibility/release-gate tests, and leave every unsupported or ambiguous player/squad/vehicle/flag/position/write capability disabled.
## 4. Generic External Run Execution and Result Contracts
### Platform probe wiring evidence (2026-08-12)
- Platform now has an internal-only `RequestSCUMSchemaProbeForSession` path that builds a durable `remote.run.db.sqlite.probe` job from the SCUM plugin's manifest declaration, active runtime binding, logical target key, adapter version, and bounded probe limits; public remote-adapter and plugin-page requests for the probe capability are denied.
- Run terminal results may carry `executionResult.sqliteSchemaProbe`; Platform DTO/domain/validator/job-channel code validates the typed redacted envelope, job/request identity, and binding fence before persisting it on the durable job.
- Generated Run packages now carry redacted autonomous lifecycle `dataTargets` entries for plugin-owned sqlite snapshots, and browser-facing runtime-profile responses continue to omit those source declarations.
- Focused evidence: `go test ./dto ./service -run 'Test(RunJobResultRequestParsesSQLiteSchemaProbeEnvelope|SCUMSchemaProbeDispatchIsPlatformScheduledAndFenced|RemoteAdapterRequestPropagatesTypedInputsToRunJob)'` and `(cd platform && go test ./...)` passed locally. These tests did not prove the active Windows Run deployment or current SCUM schema, so the later current-service and external-Run acceptance tasks stayed gated until additional evidence was recorded.
### SQLite-template contract freeze and Run handoff evidence (2026-08-13)
- Platform protocol docs now freeze the read-only `sqliteTemplate` request and `sqlite.template-query` terminal envelope: template key, logical target key, adapter/schema fingerprint, asset digest, parameter digest, bounded scalar parameters, query-only execution limits, row/result-byte limits, cancellation, and stable safe status/error codes.
- Added Platform domain/DTO/job-channel/validator/service contracts for `SCUMSQLiteTemplateRequest` and `SCUMSQLiteTemplateResult`. Run assignments can carry only the typed template request, Run results can return only the typed envelope, and Platform verifies leased job identity, binding, capability, target/template key, schema fingerprint, asset digest, parameter digest, row count, and result digest before accepting a successful result.
- Added focused tests for DTO parsing, safe validator rejection of raw SQL/path-like material and loose bounds, typed row/result validation, service lease fencing, and digest mismatch rejection. Verification passed: `go test ./dto ./validator ./service -run 'Test(RunJobResultRequestParsesSQLite|ValidateSCUMSQLiteTemplate|CoreServiceRunJobSQLiteTemplateEnvelopeIsFencedToLease)'`.
- Recorded the separately rooted Run handoff prompt in `evidence/run-sqlite-template-execution-handoff-2026-08-13.md` with positive, directional, and boundary prompts. This is a contract handoff only; tasks 4.7, 4.9, and DB-backed read gates remain unchecked until tested Run commit/deployment/terminal-envelope evidence is recorded.
### Typed RCON-template contract freeze and Run handoff evidence (2026-08-13)
- Platform protocol docs now freeze the generic `rconTemplate` request and `rcon.template-command` terminal envelope: logical transport/target/template keys, adapter/schema fingerprint when required, asset digest, payload digest, confirmation digest, target identity digest, idempotency key, bounded scalar payload, safe review reason, response/confirmation limits, conclusive confirmation status, and stable safe result/error codes.
- Added Platform domain/DTO/job-channel/validator/service contracts for `SCUMTypedRCONTemplateRequest` and `SCUMTypedRCONTemplateResult`. Run assignments can carry only the typed template request, not browser command text; Run results can return only safe digests/status/summary; Platform verifies leased job identity, binding, transport, template, schema, asset, payload, confirmation, and target digests before accepting success.
- Added focused tests for DTO parsing, validator rejection of raw command-like payload keys, unsafe review reasons, loose bounds, unconfirmed success, unsafe summaries, service lease fencing, and payload digest mismatch rejection. Verification passed: `go test ./dto ./validator ./service -run 'Test(RunJobResultRequestParses(SQLite|TypedRCON)|ValidateSCUM(SQLiteTemplate|TypedRCON)|CoreServiceRunJob(SQLiteTemplate|TypedRCONTemplate)EnvelopeIsFencedToLease)'`.
- Recorded the separately rooted Run handoff prompt in `evidence/run-typed-rcon-template-execution-handoff-2026-08-13.md` with positive, directional, and boundary prompts. This is a contract handoff only; typed RCON templates, gift catalogs, write gates, and task 4.7 remain unchecked until tested Run commit/deployment/current-service command/readback evidence is recorded.
### Guarded SQLite/XML mutation contract freeze and Run handoff evidence (2026-08-13)
- Platform protocol docs now freeze the generic `guardedMutation` request and `sqlite.guarded-mutation` terminal envelope: logical target/template key, adapter/schema fingerprint, asset digest, target identity digest, expected row/value/XML digests, preserving patch digest, backup/offline/danger-confirmation evidence digests, readback expectation digest, idempotency key, bounded scalar payload, safe review reason, single-row limit, affected-row count, readback status, and stable safe result/error codes.
- Added Platform domain/DTO/job-channel/validator/service contracts for `SCUMGuardedMutationRequest` and `SCUMGuardedMutationResult`. Run assignments can carry only the typed guarded mutation request, not raw SQL/XML/browser mutation text; Run results can return only safe digests/status/summary; Platform verifies leased job identity, binding, template, schema, asset, target, guard, patch, backup, offline, danger confirmation, and readback digests before accepting success.
- Added focused tests for DTO parsing, validator rejection of raw XML/SQL/path-like material, `855` field payloads, missing backup/offline/danger-confirmation/readback digests, loose affected-row bounds, unsafe summaries, multi-row success, missing readback, service lease fencing, and patch digest mismatch rejection. Verification passed: `go test ./dto ./validator ./service -run 'Test(RunJobResultRequestParses(SQLite|TypedRCON|GuardedMutation)|ValidateSCUM(SQLiteTemplate|TypedRCON|GuardedMutation)|CoreServiceRunJob(SQLiteTemplate|TypedRCONTemplate|GuardedMutation)EnvelopeIsFencedToLease)'`.
- Recorded the separately rooted Run handoff prompt in `evidence/run-guarded-sqlite-xml-mutation-handoff-2026-08-13.md` with positive, directional, and boundary prompts. This is a contract handoff only; no guarded XML mutation asset, `855` preset, write gate, external Run implementation evidence, or real-service mutation acceptance is enabled by this task.
- Session verification also passed: `(cd platform && go test ./...)`, `scripts/check-structure.sh`, `openspec validate replace-scum-projections-with-real-data-management --strict`, and `git diff --check`.
### Log-source tailing contract freeze and Run handoff evidence (2026-08-13)
- Platform protocol docs now freeze the generic `log.parsed-events` terminal envelope for plugin-declared log-source tailing/backfill: leased source/stream key, parser key/version, adapter version, parser asset digest, parser digest, first/last redacted source identity and stream-generation cursors, event count, tail state, replay/partial flags, logical event digests, payload digests, safe summaries, safe errors, and applied limits.
- Added Platform domain/DTO/job-channel/validator/service contracts for `SCUMParsedLogBatchResult`, parsed events/cursors, batch bounds, and log-tail states. Run results can carry only sanitized scalar event payloads, not raw log lines, paths, globs, IP/network identifiers, SQL, XML, sockets, credentials, or unredacted player identities.
- Service job completion accepts `log.parsed-events` only for `logs.backfill` jobs carrying a leased declared `file.tail` source, checks server/Run endpoint, source/stream key, plugin id/version when frozen, parser key/version/digest/adapter version when frozen, and single source identity/generation boundaries.
- Added focused tests for DTO parsing, validator rejection of raw-line/network/path material, loose max-line bounds, missing parser digest, service lease fencing, and parser digest mismatch rejection. Verification passed: `go test ./dto ./validator ./service -run 'Test(RunJobResultRequestParses(SQLite|TypedRCON|GuardedMutation|ParsedLog)|ValidateSCUM(SQLiteTemplate|TypedRCON|GuardedMutation|ParsedLog)|CoreServiceRunJob(SQLiteTemplate|TypedRCONTemplate|GuardedMutation|ParsedLogBatch)EnvelopeIsFencedToLease)'`.
- Recorded the separately rooted Run handoff prompt in `evidence/run-log-source-tailing-handoff-2026-08-13.md` with positive, directional, and boundary prompts. This is a contract handoff only; no external Run implementation evidence, parsed-login ingestion enablement, or player/session creation acceptance is enabled by this task.
### Run acceptance audit and Platform capability negotiation (2026-08-13)
- Re-audited the browser evidence files, ignored independent Run checkout, and `枣庄服务器` through server-management MCP. The audit found only the prior schema-probe/data-target Run commits and redacted current-service probe evidence; it found no independent Run implementation/deployment/acceptance evidence for generic SQLite-template execution, typed RCON-template execution, guarded SQLite/XML mutation execution, parsed log-source tailing, or their late/duplicate terminal-result behavior. The audit is recorded in `evidence/scum-capability-negotiation-and-run-acceptance-audit-2026-08-13.md`, and task 4.7 remains unchecked.
- Added Platform-side read-only SCUM capability negotiation at `GET /api/v1/server-instances/{id}/scum/capabilities`. It evaluates each manifest gate independently for the active server/plugin/Run endpoint/runtime binding using the bound Run capability list and latest accepted typed terminal evidence for matching binding, adapter, schema fingerprint, database identity, and asset digests.
- The negotiation route returns only safe capability state and reasons, dispatches no Run job, and does not expose terminal rows, SQL, XML, RCON text, host paths, DSNs, sockets, credentials, protected payloads, or raw current-service content.
- Verification passed: `go test ./domain ./dto ./service ./api -run 'TestSCUMCapabilityNegotiation|TestSCUMSchemaProbeEndpointQueuesPlatformScheduledDurableJob|TestLegacySCUMEndpointsReturnNotFoundWithoutDispatchingJobs'`.
- [x] 4.1 Add Platform protocol contracts under `platform/protocol`, API DTOs under `platform/dto`, validation under `platform/validator`, and plugin contracts/assets under `plugins/sdk` and `plugins/schemas`, plus contract documentation/mocks for probes, read-only template execution, typed RCON, guarded SQLite/XML mutation, parsed log events, and terminal result envelopes.
- [x] 4.2 Freeze the generic executor/result contract and hand off a separately authorized Run-repository task for packaged SQLite-template execution with query-only connections, bound parameters, one-statement validation, short busy/operation timeouts, cancellation, and row/result-byte limits.
- [x] 4.3 Require the independent Run task to return typed envelopes containing server/plugin binding, adapter/schema version, template key, asset digest, job identity, observed time, checksum, rows or affected-row count, and stable safe result/error codes.
- [x] 4.4 Require the independent Run task to implement generic plugin-owned typed RCON-template execution without accepting browser command text or adding branches for SCUM, SCUM keys, SCUM commands, or SCUM tables.
- [x] 4.5 Require the independent Run task to implement generic guarded single-row SQLite/XML mutation execution with expected identity/value/checksum guards, a bounded transaction, preserving XML patching, rollback on zero/multiple affected rows, and read-after-write confirmation.
- [x] 4.6 Require the independent Run task to implement or extend generic plugin-declared log-source tailing so cursor persistence, rotation, truncate, restart, partial-line buffering, parser digest fencing, logical event fingerprinting, and replay remain independent of SCUM-specific source paths.
- [ ] 4.7 Verify from the independent Run task's acceptance evidence that control/job/log/artifact priorities, leases, fencing, acknowledgements, idempotency, and late/duplicate terminal-result handling remain intact for the new generic capabilities.
- [x] 4.8 Add Platform-side capability negotiation so probe, player/squad/vehicle/flag/position reads, typed commands, gifts, and guarded mutations are gated independently for each active Run/plugin/adapter binding.
- [ ] 4.9 After the external Run contract tests/commit/deployment evidence is available, wire immutable assets and digests into generated Run packages and add distribution/contract tests proving Platform sends only template keys, bounded parameters, adapter version, and expected digest.
## 5. Dedicated Platform SCUM Persistence
- [ ] 5.1 Define SCUM domain types and narrow repository/service interfaces in the required `platform/` directories, keeping API DTOs, database models, validation, and repository contracts separate.
- [ ] 5.2 Add dedicated player, session, player-detail, source-event, sync-cursor, capability-evidence, and completed-generation records with server-scoped identities and nullable unknown fields.
- [ ] 5.3 Add dedicated squad, squad-member, vehicle, flag/territory, and current-position records with source checksum/time, adapter version, generation, and server-scoped indexes.
- [ ] 5.4 Add dedicated gift-package, gift-item, frozen-delivery, per-item receipt, eligibility-period reservation, notification-result, and immutable completed-delivery records.
- [ ] 5.5 Implement normalized MySQL models and explicit migrations with uniqueness constraints for player/event/session identity, generation rows, gift idempotency, and concurrent eligibility reservations.
- [ ] 5.6 Implement the default file-backend SCUM store as a platform-owned SQLite sidecar under the configured data directory, with pinned driver/migration behavior and no high-frequency writes to the global metadata snapshot.
- [ ] 5.7 Implement the memory backend with the same server isolation, uniqueness, transaction, null, generation, and idempotency semantics for tests.
- [ ] 5.8 Implement transactional generation commits so a complete validated scan may mark missing rows absent, while partial/failed/older scans preserve the last completed generation unchanged.
- [ ] 5.9 Add health, migration, rollback/disable, and database-instance invalidation behavior; never migrate old projection/Workflow snapshot values into the new tables as game facts.
- [ ] 5.10 Add backend-parity tests for migrations, uniqueness, concurrent first login, nullable numeric values, failed-generation retention, server isolation, and gift reservation/idempotency constraints.
## 6. Authentic Login Ingestion and Automatic Synchronization
- [ ] 6.1 Add a typed parsed-log event ingress that authenticates and correlates server binding, plugin/adapter/parser digest, transport cursor `(source identity, stream generation, sequence)`, separate stable logical event identity, and occurrence time before calling SCUM ingestion.
- [ ] 6.2 Atomically upsert one `(server_instance_id, external_player_id)` player and open one session for an authentic successful login without waiting for database enrichment.
- [ ] 6.3 Close only the matching current session on logout, do not fabricate a session for an unmatched logout, and prevent older logout/login events from regressing a newer display name, last-seen time, or online session.
- [ ] 6.4 Close or mark sessions unknown with a bounded reason when a binding/source epoch is replaced, server stops, or log continuity is lost without a logout; never leave them permanently confirmed online from database save timestamps.
- [ ] 6.5 Strip raw IP addresses and all network identifiers before durable player/session/event storage and exclude them from every SCUM API, diagnostic, and AI context.
- [ ] 6.6 Add ingestion tests for concurrent first login, replayed events, duplicate/out-of-order events, failed login, unmatched logout, partial-line resume, copy-truncate/rotation overlap replay under a new generation, Run restart, parser-digest mismatch, cross-server events, and database timestamps that must not imply online state; an overlapped logical login SHALL still produce one player/session.
- [ ] 6.7 Add an automatic scheduler that starts a capability-specific probe when an active binding lacks current evidence, starts an initial bounded scan after compatibility succeeds, then uses plugin-declared jittered cadences, backoff, and per-server/per-capability concurrency limits.
- [ ] 6.8 Schedule bounded player-detail enrichment after a new login without delaying player creation, and use the measured safe position cadence or a declared verified companion source without fabricated intermediate motion.
- [ ] 6.9 Create every durable Run job before dispatch and attach the expected server/plugin/template/digest/schema/generation correlation needed for immediate, late, and duplicate results.
- [ ] 6.10 Add a terminal-job hook that validates the full result envelope and row schema before calling the matching transactional SCUM sync service.
- [ ] 6.11 Reject malformed, foreign, duplicate, or older results idempotently; commit only complete generations and retain prior rows plus a safe connection/sync error after locks, timeouts, partial results, or incompatible schemas.
- [ ] 6.12 Publish safe player/session/squad/map updates through a platform-owned event stream/SSE while keeping Platform Web reads backed by local records.
- [ ] 6.13 Add tests proving page opens/retries never create schema probes, Run queries, projection refreshes, real-data refreshes, manual syncs, or audit jobs.
## 7. Player Management APIs
- [ ] 7.1 Add safe player-list/detail/session DTOs, request schemas, validators, API clients/contracts, and routes in their fixed directories without exposing raw logs, database rows, XML, SQL, paths, or network material.
- [ ] 7.2 Implement server-side player pagination, bounded name/external-ID search, online and squad filters, deterministic allowlisted sorting, and total/page metadata against the local SCUM store.
- [ ] 7.3 Implement player detail with identity, verified nullable facts, current verified coordinate, bounded login history, source collection times, and explicit not-yet-synchronized/confirmed-empty/incompatible/connection-failed states.
- [ ] 7.4 Enforce target-server read authorization before lookup and prevent cross-server player IDs, squad filters, selectors, counts, or existence from leaking.
- [ ] 7.5 Preserve unknown values as null/absent throughout storage, service, DTO, and JSON handling; never substitute zero, sample data, guessed profile IDs, or database save time as online evidence.
- [ ] 7.6 Remove player-intelligence, alias-history, shared-IP, access-attempt, automatic-risk, security-signal, and hard-coded increment dependencies from the SCUM player API and ingestion flow.
- [ ] 7.7 Add repository/service/API tests for search/filter/sort bounds, pagination stability, confirmed-empty versus unavailable data, nullable facts, login history, authorization, cross-server isolation, and absence of manual-refresh endpoints.
## 8. Squad Management and Realtime Map APIs
- [ ] 8.1 Implement server-scoped paginated/searchable/sortable squad list and detail APIs with verified members, adapter-declared rank meanings, leader when proven, flags/territory, and ordinary collection times.
- [ ] 8.2 Keep leader, rank, territory, and ownership unknown when joins or enum meanings are ambiguous, gate squad/member/flag/territory resources independently, and test that reference constants or proximity/history heuristics are not evidence.
- [ ] 8.3 Implement bounded local vehicle and flag APIs containing only verified identity, class/status, coordinate, ownership, and collection fields supported by each active adapter capability.
- [ ] 8.4 Implement a safe current-map dataset API for players, vehicles, flags, squads/territories, layer filters, and source collection times without returning database or Run connection material.
- [ ] 8.5 Apply the plugin-declared map version/bounds/coordinate transform server-side or through a shared tested contract, rejecting incompatible, non-finite, and out-of-bounds coordinates instead of generating fallback points.
- [ ] 8.6 Publish newer verified position/map updates through the platform event stream with entity identity and server/version fencing; page subscriptions must not dispatch Run reads.
- [ ] 8.7 Enforce server authorization, bounded selectors/result sizes, and no cross-server existence leaks across all squad/map endpoints.
- [ ] 8.8 Add service/API tests for successful and failed generations, per-resource gating, unknown ownership/ranks, last-complete rows after interruption, transform fixtures, layer filtering, event ordering, and incompatible-map unavailable results.
## 9. Gift Management, Eligibility, and Delivery
- [ ] 9.1 Add server/plugin-version-scoped gift package and typed item validators for names, classification, active state, quantities, eligibility rules, period limits, and only plugin-catalogued item keys.
- [ ] 9.2 Implement `server.game-client.read` package/history reads, `server.game-client.maintenance` package create/update/enable/delete, and `server.game-client.command` reviewed delivery APIs using the current session's effective target-server permissions.
- [ ] 9.3 Evaluate per-player/server/period eligibility in the server's declared timezone and reserve limit capacity transactionally for in-flight, partial, and unknown deliveries so concurrent requests cannot exceed the configured limit.
- [ ] 9.4 Freeze target player, package/items, quantities, plugin/game/adapter version, period reservation, delivery identity, and idempotency key before dispatch; later package edits must not alter a delivery.
- [ ] 9.5 Dispatch only plugin-declared typed item aliases and quantities through the controlled command path, never arbitrary browser command strings.
- [ ] 9.6 Treat queued, claimed, acknowledged, or started jobs as in progress; record `delivered` only after a schema-valid conclusive receipt for every required item.
- [ ] 9.7 Preserve reservations and per-item receipts for timed-out, missing, partial, or unknown outcomes, require confirmation before an explicit retry, and never automatically redeliver the whole package or already confirmed items.
- [ ] 9.8 Release a period reservation only after conclusive evidence that no game effect occurred; record post-delivery notification failure separately without changing the delivered fact or triggering redelivery.
- [ ] 9.9 Add server-scoped package statistics, searchable/filterable pagination, real player selection, reviewed send requests, and ordinary delivery-history/result APIs without Workflow or audit terminology.
- [ ] 9.10 Add concurrency, idempotency, timezone-boundary, cross-server, catalog-version, partial/unknown outcome, reservation-release, notification-failure, permission, and immutable-history tests.
## 10. Controlled Manual and AI/Agent Writes
- [ ] 10.1 Define one named-field write draft containing server/player/action/field, verified current value/checksum, proposed value, reason, adapter/digest, idempotency key, safety requirements, and a safe reviewable diff.
- [ ] 10.2 Authorize the current user's effective target-server permission when a draft is created, reviewed, confirmed, and dispatched, with backend checks authoritative and no component-principal, manifest-declaration, or callback-presence bypass.
- [ ] 10.3 Supply the plugin page host with the current session's effective permissions and readable denial reasons while keeping direct API denial authoritative.
- [ ] 10.4 Route verified Fame/cash/gold writes through plugin-owned typed RCON templates with `server.game-client.command`, validated absolute target values, explicit reason, idempotency, and declared confirmation reads.
- [ ] 10.5 Route database/XML writes only with effective `server.game-client.maintenance`, verified target/offline or maintenance state when required, genuine same-instance restorable backup evidence, expected before values/checksum, and an explicit dangerous-operation confirmation; do not create a platform-admin approval workflow or approval queue.
- [ ] 10.6 Execute preserving named-attribute XML patches only against the probe-confirmed source, reject malformed XML or absent/undeclared nodes, preserve unknown content, and update exactly one guarded row.
- [ ] 10.7 Keep `855` absent until its named mapping is confirmed; when available, expand it into an explicit per-attribute before/after review rather than accepting `fieldKey=855`, `prisoner.value`, or a generic integer.
- [ ] 10.8 Validate command/mutation terminal envelopes and readback before success, update local verified details only after conclusive confirmation, and represent missing/mismatched results as failed, conflict, or unknown without automatic retry.
- [ ] 10.9 Never chain kill, death, respawn, kick, or another destructive activation to attribute save; any verified required activation must be a separate explicitly named, permission-checked, confirmed action.
- [ ] 10.10 Preserve AI-assisted plugin configuration through the existing platform-mediated reviewable config-diff path without exposing provider keys or granting the plugin page direct write authority.
- [ ] 10.11 Make AI/Agent player-operation suggestions create the exact same named-field draft as manual forms, reject undeclared fields/protected payloads, retain the initiating user, and require that user's current effective permission plus explicit confirmation.
- [ ] 10.12 Add tests for read-only users, revoked permissions between draft and dispatch, cross-server targets, invented AI fields, stale checksums, fake backup evidence, unsafe online state, zero/multiple rows, malformed XML, missing nodes, unknown results, confirmation mismatch, duplicate requests, and no approval-queue creation.
## 11. Five-Tab SCUM Product Surface
- [ ] 11.1 Place SCUM API clients/types, route definitions, page contracts, component contracts, schemas/validators, bridge/SDK types, and shared utilities in their fixed frontend/plugin directories rather than inside page components.
- [x] 11.2 Make the SCUM detail navigation contain exactly `用户管理`, `队伍管理`, `实时地图`, `礼包管理`, `AI 助手` in that order, default to `用户管理`, and fall back from legacy `manage`, `workflows`, or invalid sections without affecting non-SCUM plugins.
- [ ] 11.3 Preserve the existing server-list deployment action and relocate display-name and administrator-membership controls to a compact detail-header settings drawer/dialog with existing owner authorization; do not add another permanent management tab.
- [ ] 11.4 Build `用户管理` as a full-width server-paginated table with bounded filters/search/sort, online evidence, nullable verified facts, detail/login-history drawer, and explicit named-field edit dialogs.
- [ ] 11.5 Build `队伍管理` as a full-width paginated squad table and semantic detail drawer separating leader/ranks, members, flags, and territory while showing unknown facts honestly.
- [ ] 11.6 Build `实时地图` from the authorized map asset and tested transform with distinct player/vehicle/flag/territory layers, filters, legend, source coordinates/collection time, safe live updates, and a clear incompatible/unavailable state.
- [ ] 11.7 Build `礼包管理` with real package statistics/table, CRUD dialogs, typed items and limits, real player selection, reviewed delivery, and delivery history for in-progress/delivered/failed/partial/unknown/notification-failure outcomes.
- [ ] 11.8 Keep `AI 助手` as the final tab for plugin configuration diffs and controlled player-operation drafts, with apply disabled when effective permission is absent.
- [ ] 11.9 Hide or disable write controls according to current effective permissions with textual reasons, and re-check authorization server-side on every apply request.
- [ ] 11.10 Load only platform-local resource APIs and the platform event stream; display ordinary connection and last synchronized/collected information, and let retry repeat only a local read.
- [ ] 11.11 Reuse shared tables, drawers, dialogs, status, `console-*`, and theme tokens; preserve black-mecha and magical-girl readability, keep CSS declarations compressed, and add no page-local fixed decoration or generic opaque SaaS card system.
- [ ] 11.12 Cover keyboard/focus behavior, non-color-only status, responsive full-width working surfaces, bounded compact actions, and readable destructive confirmations.
- [ ] 11.13 Add frontend tests for exact navigation/order/default/fallback, settings ownership, local-only loading, permission presentation, null/empty/error states, real map/gift data, AI review parity, and absence of fake actions or placeholder records.
## 12. Projection, Workflow, Intelligence, and Placeholder Removal
- [x] 12.1 Inventory references before deletion and distinguish SCUM-only projection/Workflow/player-intelligence code from generic durable Run jobs, internal write evidence, and non-SCUM consumers.
- [x] 12.2 Remove SCUM Workflow instance/step/status APIs, repositories, services, routes, clients, manifest declarations, page components, workflow creation/listing, pending-review counters, operation approval routes, and approval/confirmation queue surfaces without removing generic Run job execution.
- [ ] 12.3 Remove SCUM projection/observation/freshness snapshot types, ingestion, metadata fields, refresh/audit services, page actions, and manual synchronization endpoints; removed endpoints must return not found or a stable removal response and dispatch no job.
- [ ] 12.4 Remove SCUM dependencies on alias history, shared IP/fingerprint, access attempts, automatic risk/security signals, and player intelligence; delete shared implementation only after proving it has no remaining non-SCUM consumer.
- [x] 12.5 Remove the standalone `管理` and `Workflow 状态` tabs, legacy placeholders/routes, fake maintenance/backup evidence, hard-coded increments, opaque `855` action, hard-coded `starter-pack`, fixed notification, gradient-only map, arbitrary percentage points, and sample/generated players/world data.
- [x] 12.6 Remove runtime product copy including `Workflow 状态`, `投影`, `真实投影`, `玩家投影`, `刷新投影`, `刷新世界投影`, `刷新真实数据`, `发起审计`, `创建发放 workflow`, `typed workflow`, `typed observation`, `typed operation`, `待审操作`, `审批/确认队列`, `清理旧入口`, `目前暂无真实投影数据`, `暂无真实投影数据`, `暂无玩家投影`, and `Companion 可用`.
- [ ] 12.7 Add upgrade behavior that starts the new SCUM stores empty, populates only from post-upgrade authenticated logs/current-service sync, invalidates incompatible bindings, and never translates old snapshot values into real facts.
- [ ] 12.8 Add a rollback/feature-disable path that disables incompatible SCUM reads/writes while leaving diagnostic local records intact and never re-enables fake projection or Workflow data.
- [x] 12.9 Add scoped runtime-source/manifest/API tests or assertions proving banned copy/actions/routes are absent, removed endpoints cannot dispatch jobs, and generic lifecycle, logs, jobs, AI provider management, and non-SCUM plugin navigation still work.
- [x] 12.10 Record the supersession mapping from the completed-but-unarchived legacy SCUM changes to these unique replacement capabilities; do not archive obsolete deltas into the main baseline, and leave any history consolidation to a separate reviewed skip-specs/equivalent archival task.
## 13. End-to-End Verification and Release
- [ ] 13.1 Run focused Go tests after each Platform repository, migration, ingestion, scheduler, API, gift, permission, and terminal-result change, then run `(cd platform && go test ./...)`.
- [ ] 13.2 Run plugin SDK/parser/query/map/manifest tests and final checks with `(cd plugins && npm run typecheck && npm run test && npm run validate:manifest)`, then run `(cd plugins/examples/scum-server-plugin/companion && go test ./...)`.
- [ ] 13.3 Run frontend tests and final checks with `(cd platform_web && npm run typecheck && npm run test && npm run build)`.
- [x] 13.4 In the separately authorized Run-repository task, run `go test ./...` from that repository's own root and record its tested commit/version plus deployment compatibility evidence here; do not edit, stage, or commit Run source from the browser-repository apply task.
- [ ] 13.5 Against the active current service, verify read-only schema compatibility, authentic login-created local player/session data, automatic player/squad/vehicle/flag/position sync, generation retention after an induced safe read failure, and no unbound copied/cache/fixture database use.
- [ ] 13.6 Verify login-log acceptance with sanitized real fixtures covering partial lines, failed login, rotation, truncate, restart/resume, duplicate, and out-of-order events plus server/Run binding/plugin/parser-digest fencing.
- [ ] 13.7 Extend and run `scripts/browser-acceptance.sh` against synchronized local data for the exact five tabs, local-only page reads, user/squad/map/gift behavior, permission-aware edit reviews, AI configuration/player drafts, legacy-route fallback, and absence of projection/Workflow/manual-refresh/audit controls.
- [ ] 13.8 Verify controlled writes against isolated test data or an explicitly authorized test player only; prove permission, explicit confirmation, guards, backup/offline requirements, idempotency, readback, unknown-result handling, XML preservation, and no implicit respawn.
- [ ] 13.9 Perform scoped security checks proving browser/API/AI/job-safe responses contain no raw SQL, RCON, XML, host/database paths, credentials, sockets, IP data, or cross-server resource existence, and that external Run has no SCUM-specific executor branches.
- [ ] 13.10 Run `scripts/check-structure.sh` and fix every relevant structural violation without moving implementation outside its owning root.
- [ ] 13.11 Run `openspec validate replace-scum-projections-with-real-data-management --strict`, review task evidence and the final diff, and leave any task unchecked if its real-service, external-Run, test, or safety evidence is missing.
- [ ] 13.12 On `main`, stage only files belonging to this change, create a concise commit after all required verification succeeds, and push the configured remote without including unrelated pre-existing worktree changes.