Add Prettier and ESLint tooling (Refs #77)

This commit is contained in:
2026-10-09 15:56:13 -04:00
parent 8ed059b8d3
commit 16469e2d43
711 changed files with 99737 additions and 28286 deletions
+10 -10
View File
@@ -31,16 +31,16 @@ guessable token. An unset setup token holds setup closed.
## Roles
| Capability | Viewer | Operator | Administrator |
| --- | --- | --- | --- |
| Fleet, metrics, matches and operation summaries | Yes | Yes | Yes |
| Raw configs, file diffs, logs, RCON and telemetry diagnostics | No | Yes | Yes |
| Deploy/start/stop/restart/rebuild/remove servers | No | Yes | Yes |
| Scripts, plugins, configs, campaigns, betas and collections | Read summaries | Manage | Manage |
| Host setup, deletion, enrollment, credentials, runtime preparation and game-file upload/cache | Read status | Read status | Manage |
| Server keys and global settings/maintenance policies | No | No | Manage |
| Create users, change roles, disable accounts and reset passwords | No | No | Yes |
| Own password and sign out | Yes | Yes | Yes |
| Capability | Viewer | Operator | Administrator |
| --------------------------------------------------------------------------------------------- | -------------- | ----------- | ------------- |
| Fleet, metrics, matches and operation summaries | Yes | Yes | Yes |
| Raw configs, file diffs, logs, RCON and telemetry diagnostics | No | Yes | Yes |
| Deploy/start/stop/restart/rebuild/remove servers | No | Yes | Yes |
| Scripts, plugins, configs, campaigns, betas and collections | Read summaries | Manage | Manage |
| Host setup, deletion, enrollment, credentials, runtime preparation and game-file upload/cache | Read status | Read status | Manage |
| Server keys and global settings/maintenance policies | No | No | Manage |
| Create users, change roles, disable accounts and reset passwords | No | No | Yes |
| Own password and sign out | Yes | Yes | Yes |
Operators can launch using available game-pool keys already saved by an administrator. They
cannot save keys indirectly through a launch request. An operator's content
+4 -4
View File
@@ -12,10 +12,10 @@ Choose **Add policy**, select the game and scope, and enter an explicit maximum.
Choose **Save policy** to apply changes directly. Saving checks the current fleet, policy revision, ownership conflicts, and host readiness. If saving is blocked, the form keeps your settings and shows the reason. Saved policies show lobby counts, key availability, and the current status. An active job appears once with its latest stage and a **View job** link. Use **Lobbies** for per-map spare coverage and occupancy evidence, **Activity** for decision changes grouped by job, and **Metrics** for observed capacity and provisioning measurements.
| Autoscaling | Behavior |
| --- | --- |
| Off | No new actions. Unsubmitted work is withdrawn and delivered operations remain tracked until settled. |
| On | Adds lobbies and removes surplus lobbies after continuous empty evidence and all removal checks pass. |
| Autoscaling | Behavior |
| ----------- | ----------------------------------------------------------------------------------------------------- |
| Off | No new actions. Unsubmitted work is withdrawn and delivered operations remain tracked until settled. |
| On | Adds lobbies and removes surplus lobbies after continuous empty evidence and all removal checks pass. |
Plutonium keys belong to a game pool shared by every map, manual launch, collection, beta, and autoscaling policy for that game. An eligible creation uses the lowest available lobby number from 1–20 and reserves any free game key atomically. Key labels do not select a map or lobby. The policy shows saved and available game keys; policy maxima can exceed pool size, and a policy can be saved before any keys are added. An empty or exhausted pool holds new growth with a clear reason; it does not prevent surplus removal. Queued launches reserve their key, stopped instances retain it, and confirmed cleanup returns it to the pool. Failed or uncertain launches keep their reservation until safely reconciled. Existing lobbies and unfinished operations must be healthy and settled before activation. Automatic removal also requires agent **1.7.0 or later** advertising `instance.autoscaling-remove` on each affected host.
+71 -39
View File
@@ -56,12 +56,12 @@ There are four events. Send them whether or not a beta is active.
### Event fields
| Event | Fields |
| --- | --- |
| `game_start` | `server`, `map`, `players` with each player's `name` and `guid` |
| Event | Fields |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `game_start` | `server`, `map`, `players` with each player's `name` and `guid` |
| `round_change` | `server`, `map`, `round`, `players` with each player's `name`, `guid`, `kills`, `headshots`, `downs`, `revives`, and `score` |
| `heartbeat` | Same fields as `round_change`; sent periodically during a round to refresh the current round and player stats |
| `game_end` | `server`, `map`, `round`, `players` with each player's `name`, `guid`, `kills`, `headshots`, `downs`, `revives`, and `score` |
| `heartbeat` | Same fields as `round_change`; sent periodically during a round to refresh the current round and player stats |
| `game_end` | `server`, `map`, `round`, `players` with each player's `name`, `guid`, `kills`, `headshots`, `downs`, `revives`, and `score` |
`server` is the exact registered Electric Cherry server name. `map` is the
current map. `players` is the full player array, including an empty array when
@@ -89,13 +89,13 @@ Send when the game starts. Round and stats are not required.
```json
{
"event": "game_start",
"server": "t6_zombie_town_1",
"map": "zm_transit",
"players": [
{ "name": "Josh", "guid": "12345678901234567" },
{ "name": "Alex", "guid": "23456789012345678" }
]
"event": "game_start",
"server": "t6_zombie_town_1",
"map": "zm_transit",
"players": [
{ "name": "Josh", "guid": "12345678901234567" },
{ "name": "Alex", "guid": "23456789012345678" }
]
}
```
@@ -105,14 +105,30 @@ Send the new round and each player's current stats.
```json
{
"event": "round_change",
"server": "t6_zombie_town_1",
"map": "zm_transit",
"round": 25,
"players": [
{ "name": "Josh", "guid": "12345678901234567", "kills": 420, "headshots": 160, "downs": 1, "revives": 3, "score": 32000 },
{ "name": "Alex", "guid": "23456789012345678", "kills": 380, "headshots": 140, "downs": 3, "revives": 1, "score": 28000 }
]
"event": "round_change",
"server": "t6_zombie_town_1",
"map": "zm_transit",
"round": 25,
"players": [
{
"name": "Josh",
"guid": "12345678901234567",
"kills": 420,
"headshots": 160,
"downs": 1,
"revives": 3,
"score": 32000
},
{
"name": "Alex",
"guid": "23456789012345678",
"kills": 380,
"headshots": 140,
"downs": 3,
"revives": 1,
"score": 28000
}
]
}
```
@@ -122,14 +138,30 @@ Send the final round and each player's final stats when the game ends.
```json
{
"event": "game_end",
"server": "t6_zombie_town_1",
"map": "zm_transit",
"round": 26,
"players": [
{ "name": "Josh", "guid": "12345678901234567", "kills": 445, "headshots": 170, "downs": 2, "revives": 3, "score": 33500 },
{ "name": "Alex", "guid": "23456789012345678", "kills": 401, "headshots": 146, "downs": 4, "revives": 1, "score": 29750 }
]
"event": "game_end",
"server": "t6_zombie_town_1",
"map": "zm_transit",
"round": 26,
"players": [
{
"name": "Josh",
"guid": "12345678901234567",
"kills": 445,
"headshots": 170,
"downs": 2,
"revives": 3,
"score": 33500
},
{
"name": "Alex",
"guid": "23456789012345678",
"kills": 401,
"headshots": 146,
"downs": 4,
"revives": 1,
"score": 29750
}
]
}
```
@@ -213,18 +245,18 @@ an occupied server can still have no scoreboard report.
Requirements on a qualifying server are ANDed:
| Requirement | Evidence |
| --- | --- |
| Reach round X | A round change, heartbeat, or game end reports round >= X with the required player count |
| Requirement | Evidence |
| --------------------------- | ------------------------------------------------------------------------------------------------ |
| Reach round X | A round change, heartbeat, or game end reports round >= X with the required player count |
| Complete qualifying matches | Game end at round 2 or later, optionally qualified by a higher round, player count, and duration |
| Populated minutes | Time between consecutive game reports with enough players at both ends |
| Player-hours | Populated minutes multiplied by the lower reported player count, divided by 60 |
| Reach player count | Player array length in a game report |
| Sustained population | Consecutive report intervals above the player threshold within one game |
| Continuous healthy minutes | Consecutive fresh container/RCON observations |
| Maximum health outages | Transitions from observed healthy to unhealthy |
| Successful recovery cycles | Repeat the other requirements after each additional empty-server restart |
| Tester checklist | Tester name and observation entered on the beta detail page |
| Populated minutes | Time between consecutive game reports with enough players at both ends |
| Player-hours | Populated minutes multiplied by the lower reported player count, divided by 60 |
| Reach player count | Player array length in a game report |
| Sustained population | Consecutive report intervals above the player threshold within one game |
| Continuous healthy minutes | Consecutive fresh container/RCON observations |
| Maximum health outages | Transitions from observed healthy to unhealthy |
| Successful recovery cycles | Repeat the other requirements after each additional empty-server restart |
| Tester checklist | Tester name and observation entered on the beta detail page |
All gameplay requirements use the script reports. Match counts do not read game
logs. The reported round and required player count must occur together in the
+5 -5
View File
@@ -26,11 +26,11 @@ openssl rand -hex 32
Set these values in `.env`:
| Variable | Purpose |
| --- | --- |
| `EC_PUBLIC_URL` | The external HTTPS address of the dashboard. |
| `EC_SETUP_TOKEN` | The generated secret, used to create the first administrator. |
| `EC_DATA_DIR` | A persistent directory for the database, game files, and beta archives. |
| Variable | Purpose |
| -------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `EC_PUBLIC_URL` | The external HTTPS address of the dashboard. |
| `EC_SETUP_TOKEN` | The generated secret, used to create the first administrator. |
| `EC_DATA_DIR` | A persistent directory for the database, game files, and beta archives. |
| `EC_TELEMETRY_TOKEN` | A separate secret of at least 32 characters for game reporters. Generate it independently with the same command. |
For an existing installation, retain its original data directory. Compose
+59 -59
View File
@@ -87,15 +87,15 @@ of inferring one. GUIDs stay strings.
## Recorded statistics
| Statistic | Meaning |
| --- | --- |
| Highest round | Highest round reported with that player present, including players who joined mid-game. |
| Total kills, headshots, revives, downs | Sum of each player's highest reported counter in each game. Round snapshots are cumulative, so they are never added together within a game. |
| Total rounds | Round progression during observed participation, added across games. A player observed at game start and then round 8 receives seven rounds. A player first seen at round 8 gets a highest-round record of 8, but zero total rounds; reaching round 9 then adds one. |
| Games played | Completed games in which a stats report at round 2 or later contains the player, excluding players who left in the same round they joined. Staying through game end counts even without a round change. Legacy participation with an unknown joining round still counts. Start-only and round 1 participation do not count. |
| Games completed | Games whose `game_end` roster contains the player. Disconnected players retain earlier stats without receiving completion credit. |
| Best game kills | Highest kill count recorded in any one game. |
| Highest reported score | Highest observed score balance. Spending points can lower the score, so this is not cumulative points earned. |
| Statistic | Meaning |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Highest round | Highest round reported with that player present, including players who joined mid-game. |
| Total kills, headshots, revives, downs | Sum of each player's highest reported counter in each game. Round snapshots are cumulative, so they are never added together within a game. |
| Total rounds | Round progression during observed participation, added across games. A player observed at game start and then round 8 receives seven rounds. A player first seen at round 8 gets a highest-round record of 8, but zero total rounds; reaching round 9 then adds one. |
| Games played | Completed games in which a stats report at round 2 or later contains the player, excluding players who left in the same round they joined. Staying through game end counts even without a round change. Legacy participation with an unknown joining round still counts. Start-only and round 1 participation do not count. |
| Games completed | Games whose `game_end` roster contains the player. Disconnected players retain earlier stats without receiving completion credit. |
| Best game kills | Highest kill count recorded in any one game. |
| Highest reported score | Highest observed score balance. Spending points can lower the score, so this is not cumulative points earned. |
Same-round departures retain their recorded stats, personal bests, and match
history; only the games-played count excludes them. This also changes the game
@@ -211,15 +211,15 @@ example above works for command-line or server-side clients. Successful response
All parameters are optional. Names and enumerated values are case-sensitive.
Use URL encoding for map keys and search text.
| Parameter | Default | Accepted values and behavior |
| --- | --- | --- |
| `game` | Both games | Exactly `t5` or `t6`. An empty value is invalid. |
| `map` | All maps | Opaque `maps[].key`, at most 1024 characters. Empty means no map filter. An unknown key or a game/map mismatch returns an empty selection, not an error. |
| `players` | All squad sizes | Exactly `1`, `2`, `3`, or `4`, matching the recorded starting player count. Unknown counts contribute only when this filter is absent. |
| `metric` | `highestRound` | One of the metric keys below. An empty or unknown value is invalid. |
| `q` | No search | At most 100 characters before trimming. Matches a literal substring of the current name or GUID, ignoring ASCII letter case. Surrounding whitespace is trimmed; whitespace-only input means no search. `%` and `_` are literal characters, not wildcards. |
| `limit` | `50` | Integer from 1 to 100. |
| `offset` | `0` | Integer from 0 to 1,000,000; counts matching entries to skip, not ranks or pages. |
| Parameter | Default | Accepted values and behavior |
| --------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `game` | Both games | Exactly `t5` or `t6`. An empty value is invalid. |
| `map` | All maps | Opaque `maps[].key`, at most 1024 characters. Empty means no map filter. An unknown key or a game/map mismatch returns an empty selection, not an error. |
| `players` | All squad sizes | Exactly `1`, `2`, `3`, or `4`, matching the recorded starting player count. Unknown counts contribute only when this filter is absent. |
| `metric` | `highestRound` | One of the metric keys below. An empty or unknown value is invalid. |
| `q` | No search | At most 100 characters before trimming. Matches a literal substring of the current name or GUID, ignoring ASCII letter case. Surrounding whitespace is trimmed; whitespace-only input means no search. `%` and `_` are literal characters, not wildcards. |
| `limit` | `50` | Integer from 1 to 100. |
| `offset` | `0` | Integer from 0 to 1,000,000; counts matching entries to skip, not ranks or pages. |
`limit` and `offset` accept decimal digits only. Empty strings, signs, spaces,
fractions and exponent notation are rejected rather than clamped. String
@@ -235,40 +235,40 @@ Metric keys are `highestRound`, `kills`, `roundsSurvived`, `headshots`, `revives
HTTP `200` returns the following top-level fields directly, with no `ok` or
`data` wrapper:
| Field | Type | Meaning |
| --- | --- | --- |
| `entries` | Entry array | Requested page, ordered by the selected metric descending. |
| `maps` | Map array | Available completed-match map options, filtered only by `game`, independent of `map`, `q`, metric qualification and pagination. |
| `total` | number | Number of matching GUIDs after metric qualification and search, before pagination. |
| `limit`, `offset` | number | Accepted pagination values. |
| `metric` | string | Selected metric key, including the default when omitted. |
| `summary` | object | Totals for all qualifying completed participation in the game/map scope, independent of `q`, metric qualification and pagination. |
| Field | Type | Meaning |
| ----------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `entries` | Entry array | Requested page, ordered by the selected metric descending. |
| `maps` | Map array | Available completed-match map options, filtered only by `game`, independent of `map`, `q`, metric qualification and pagination. |
| `total` | number | Number of matching GUIDs after metric qualification and search, before pagination. |
| `limit`, `offset` | number | Accepted pagination values. |
| `metric` | string | Selected metric key, including the default when omitted. |
| `summary` | object | Totals for all qualifying completed participation in the game/map scope, independent of `q`, metric qualification and pagination. |
Each entry combines one GUID's qualifying participation across the selected
games/maps. It contains all of these fields regardless of the selected metric:
| Entry field | Type | Meaning |
| --- | --- | --- |
| `guid` | string | Player identity. Preserve it as a string, including leading zeros. |
| `name` | string | Latest reported name across both games, even if that report is outside the selected scope or from an unfinished match. |
| `rank` | number | Rank within the scope after metric qualification, before search/pagination. Ties share rank and leave gaps: 1, 1, 3. |
| `highestRound`, `kills`, `roundsSurvived`, `headshots`, `revives`, `downs`, `gamesPlayed`, `gamesCompleted`, `bestKills`, `bestScore` | number | The ten counters defined under [Recorded statistics](#recorded-statistics). |
| `headshotRate`, `killsPerDown`, `averageKills`, `averageRounds`, `completionRate` | number or null | Ratios defined below; `null` if the denominator is zero. |
| `lastSeen` | string | Latest player observation among the qualifying participation in this scope, not the latest global identity update. |
| `records` | object | Personal-best evidence keyed by `highestRound`, `bestKills` and `bestScore`. |
| Entry field | Type | Meaning |
| ------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `guid` | string | Player identity. Preserve it as a string, including leading zeros. |
| `name` | string | Latest reported name across both games, even if that report is outside the selected scope or from an unfinished match. |
| `rank` | number | Rank within the scope after metric qualification, before search/pagination. Ties share rank and leave gaps: 1, 1, 3. |
| `highestRound`, `kills`, `roundsSurvived`, `headshots`, `revives`, `downs`, `gamesPlayed`, `gamesCompleted`, `bestKills`, `bestScore` | number | The ten counters defined under [Recorded statistics](#recorded-statistics). |
| `headshotRate`, `killsPerDown`, `averageKills`, `averageRounds`, `completionRate` | number or null | Ratios defined below; `null` if the denominator is zero. |
| `lastSeen` | string | Latest player observation among the qualifying participation in this scope, not the latest global identity update. |
| `records` | object | Personal-best evidence keyed by `highestRound`, `bestKills` and `bestScore`. |
Entries have no `game` field. Equal metric values are displayed in name order
(ASCII case-insensitive, then exact name), then GUID order. `q` is a substring
search, not an exact-GUID lookup; a tool looking up one GUID must check equality
on returned `guid` values and account for pagination.
| Ratio | Calculation | Requirement to rank by this metric |
| --- | --- | --- |
| `headshotRate` | `headshots / kills` | `gamesPlayed >= 5` and `kills >= 100` |
| `killsPerDown` | `kills / downs` | `gamesPlayed >= 5` and `downs >= 5` |
| `averageKills` | `kills / gamesPlayed` | `gamesPlayed >= 5` |
| `averageRounds` | `roundsSurvived / gamesPlayed` | `gamesPlayed >= 5` |
| `completionRate` | `gamesCompleted / gamesPlayed` | `gamesPlayed >= 5` |
| Ratio | Calculation | Requirement to rank by this metric |
| ---------------- | ------------------------------ | ------------------------------------- |
| `headshotRate` | `headshots / kills` | `gamesPlayed >= 5` and `kills >= 100` |
| `killsPerDown` | `kills / downs` | `gamesPlayed >= 5` and `downs >= 5` |
| `averageKills` | `kills / gamesPlayed` | `gamesPlayed >= 5` |
| `averageRounds` | `roundsSurvived / gamesPlayed` | `gamesPlayed >= 5` |
| `completionRate` | `gamesCompleted / gamesPlayed` | `gamesPlayed >= 5` |
These are unrounded ratios, not formatted strings. For `headshotRate` and
`completionRate`, `0.5` means 50%. Requirements use the selected game/map scope
@@ -283,14 +283,14 @@ engine map identifier; `name` is the display name. Pass `key` as the request's
completed matches reaching round 2, so an option can exist without any qualifying
players. Removed servers' maps remain available.
| Summary field | Type | Meaning |
| --- | --- | --- |
| `players` | number | Unique qualifying GUIDs, combined across games. |
| `matches` | number | Distinct completed matches with qualifying player participation; not the sum of `gamesPlayed`. |
| `kills`, `roundsSurvived` | number | Sums across qualifying players; rounds are player-rounds. |
| `highestRound` | number | Highest qualifying player's recorded round. |
| `firstTrackedAt` | string or null | Earliest match `startedAt` among those matches. |
| `updatedAt` | string or null | Latest match report receipt time among those matches; not a response-generation time or a complete data-change token. |
| Summary field | Type | Meaning |
| ------------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------- |
| `players` | number | Unique qualifying GUIDs, combined across games. |
| `matches` | number | Distinct completed matches with qualifying player participation; not the sum of `gamesPlayed`. |
| `kills`, `roundsSurvived` | number | Sums across qualifying players; rounds are player-rounds. |
| `highestRound` | number | Highest qualifying player's recorded round. |
| `firstTrackedAt` | string or null | Earliest match `startedAt` among those matches. |
| `updatedAt` | string or null | Latest match report receipt time among those matches; not a response-generation time or a complete data-change token. |
For an empty scope, numeric summary fields are zero and both timestamps are
`null`. A search with no results or an offset beyond `total` returns
@@ -301,15 +301,15 @@ Each `records` value has the following fields. Evidence uses the same game/map
scope as the entry, and ties choose the earliest completion, then lowest match
ID. The three records can refer to different matches.
| Evidence field | Type | Meaning |
| --- | --- | --- |
| `matchId`, `value` | number | Completed match ID and that personal-best value. Link to `/matches/{matchId}` for its results page. |
| `game`, `mapKey`, `mapName`, `server` | string | Recorded game, opaque map key, map display name and server name. |
| `startedAt` | string | First recorded match observation; only the game start when `startObserved` is true. |
| `endedAt` | string or null | Recorded completion time; can be unknown in older stored records. |
| `startObserved` | boolean | Whether a `game_start` was received for the match. |
| `presentAtStart` | boolean or null | Whether the player was first observed at the recorded start; `null` for unknown older participation. |
| `firstObservedRound` | number or null | Round of the player's first observation, or unknown. This does not prove continuous survival. |
| Evidence field | Type | Meaning |
| ------------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------- |
| `matchId`, `value` | number | Completed match ID and that personal-best value. Link to `/matches/{matchId}` for its results page. |
| `game`, `mapKey`, `mapName`, `server` | string | Recorded game, opaque map key, map display name and server name. |
| `startedAt` | string | First recorded match observation; only the game start when `startObserved` is true. |
| `endedAt` | string or null | Recorded completion time; can be unknown in older stored records. |
| `startObserved` | boolean | Whether a `game_start` was received for the match. |
| `presentAtStart` | boolean or null | Whether the player was first observed at the recorded start; `null` for unknown older participation. |
| `firstObservedRound` | number or null | Round of the player's first observation, or unknown. This does not prove continuous survival. |
Timestamps reflect controller receipt/observation times, normally ISO 8601 UTC
strings such as `2026-10-05T12:00:00.000Z`, not reporter gameplay-clock times.
+6 -6
View File
@@ -63,13 +63,13 @@ represents the current registration rather than every instance in the history.
Hosting Rules v1 deliberately offer experiments even with small samples:
| Recorded condition | Suggested experiment |
| --- | --- |
| At least 20% of known capacity time had every lobby full | Trial one additional lobby during busy hours. |
| Capacity unavailable and players present for at least 80% of known server time | Tentatively trial an extra lobby using occupancy as a proxy. |
| Recorded condition | Suggested experiment |
| ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| At least 20% of known capacity time had every lobby full | Trial one additional lobby during busy hours. |
| Capacity unavailable and players present for at least 80% of known server time | Tentatively trial an extra lobby using occupancy as a proxy. |
| Players present for at most 10% of known time, with under 1% measured pressure or unavailable capacity | Review one idle lobby or a shorter hosting window while preserving access to the map. |
| Occupancy unavailable | Check telemetry/RCON reporting and watch for known player counts. |
| Other observations | Check missing capacity or keep the lineup and watch peaks. |
| Occupancy unavailable | Check telemetry/RCON reporting and watch for known player counts. |
| Other observations | Check missing capacity or keep the lineup and watch peaks. |
Each suggestion includes evidence and an outcome to watch. Unknown capacity,
less than one hour of relevant known evidence, or substantial unknown captured
+1 -1
View File
@@ -52,7 +52,7 @@ GitHub release is imported from its detail page.
- `GET /api/plugins/github/release?url=...` previews a release and its DLL assets.
- `POST /api/plugins/github/import` accepts JSON `{ url, assetId, name,
scopeType?, scopeValue? }` for a new plugin, or `{ url, assetId, pluginId }`
scopeType?, scopeValue? }` for a new plugin, or `{ url, assetId, pluginId }`
for an existing plugin. Use the preview's exact release URL, not a mutable
`latest` URL. Returns plugin/version IDs, checksum and the beta builder URL.
- `GET /api/plugins/updates` checks all plugins; `?pluginId=123` checks one.
+7 -7
View File
@@ -34,14 +34,14 @@ of its explicit removal list, which resets whenever the preview is refreshed.
See [Collections](collections.md) for the review details and safe submission
retries when a response is lost.
| Action | Behavior |
| --- | --- |
| Create | Create a new instance using the latest promoted files and verify container health, game status, the selected map, and the Plutonium revision. |
| Start | Start the existing container and verify container health and RCON. |
| Restart | Wait until empty, restart the existing container, and verify container health and RCON. |
| Action | Behavior |
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Create | Create a new instance using the latest promoted files and verify container health, game status, the selected map, and the Plutonium revision. |
| Start | Start the existing container and verify container health and RCON. |
| Restart | Wait until empty, restart the existing container, and verify container health and RCON. |
| Rebuild | Wait until empty, replace the instance through the host agent, preserving its server identity and port while advancing its generation. Verify container health, game status, map, and Plutonium revision. |
| Stop | Wait until empty, stop the container, and verify that the host agent reports it stopped. Keep the instance for a later Start. |
| Remove | Wait until empty, remove the container and its files through the host agent, then retire the instance and registration. |
| Stop | Wait until empty, stop the container, and verify that the host agent reports it stopped. Keep the instance for a later Start. |
| Remove | Wait until empty, remove the container and its files through the host agent, then retire the instance and registration. |
## Safety and verification
+22 -22
View File
@@ -44,28 +44,28 @@ expire unused artifact versions when their age policy is disabled. Game-file gra
is a delay: 0 adds no delay. A positive age and version count together preserve the
minimum count as well as versions younger than the age threshold.
| History or storage | Default |
| --- | --- |
| Campaigns | 7 days |
| Successful routine operations | 1 day |
| Provisioning workflows | Indefinite |
| Agent actions | Indefinite |
| Explicitly resolved failures | Indefinite |
| Non-update maintenance jobs | 30 days |
| Resolved recovery incidents | Indefinite |
| Host resource history | 7 days |
| Instance resource samples | 1 day |
| Fleet occupancy metrics | 31 days |
| Telemetry diagnostics | 7 days; 200 per server; 10,000 overall |
| Completed/interrupted matches | Indefinite |
| Closed betas and test evidence | Indefinite |
| Campaign file bodies and closed beta snapshots | 30 days |
| Completed launch and command file bodies | 30 days |
| Unused artifact versions | No automatic expiry; no minimum count |
| Unused game files | No grace period; keep latest 1 version per game |
| Incomplete browser uploads | Indefinite |
| Authentication audit events | Indefinite |
| Minimum history count | 0 additional records |
| History or storage | Default |
| ---------------------------------------------- | ----------------------------------------------- |
| Campaigns | 7 days |
| Successful routine operations | 1 day |
| Provisioning workflows | Indefinite |
| Agent actions | Indefinite |
| Explicitly resolved failures | Indefinite |
| Non-update maintenance jobs | 30 days |
| Resolved recovery incidents | Indefinite |
| Host resource history | 7 days |
| Instance resource samples | 1 day |
| Fleet occupancy metrics | 31 days |
| Telemetry diagnostics | 7 days; 200 per server; 10,000 overall |
| Completed/interrupted matches | Indefinite |
| Closed betas and test evidence | Indefinite |
| Campaign file bodies and closed beta snapshots | 30 days |
| Completed launch and command file bodies | 30 days |
| Unused artifact versions | No automatic expiry; no minimum count |
| Unused game files | No grace period; keep latest 1 version per game |
| Incomplete browser uploads | Indefinite |
| Authentication audit events | Indefinite |
| Minimum history count | 0 additional records |
Telemetry age and count policies are independent; 0 disables each individual cap.
Diagnostic responses remain bounded to 10,000 rows when the per-server retention