refactor(scum): remove unverified manifest templates
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
- [ ] 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.
|
||||
- [ ] 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.
|
||||
- [ ] 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.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.
|
||||
- [ ] 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
|
||||
|
||||
@@ -284,172 +284,8 @@
|
||||
"maxRecords": 1000
|
||||
}
|
||||
],
|
||||
"queryTemplates": [
|
||||
{
|
||||
"key": "scum.player.profile",
|
||||
"title": "Read SCUM player profile, economy, squad, and position facts",
|
||||
"permission": "server.game-client.read",
|
||||
"engine": "sqlite",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/bridge/queries/scum-player-profile.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/queries/scum-player-profile.result.schema.json",
|
||||
"maxRows": 500,
|
||||
"timeoutSeconds": 15
|
||||
},
|
||||
{
|
||||
"key": "scum.squads",
|
||||
"title": "Read SCUM squad records",
|
||||
"permission": "server.game-client.read",
|
||||
"engine": "sqlite",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/bridge/queries/scum-squads.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/queries/scum-squads.result.schema.json",
|
||||
"maxRows": 500,
|
||||
"timeoutSeconds": 15
|
||||
},
|
||||
{
|
||||
"key": "scum.squad-members",
|
||||
"title": "Read SCUM squad membership records",
|
||||
"permission": "server.game-client.read",
|
||||
"engine": "sqlite",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/bridge/queries/scum-squad-members.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/queries/scum-squad-members.result.schema.json",
|
||||
"maxRows": 500,
|
||||
"timeoutSeconds": 15
|
||||
},
|
||||
{
|
||||
"key": "scum.vehicles",
|
||||
"title": "Read SCUM vehicle records and coordinates",
|
||||
"permission": "server.game-client.read",
|
||||
"engine": "sqlite",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/bridge/queries/scum-vehicles.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/queries/scum-vehicles.result.schema.json",
|
||||
"maxRows": 500,
|
||||
"timeoutSeconds": 15
|
||||
},
|
||||
{
|
||||
"key": "scum.flags",
|
||||
"title": "Read SCUM flag and ownership records",
|
||||
"permission": "server.game-client.read",
|
||||
"engine": "sqlite",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/bridge/queries/scum-flags.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/queries/scum-flags.result.schema.json",
|
||||
"maxRows": 500,
|
||||
"timeoutSeconds": 15
|
||||
},
|
||||
{
|
||||
"key": "scum.positions",
|
||||
"title": "Read SCUM current player, vehicle, and flag coordinates",
|
||||
"permission": "server.game-client.read",
|
||||
"engine": "sqlite",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/bridge/queries/scum-positions.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/queries/scum-positions.result.schema.json",
|
||||
"maxRows": 500,
|
||||
"timeoutSeconds": 15
|
||||
}
|
||||
],
|
||||
"operationTemplates": [
|
||||
{
|
||||
"key": "player.fame.set",
|
||||
"title": "Set SCUM player fame through RCON",
|
||||
"permission": "server.game-client.command",
|
||||
"approvalLevel": "operator",
|
||||
"kind": "rcon",
|
||||
"transportKey": "scum-management",
|
||||
"targetKey": "scum-management",
|
||||
"payloadSchemaRef": "schemas/bridge/player-fame-set.payload.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/player-rcon-set.result.schema.json",
|
||||
"confirmationSchemaRef": "schemas/bridge/player-fame-set.confirmation.schema.json",
|
||||
"timeoutSeconds": 60,
|
||||
"maxPayloadBytes": 2048,
|
||||
"safety": {
|
||||
"requiresApproval": true,
|
||||
"requiresConfirmation": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "player.currency.normal.set",
|
||||
"title": "Set SCUM normal currency through RCON",
|
||||
"permission": "server.game-client.command",
|
||||
"approvalLevel": "operator",
|
||||
"kind": "rcon",
|
||||
"transportKey": "scum-management",
|
||||
"targetKey": "scum-management",
|
||||
"payloadSchemaRef": "schemas/bridge/player-currency-set.payload.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/player-rcon-set.result.schema.json",
|
||||
"confirmationSchemaRef": "schemas/bridge/player-currency-set.confirmation.schema.json",
|
||||
"timeoutSeconds": 60,
|
||||
"maxPayloadBytes": 2048,
|
||||
"safety": {
|
||||
"requiresApproval": true,
|
||||
"requiresConfirmation": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "player.currency.gold.set",
|
||||
"title": "Set SCUM gold currency through RCON",
|
||||
"permission": "server.game-client.command",
|
||||
"approvalLevel": "operator",
|
||||
"kind": "rcon",
|
||||
"transportKey": "scum-management",
|
||||
"targetKey": "scum-management",
|
||||
"payloadSchemaRef": "schemas/bridge/player-currency-set.payload.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/player-rcon-set.result.schema.json",
|
||||
"confirmationSchemaRef": "schemas/bridge/player-currency-set.confirmation.schema.json",
|
||||
"timeoutSeconds": 60,
|
||||
"maxPayloadBytes": 2048,
|
||||
"safety": {
|
||||
"requiresApproval": true,
|
||||
"requiresConfirmation": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "player.notify",
|
||||
"title": "Notify SCUM player through RCON chat",
|
||||
"permission": "server.game-client.command",
|
||||
"approvalLevel": "operator",
|
||||
"kind": "rcon",
|
||||
"transportKey": "scum-management",
|
||||
"targetKey": "scum-management",
|
||||
"payloadSchemaRef": "schemas/bridge/player-notify.payload.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/player-notify.result.schema.json",
|
||||
"confirmationSchemaRef": "schemas/bridge/player-notify.confirmation.schema.json",
|
||||
"timeoutSeconds": 60,
|
||||
"maxPayloadBytes": 2048,
|
||||
"safety": {
|
||||
"requiresApproval": true,
|
||||
"requiresConfirmation": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "reward.deliver",
|
||||
"title": "Deliver approved SCUM reward through typed command",
|
||||
"permission": "server.game-client.command",
|
||||
"approvalLevel": "operator",
|
||||
"kind": "rcon",
|
||||
"transportKey": "scum-management",
|
||||
"targetKey": "scum-management",
|
||||
"payloadSchemaRef": "schemas/bridge/reward-deliver.payload.schema.json",
|
||||
"resultSchemaRef": "schemas/bridge/reward-deliver.result.schema.json",
|
||||
"confirmationSchemaRef": "schemas/bridge/reward-deliver.confirmation.schema.json",
|
||||
"timeoutSeconds": 60,
|
||||
"maxPayloadBytes": 4096,
|
||||
"safety": {
|
||||
"requiresApproval": true,
|
||||
"requiresConfirmation": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"queryTemplates": [],
|
||||
"operationTemplates": [],
|
||||
"commandRetentionSeconds": 604800,
|
||||
"maxCommands": 1000,
|
||||
"features": [
|
||||
@@ -486,19 +322,7 @@
|
||||
"players",
|
||||
"online.sessions"
|
||||
],
|
||||
"queryTemplateKeys": [
|
||||
"scum.player.profile",
|
||||
"scum.positions"
|
||||
],
|
||||
"operationKeys": [
|
||||
"player.fame.set",
|
||||
"player.currency.normal.set",
|
||||
"player.currency.gold.set",
|
||||
"player.notify"
|
||||
],
|
||||
"featureKeys": [
|
||||
"state.patch"
|
||||
]
|
||||
"featureKeys": []
|
||||
},
|
||||
{
|
||||
"pageKey": "squads",
|
||||
@@ -506,11 +330,6 @@
|
||||
"squads",
|
||||
"flags"
|
||||
],
|
||||
"queryTemplateKeys": [
|
||||
"scum.squads",
|
||||
"scum.squad-members",
|
||||
"scum.flags"
|
||||
],
|
||||
"featureKeys": []
|
||||
},
|
||||
{
|
||||
@@ -520,12 +339,6 @@
|
||||
"vehicles",
|
||||
"flags"
|
||||
],
|
||||
"queryTemplateKeys": [
|
||||
"scum.player.profile",
|
||||
"scum.vehicles",
|
||||
"scum.flags",
|
||||
"scum.positions"
|
||||
],
|
||||
"featureKeys": []
|
||||
},
|
||||
{
|
||||
@@ -533,13 +346,7 @@
|
||||
"snapshotTypes": [
|
||||
"players"
|
||||
],
|
||||
"operationKeys": [
|
||||
"reward.deliver",
|
||||
"player.notify"
|
||||
],
|
||||
"featureKeys": [
|
||||
"reward.delivery"
|
||||
]
|
||||
"featureKeys": []
|
||||
}
|
||||
],
|
||||
"companion": {
|
||||
@@ -675,8 +482,7 @@
|
||||
"server.game-client.maintenance"
|
||||
],
|
||||
"bridgeActions": [
|
||||
"server.instances.read",
|
||||
"remote.access.request"
|
||||
"server.instances.read"
|
||||
],
|
||||
"featureKeys": []
|
||||
},
|
||||
@@ -692,8 +498,7 @@
|
||||
"server.game-client.read"
|
||||
],
|
||||
"bridgeActions": [
|
||||
"server.instances.read",
|
||||
"remote.access.request"
|
||||
"server.instances.read"
|
||||
],
|
||||
"featureKeys": []
|
||||
},
|
||||
@@ -709,8 +514,7 @@
|
||||
"server.game-client.read"
|
||||
],
|
||||
"bridgeActions": [
|
||||
"server.instances.read",
|
||||
"remote.access.request"
|
||||
"server.instances.read"
|
||||
],
|
||||
"featureKeys": []
|
||||
},
|
||||
@@ -729,9 +533,7 @@
|
||||
"bridgeActions": [
|
||||
"server.instances.read"
|
||||
],
|
||||
"featureKeys": [
|
||||
"reward.delivery"
|
||||
]
|
||||
"featureKeys": []
|
||||
}
|
||||
],
|
||||
"ai": {
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["playerId", "fieldKey", "value", "observedAt", "checksum"],
|
||||
"properties": {
|
||||
"playerId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"fieldKey": { "const": "855" },
|
||||
"value": { "type": "integer", "minimum": 0, "maximum": 100000 },
|
||||
"observedAt": { "type": "string", "format": "date-time" },
|
||||
"checksum": { "type": "string", "minLength": 1, "maxLength": 160 }
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["playerId", "fieldKey", "before", "after", "safetyWindow", "backupRef"],
|
||||
"properties": {
|
||||
"playerId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"fieldKey": { "const": "855" },
|
||||
"before": { "type": "integer", "minimum": 0, "maximum": 100000 },
|
||||
"after": { "type": "integer", "minimum": 0, "maximum": 100000 },
|
||||
"safetyWindow": { "type": "string", "minLength": 1, "maxLength": 120 },
|
||||
"backupRef": { "type": "string", "minLength": 1, "maxLength": 180 },
|
||||
"reason": { "type": "string", "maxLength": 240 }
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["outcome", "affectedRows", "mutationChecksum"],
|
||||
"properties": {
|
||||
"outcome": { "enum": ["succeeded", "failed", "unknown", "stale-before"] },
|
||||
"affectedRows": { "type": "integer", "minimum": 0, "maximum": 1 },
|
||||
"mutationChecksum": { "type": "string", "minLength": 1, "maxLength": 160 },
|
||||
"safeMessage": { "type": "string", "maxLength": 240 }
|
||||
}
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerCurrencySetConfirmation",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["playerId", "amount", "observedAt"],
|
||||
"properties": {
|
||||
"playerId": { "type": "string", "minLength": 17, "maxLength": 17, "pattern": "^[0-9]{17}$" },
|
||||
"amount": { "type": "integer", "minimum": 0, "maximum": 2147483647 },
|
||||
"currency": { "enum": ["normal", "gold"] },
|
||||
"observationId": { "type": "string", "minLength": 1, "maxLength": 160 },
|
||||
"observedAt": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerCurrencySetPayload",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["playerId", "amount"],
|
||||
"properties": {
|
||||
"playerId": { "type": "string", "minLength": 17, "maxLength": 17, "pattern": "^[0-9]{17}$" },
|
||||
"amount": { "type": "integer", "minimum": 0, "maximum": 2147483647 },
|
||||
"reason": { "type": "string", "minLength": 1, "maxLength": 240 }
|
||||
}
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerFameSetConfirmation",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["playerId", "fame", "observedAt"],
|
||||
"properties": {
|
||||
"playerId": { "type": "string", "minLength": 17, "maxLength": 17, "pattern": "^[0-9]{17}$" },
|
||||
"fame": { "type": "integer", "minimum": -2147483648, "maximum": 2147483647 },
|
||||
"observationId": { "type": "string", "minLength": 1, "maxLength": 160 },
|
||||
"observedAt": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerFameSetPayload",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["playerId", "fame"],
|
||||
"properties": {
|
||||
"playerId": { "type": "string", "minLength": 17, "maxLength": 17, "pattern": "^[0-9]{17}$" },
|
||||
"fame": { "type": "integer", "minimum": -2147483648, "maximum": 2147483647 },
|
||||
"reason": { "type": "string", "minLength": 1, "maxLength": 240 }
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerNotifyConfirmation",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["playerId", "outcome", "observedAt"],
|
||||
"properties": {
|
||||
"playerId": { "type": "string", "minLength": 17, "maxLength": 17, "pattern": "^[0-9]{17}$" },
|
||||
"outcome": { "enum": ["sent", "failed", "unknown"] },
|
||||
"observedAt": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerRCONSetResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["outcome"],
|
||||
"properties": {
|
||||
"outcome": { "enum": ["queued", "succeeded", "failed", "unknown"] },
|
||||
"runJobId": { "type": "string", "minLength": 1, "maxLength": 160 },
|
||||
"summary": { "type": "string", "maxLength": 240 }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
# SCUM.db Query Contract
|
||||
|
||||
These query template keys are browser-safe declarations. They intentionally do not carry SQL text, host paths, DSNs, sockets, or credentials. The bound run/agent beside the current SCUM service owns the actual SQLite read implementation and must return rows matching the referenced result schemas.
|
||||
|
||||
| Template key | SCUM.db source tables | Projection target |
|
||||
| --- | --- | --- |
|
||||
| `scum.player.profile` | `user_profile`, `prisoner`, `prisoner_entity`, `entity`, `bank_account_registry`, `bank_account_registry_currencies`, optional `squad_member` / `squad` joins | Player identity, economy, squad summary, and current position |
|
||||
| `scum.squads` | `squad`, optional `squad_member`, optional `user_profile` leader joins | Squad records and leader/member counts |
|
||||
| `scum.squad-members` | `squad_member`, `user_profile`, optional `squad` joins | Squad roster and member identity mapping |
|
||||
| `scum.vehicles` | `vehicle_spawner`, `entity`, optional owner/squad joins when present | Vehicle inventory and coordinates; unknown class labels remain unknown |
|
||||
| `scum.flags` | `base_element`, `entity`, `user_profile`, `squad_member`, `squad` where available | Flag ownership, ownership confidence, and coordinates |
|
||||
| `scum.positions` | `prisoner_entity`, `vehicle_spawner`, `base_element`, `entity` | Current player, vehicle, and flag coordinates |
|
||||
|
||||
`last_save_time` is freshness evidence only. It must not be treated as proof that a player is online; online state comes from login/logoff evidence or an explicit typed online field.
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMFlagsParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"flagId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"ownerProfileId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"squadId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"limit": { "type": "integer", "minimum": 1, "maximum": 500 }
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMFlagsResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 500,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["flagId"],
|
||||
"properties": {
|
||||
"flagId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"entityId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"ownerProfileId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"ownerPlayerId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"ownerSquadId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"ownerSquadName": { "type": "string", "minLength": 1, "maxLength": 80 },
|
||||
"ownershipConfidence": { "enum": ["direct", "member", "squad", "unknown"] },
|
||||
"x": { "type": "number" },
|
||||
"y": { "type": "number" },
|
||||
"z": { "type": "number" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"truncated": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerProfileParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"gamePlayerId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" },
|
||||
"userProfileId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" },
|
||||
"steamId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" },
|
||||
"search": { "type": "string", "minLength": 1, "maxLength": 80 },
|
||||
"limit": { "type": "integer", "minimum": 1, "maximum": 500 }
|
||||
}
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerProfileResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 500,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["userProfileId"],
|
||||
"properties": {
|
||||
"gamePlayerId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"userProfileId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"steamId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"displayName": { "type": "string", "minLength": 1, "maxLength": 80 },
|
||||
"squadId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"squadName": { "type": "string", "minLength": 1, "maxLength": 80 },
|
||||
"famePoints": { "type": "number" },
|
||||
"normalBalance": { "type": "number" },
|
||||
"goldBalance": { "type": "number" },
|
||||
"x": { "type": "number" },
|
||||
"y": { "type": "number" },
|
||||
"z": { "type": "number" },
|
||||
"lastSaveTime": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"truncated": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPositionsParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"subjectType": { "enum": ["player", "vehicle", "flag"] },
|
||||
"subjectId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"limit": { "type": "integer", "minimum": 1, "maximum": 500 }
|
||||
}
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPositionsResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 500,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["subjectType", "subjectId", "x", "y"],
|
||||
"properties": {
|
||||
"subjectType": { "enum": ["player", "vehicle", "flag"] },
|
||||
"subjectId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"gamePlayerId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"vehicleId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"entityId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"x": { "type": "number" },
|
||||
"y": { "type": "number" },
|
||||
"z": { "type": "number" },
|
||||
"lastSaveTime": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"truncated": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMSquadMembersParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"squadId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"userProfileId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"limit": { "type": "integer", "minimum": 1, "maximum": 500 }
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMSquadMembersResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 500,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["squadId", "userProfileId"],
|
||||
"properties": {
|
||||
"squadId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"userProfileId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"gamePlayerId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"steamId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"displayName": { "type": "string", "minLength": 1, "maxLength": 80 },
|
||||
"rank": { "type": "string", "minLength": 1, "maxLength": 32 },
|
||||
"isLeader": { "type": "boolean" },
|
||||
"joinedAt": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"truncated": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMSquadsParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"squadId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"search": { "type": "string", "minLength": 1, "maxLength": 80 },
|
||||
"limit": { "type": "integer", "minimum": 1, "maximum": 500 }
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMSquadsResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 500,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["squadId"],
|
||||
"properties": {
|
||||
"squadId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"name": { "type": "string", "minLength": 1, "maxLength": 80 },
|
||||
"leaderProfileId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"leaderPlayerId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"memberCount": { "type": "integer", "minimum": 0, "maximum": 1000 },
|
||||
"score": { "type": "number" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"truncated": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMVehiclesParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"vehicleId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"ownerProfileId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"squadId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"limit": { "type": "integer", "minimum": 1, "maximum": 500 }
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMVehiclesResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 500,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["vehicleId"],
|
||||
"properties": {
|
||||
"vehicleId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"entityId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"className": { "type": "string", "minLength": 1, "maxLength": 120 },
|
||||
"label": { "type": "string", "minLength": 1, "maxLength": 120 },
|
||||
"ownerProfileId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"ownerPlayerId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"squadId": { "type": "string", "minLength": 1, "maxLength": 96 },
|
||||
"x": { "type": "number" },
|
||||
"y": { "type": "number" },
|
||||
"z": { "type": "number" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"truncated": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMRewardDeliverConfirmation",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["grantId", "outcome", "observedAt"],
|
||||
"properties": {
|
||||
"grantId": { "type": "string", "minLength": 1, "maxLength": 160 },
|
||||
"outcome": { "enum": ["delivered", "failed", "unknown"] },
|
||||
"observationId": { "type": "string", "minLength": 1, "maxLength": 160 },
|
||||
"observedAt": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
@@ -191,16 +191,15 @@ describe("plugin manifest validation", () => {
|
||||
expect(validateManifestFile("examples/scum-server-plugin/manifest.json")).toEqual([]);
|
||||
});
|
||||
|
||||
it("removes raw protected SQL and management request command surfaces", () => {
|
||||
it("removes unverified SCUM query and operation declarations", () => {
|
||||
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as { gameClientBridge: { commands: Array<{ type: string; protectedRequest?: { kind: string } }>; queryTemplates: Array<{ key: string }>; operationTemplates: Array<{ key: string; kind: string }> } };
|
||||
const commands = manifest.gameClientBridge.commands.filter((candidate) => candidate.protectedRequest);
|
||||
expect(commands).toEqual([]);
|
||||
expect(manifest.gameClientBridge.commands.map((command) => command.type)).not.toEqual(expect.arrayContaining(["config.read", "config.patch", "database.request", "management.rcon.request", "management.program.request"]));
|
||||
expect(manifest.gameClientBridge.queryTemplates.map((query) => query.key)).toEqual(expect.arrayContaining(["scum.player.profile", "scum.squads", "scum.squad-members", "scum.vehicles", "scum.flags", "scum.positions"]));
|
||||
expect(manifest.gameClientBridge.operationTemplates.map((operation) => operation.key)).toEqual(expect.arrayContaining(["player.fame.set", "player.currency.normal.set", "player.currency.gold.set", "player.notify", "reward.deliver"]));
|
||||
expect(manifest.gameClientBridge.operationTemplates.map((operation) => operation.key)).not.toContain("player.attribute.855.set");
|
||||
expect(fs.existsSync(path.join(pluginDir, "schemas/bridge/queries/SCUM_DB_CONTRACT.md"))).toBe(true);
|
||||
expect(manifest.gameClientBridge.queryTemplates).toEqual([]);
|
||||
expect(manifest.gameClientBridge.operationTemplates).toEqual([]);
|
||||
expect(fs.existsSync(path.join(pluginDir, "schemas/bridge/queries/SCUM_DB_CONTRACT.md"))).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps SCUM database-backed live-data gates disabled until current-service evidence exists", () => {
|
||||
@@ -474,7 +473,7 @@ describe("plugin manifest validation", () => {
|
||||
snapshots: Array<{ type: string; schemaVersion: string; schemaRef: string }>;
|
||||
pages: Array<{ pageKey: string; commandTypes?: string[]; snapshotTypes?: string[]; queryTemplateKeys?: string[]; operationKeys?: string[] }>;
|
||||
};
|
||||
pages: Array<{ key: string; permissions?: string[] }>;
|
||||
pages: Array<{ key: string; permissions?: string[]; bridgeActions?: string[] }>;
|
||||
fileWorkspace?: {
|
||||
defaultDirectoryKey: string;
|
||||
directories: Array<{ key: string; label: string; scope: string }>;
|
||||
@@ -513,16 +512,11 @@ describe("plugin manifest validation", () => {
|
||||
expect(manifest.gameClientBridge.snapshots.map((snapshot) => snapshot.type)).toEqual(expect.arrayContaining(["companion.health", "online.sessions", "players", "squads", "vehicles", "flags"]));
|
||||
expect(manifest.gameClientBridge.pages.map((page) => page.pageKey)).toEqual(["players", "squads", "live-map", "gifts"]);
|
||||
expect(manifest.gameClientBridge.pages.map((page) => page.pageKey)).not.toContain("files-config");
|
||||
expect(manifest.gameClientBridge.pages.find((page) => page.pageKey === "players")?.operationKeys).toEqual(expect.arrayContaining([
|
||||
"player.fame.set",
|
||||
"player.currency.normal.set",
|
||||
"player.currency.gold.set",
|
||||
"player.notify"
|
||||
]));
|
||||
expect(manifest.gameClientBridge.pages.find((page) => page.pageKey === "players")?.operationKeys).not.toContain("player.attribute.855.set");
|
||||
expect(manifest.gameClientBridge.pages.every((page) => !(page.queryTemplateKeys?.length) && !(page.operationKeys?.length))).toBe(true);
|
||||
expect(manifest.gameClientBridge.pages.find((page) => page.pageKey === "workflows")).toBeUndefined();
|
||||
expect(manifest.pages.map((page) => page.key)).toEqual(["players", "squads", "live-map", "gifts"]);
|
||||
expect(manifest.pages.map((page) => page.key)).not.toContain("files-config");
|
||||
expect(manifest.pages.every((page) => !(page.bridgeActions ?? []).includes("remote.access.request"))).toBe(true);
|
||||
expect(manifest.pages.find((page) => page.key === "players")?.permissions).toEqual(expect.arrayContaining(["server.game-client.read", "server.game-client.command", "server.game-client.maintenance"]));
|
||||
expect(manifest.fileWorkspace).toBeUndefined();
|
||||
expect(manifest.runtimeProfiles?.lifecycleProfiles?.find((profile) => profile.key === "scum-client")?.capabilities).not.toContain("remote.run.rcon.command");
|
||||
@@ -637,7 +631,7 @@ describe("plugin manifest validation", () => {
|
||||
expect(manifest.gameClientBridge.pages.find((page) => page.pageKey === "live-map")?.snapshotTypes).toEqual(expect.arrayContaining(["players", "vehicles", "flags"]));
|
||||
});
|
||||
|
||||
it("declares typed SCUM.db query templates without browser-visible SQL", () => {
|
||||
it("keeps SCUM.db query templates absent until current-service evidence exists", () => {
|
||||
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as {
|
||||
permissions: string[];
|
||||
@@ -661,7 +655,7 @@ describe("plugin manifest validation", () => {
|
||||
pages: Array<{ key: string; permissions?: string[]; bridgeActions?: string[] }>;
|
||||
runtimeProfiles?: { transportProfiles?: Array<{ key: string; kind: string; targetKey?: string; capabilities: string[] }> };
|
||||
};
|
||||
const expectedKeys = ["scum.player.profile", "scum.squads", "scum.squad-members", "scum.vehicles", "scum.flags", "scum.positions"];
|
||||
const expectedKeys: string[] = [];
|
||||
const templatesByKey = new Map(manifest.gameClientBridge.queryTemplates.map((template) => [template.key, template]));
|
||||
expect([...templatesByKey.keys()]).toEqual(expect.arrayContaining(expectedKeys));
|
||||
expect(manifest.capabilities).toContain("remote.run.db.sqlite.query");
|
||||
@@ -685,17 +679,17 @@ describe("plugin manifest validation", () => {
|
||||
const playersPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "players");
|
||||
const squadsPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "squads");
|
||||
const mapPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "live-map");
|
||||
expect(playersPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.player.profile", "scum.positions"]));
|
||||
expect(squadsPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.squads", "scum.squad-members", "scum.flags"]));
|
||||
expect(mapPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.vehicles", "scum.flags", "scum.positions"]));
|
||||
expect(playersPage?.queryTemplateKeys).toBeUndefined();
|
||||
expect(squadsPage?.queryTemplateKeys).toBeUndefined();
|
||||
expect(mapPage?.queryTemplateKeys).toBeUndefined();
|
||||
for (const pageKey of ["players", "squads", "live-map"]) {
|
||||
const pluginPage = manifest.pages.find((page) => page.key === pageKey);
|
||||
expect(pluginPage?.permissions).toContain("server.game-client.read");
|
||||
expect(pluginPage?.bridgeActions).toContain("remote.access.request");
|
||||
expect(pluginPage?.bridgeActions).not.toContain("remote.access.request");
|
||||
}
|
||||
});
|
||||
|
||||
it("declares typed SCUM RCON operations without arbitrary command inputs", () => {
|
||||
it("keeps SCUM RCON operation templates absent until command confirmation is verified", () => {
|
||||
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as {
|
||||
gameClientBridge: {
|
||||
@@ -704,7 +698,7 @@ describe("plugin manifest validation", () => {
|
||||
};
|
||||
pages: Array<{ key: string; permissions?: string[] }>;
|
||||
};
|
||||
const expectedKeys = ["player.fame.set", "player.currency.normal.set", "player.currency.gold.set", "player.notify", "reward.deliver"];
|
||||
const expectedKeys: string[] = [];
|
||||
const operationsByKey = new Map(manifest.gameClientBridge.operationTemplates.map((operation) => [operation.key, operation]));
|
||||
expect([...operationsByKey.keys()]).toEqual(expect.arrayContaining(expectedKeys));
|
||||
for (const key of expectedKeys) {
|
||||
@@ -723,8 +717,8 @@ describe("plugin manifest validation", () => {
|
||||
}
|
||||
const playersPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "players");
|
||||
const giftsPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "gifts");
|
||||
expect(playersPage?.operationKeys).toEqual(expect.arrayContaining(["player.fame.set", "player.currency.normal.set", "player.currency.gold.set", "player.notify"]));
|
||||
expect(giftsPage?.operationKeys).toEqual(expect.arrayContaining(["reward.deliver", "player.notify"]));
|
||||
expect(playersPage?.operationKeys).toBeUndefined();
|
||||
expect(giftsPage?.operationKeys).toBeUndefined();
|
||||
expect(manifest.pages.find((page) => page.key === "players")?.permissions).toContain("server.game-client.command");
|
||||
expect(manifest.pages.find((page) => page.key === "gifts")?.permissions).toContain("server.game-client.command");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user