docs(openspec): propose real SCUM data management
This commit is contained in:
+117
@@ -0,0 +1,117 @@
|
||||
## 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
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
## 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
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
## 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
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
## 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
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
## 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
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
## 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
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
## 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
|
||||
Reference in New Issue
Block a user