Add SCUM player query assets
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"key": "scum-player-details-read-v1",
|
||||
"adapterVersion": "scum-live-data-v1",
|
||||
"queryVersion": "scum-sqlite-query-v1",
|
||||
"capability": "player-details.read",
|
||||
"requiredSchemaFingerprint": "sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0",
|
||||
"statementType": "single-select-or-cte",
|
||||
"statement": "SELECT u.id AS externalPlayerId, u.id_type AS idType, u.provider AS provider, u.creation_time AS userCreationTime, u.last_login_time AS userLastLoginTime, u.is_banned AS isBanned, up.id AS profileId, up.name AS displayName, up.type AS profileType, p.id AS prisonerId, p.user_profile_id AS prisonerUserProfileId, p.last_save_time AS prisonerLastSaveTime, pe.entity_id AS entityId, CASE WHEN up.template_xml IS NULL THEN NULL ELSE length(up.template_xml) END AS profileXmlLength FROM \"user\" u LEFT JOIN user_profile up ON up.user_id = u.id AND up.type = 1 LEFT JOIN prisoner p ON p.id = up.prisoner_id AND p.user_profile_id = up.id LEFT JOIN prisoner_entity pe ON pe.prisoner_id = p.id WHERE u.id = :externalPlayerId LIMIT 1",
|
||||
"parameters": [
|
||||
{ "name": "externalPlayerId", "binding": ":externalPlayerId", "type": "string", "required": true, "minLength": 1, "maxLength": 96 }
|
||||
],
|
||||
"safety": {
|
||||
"queryOnly": true,
|
||||
"readOnlyConnection": true,
|
||||
"forbidMultipleStatements": true,
|
||||
"forbidAttach": true,
|
||||
"forbidWritePragmas": true,
|
||||
"forbidExtensionLoading": true,
|
||||
"maxRows": 1,
|
||||
"timeoutMs": 2000,
|
||||
"maxResultBytes": 32768
|
||||
},
|
||||
"evidence": {
|
||||
"source": "openspec/changes/replace-scum-projections-with-real-data-management/evidence/scum-current-service-sqlite-diagnostic-2026-08-12.md",
|
||||
"provenFields": ["user.id", "user.id_type", "user.provider", "user.creation_time", "user.last_login_time", "user.is_banned", "user_profile.id", "user_profile.name", "user_profile.type", "user_profile.template_xml", "prisoner.id", "prisoner.user_profile_id", "prisoner.last_save_time", "prisoner_entity.entity_id"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"key": "scum-player-economy-read-v1",
|
||||
"adapterVersion": "scum-live-data-v1",
|
||||
"queryVersion": "scum-sqlite-query-v1",
|
||||
"capability": "player-details.read",
|
||||
"requiredSchemaFingerprint": "sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0",
|
||||
"statementType": "single-select-or-cte",
|
||||
"statement": "SELECT u.id AS externalPlayerId, up.id AS profileId, bar.id AS bankAccountId, bac.id AS currencyRowId, bac.currency_type AS currencyType, bac.account_balance AS accountBalance FROM \"user\" u JOIN user_profile up ON up.user_id = u.id AND up.type = 1 JOIN bank_account_registry bar ON bar.account_owner_user_profile_id = up.id JOIN bank_account_registry_currencies bac ON bac.bank_account_id = bar.id WHERE u.id = :externalPlayerId ORDER BY bac.currency_type ASC, bac.id ASC LIMIT :limit",
|
||||
"parameters": [
|
||||
{ "name": "externalPlayerId", "binding": ":externalPlayerId", "type": "string", "required": true, "minLength": 1, "maxLength": 96 },
|
||||
{ "name": "limit", "binding": ":limit", "type": "integer", "required": true, "minimum": 1, "maximum": 16 }
|
||||
],
|
||||
"safety": {
|
||||
"queryOnly": true,
|
||||
"readOnlyConnection": true,
|
||||
"forbidMultipleStatements": true,
|
||||
"forbidAttach": true,
|
||||
"forbidWritePragmas": true,
|
||||
"forbidExtensionLoading": true,
|
||||
"maxRows": 16,
|
||||
"timeoutMs": 2000,
|
||||
"maxResultBytes": 32768
|
||||
},
|
||||
"evidence": {
|
||||
"source": "openspec/changes/replace-scum-projections-with-real-data-management/evidence/scum-current-service-sqlite-diagnostic-2026-08-12.md",
|
||||
"provenJoins": ["bank_account_registry.account_owner_user_profile_id -> user_profile.id", "bank_account_registry_currencies.bank_account_id -> bank_account_registry.id"],
|
||||
"ambiguity": "Currency labels, units, command execution, and readback confirmation are unverified; currencyType remains numeric and version-scoped."
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"key": "scum-player-session-enrichment-read-v1",
|
||||
"adapterVersion": "scum-live-data-v1",
|
||||
"queryVersion": "scum-sqlite-query-v1",
|
||||
"capability": "players.read",
|
||||
"requiredSchemaFingerprint": "sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0",
|
||||
"statementType": "single-select-or-cte",
|
||||
"statement": "SELECT u.id AS externalPlayerId, u.id_type AS idType, u.provider AS provider, u.creation_time AS userCreationTime, u.last_login_time AS userLastLoginTime, u.is_banned AS isBanned, up.id AS profileId, up.name AS displayName, up.type AS profileType, p.id AS prisonerId FROM \"user\" u LEFT JOIN user_profile up ON up.user_id = u.id AND up.type = 1 LEFT JOIN prisoner p ON p.id = up.prisoner_id AND p.user_profile_id = up.id WHERE u.id = :externalPlayerId LIMIT 1",
|
||||
"parameters": [
|
||||
{ "name": "externalPlayerId", "binding": ":externalPlayerId", "type": "string", "required": true, "minLength": 1, "maxLength": 96 }
|
||||
],
|
||||
"safety": {
|
||||
"queryOnly": true,
|
||||
"readOnlyConnection": true,
|
||||
"forbidMultipleStatements": true,
|
||||
"forbidAttach": true,
|
||||
"forbidWritePragmas": true,
|
||||
"forbidExtensionLoading": true,
|
||||
"maxRows": 1,
|
||||
"timeoutMs": 2000,
|
||||
"maxResultBytes": 32768
|
||||
},
|
||||
"evidence": {
|
||||
"source": "openspec/changes/replace-scum-projections-with-real-data-management/evidence/scum-current-service-sqlite-diagnostic-2026-08-12.md",
|
||||
"sessionBoundary": "Online state and local sessions are created from authenticated login/logout events; this query only enriches a login-created identity with proven database facts."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"key": "scum-players-read-v1",
|
||||
"adapterVersion": "scum-live-data-v1",
|
||||
"queryVersion": "scum-sqlite-query-v1",
|
||||
"capability": "players.read",
|
||||
"requiredSchemaFingerprint": "sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0",
|
||||
"statementType": "single-select-or-cte",
|
||||
"statement": "WITH player_rows AS (SELECT u.id AS externalPlayerId, u.id_type AS idType, u.provider AS provider, u.creation_time AS userCreationTime, u.last_login_time AS userLastLoginTime, u.is_banned AS isBanned, up.id AS profileId, up.name AS displayName, up.type AS profileType, p.id AS prisonerId, pe.entity_id AS entityId FROM \"user\" u LEFT JOIN user_profile up ON up.user_id = u.id AND up.type = 1 LEFT JOIN prisoner p ON p.id = up.prisoner_id AND p.user_profile_id = up.id LEFT JOIN prisoner_entity pe ON pe.prisoner_id = p.id ORDER BY u.last_login_time DESC, u.id ASC LIMIT :limit OFFSET :offset) SELECT externalPlayerId, idType, provider, userCreationTime, userLastLoginTime, isBanned, profileId, displayName, profileType, prisonerId, entityId FROM player_rows",
|
||||
"parameters": [
|
||||
{ "name": "limit", "binding": ":limit", "type": "integer", "required": true, "minimum": 1, "maximum": 100 },
|
||||
{ "name": "offset", "binding": ":offset", "type": "integer", "required": true, "minimum": 0, "maximum": 1000000 }
|
||||
],
|
||||
"safety": {
|
||||
"queryOnly": true,
|
||||
"readOnlyConnection": true,
|
||||
"forbidMultipleStatements": true,
|
||||
"forbidAttach": true,
|
||||
"forbidWritePragmas": true,
|
||||
"forbidExtensionLoading": true,
|
||||
"maxRows": 100,
|
||||
"timeoutMs": 2000,
|
||||
"maxResultBytes": 65536
|
||||
},
|
||||
"evidence": {
|
||||
"source": "openspec/changes/replace-scum-projections-with-real-data-management/evidence/scum-current-service-sqlite-diagnostic-2026-08-12.md",
|
||||
"provenJoins": ["user_profile.user_id -> user.id", "user_profile.prisoner_id -> prisoner.id", "prisoner.user_profile_id -> user_profile.id", "prisoner_entity.prisoner_id -> prisoner.id"]
|
||||
}
|
||||
}
|
||||
@@ -421,6 +421,68 @@
|
||||
"cursorPolicy": "source-generation-sequence",
|
||||
"privacy": { "stripNetworkIdentifiers": true, "logicalEventIdentity": "native-or-sanitized-fields" }
|
||||
}
|
||||
],
|
||||
"sqliteQueries": [
|
||||
{
|
||||
"key": "scum-players-read",
|
||||
"adapterVersion": "scum-live-data-v1",
|
||||
"assetPath": "assets/scum-live/queries/players-read.json",
|
||||
"digest": "sha256:b3359f3c5939a410a98ddfccb920791044df76da4f8e5df4e726a9fe58423520",
|
||||
"capability": "players.read",
|
||||
"requiredSchemaFingerprint": "sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/scum-live/players-read.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/scum-live/players-read.result.schema.json",
|
||||
"maxRows": 100,
|
||||
"timeoutMs": 2000,
|
||||
"maxResultBytes": 65536
|
||||
},
|
||||
{
|
||||
"key": "scum-player-details-read",
|
||||
"adapterVersion": "scum-live-data-v1",
|
||||
"assetPath": "assets/scum-live/queries/player-details-read.json",
|
||||
"digest": "sha256:c980807b736f8988cd7c37ecb97c72e5e707050450ebc8c539dccec06c60e1f8",
|
||||
"capability": "player-details.read",
|
||||
"requiredSchemaFingerprint": "sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/scum-live/player-details-read.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/scum-live/player-details-read.result.schema.json",
|
||||
"maxRows": 1,
|
||||
"timeoutMs": 2000,
|
||||
"maxResultBytes": 32768
|
||||
},
|
||||
{
|
||||
"key": "scum-player-economy-read",
|
||||
"adapterVersion": "scum-live-data-v1",
|
||||
"assetPath": "assets/scum-live/queries/player-economy-read.json",
|
||||
"digest": "sha256:919c5f68f74fdb0743fa5d9b59aeecd003dcdac5bc51e52d3a486ed1045c9a48",
|
||||
"capability": "player-details.read",
|
||||
"requiredSchemaFingerprint": "sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/scum-live/player-economy-read.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/scum-live/player-economy-read.result.schema.json",
|
||||
"maxRows": 16,
|
||||
"timeoutMs": 2000,
|
||||
"maxResultBytes": 32768
|
||||
},
|
||||
{
|
||||
"key": "scum-player-session-enrichment-read",
|
||||
"adapterVersion": "scum-live-data-v1",
|
||||
"assetPath": "assets/scum-live/queries/player-session-enrichment-read.json",
|
||||
"digest": "sha256:d9c262d0b4f1b600b608c8279a6dfb052de1a605fe1286ddc15f74892eace4fc",
|
||||
"capability": "players.read",
|
||||
"requiredSchemaFingerprint": "sha256:ebd477d6c6ead9c34c41169af489236d762a76186d45dedd753d50f1b81e26f0",
|
||||
"transportKey": "scum-database",
|
||||
"targetKey": "scum-database",
|
||||
"parameterSchemaRef": "schemas/scum-live/player-session-enrichment-read.parameters.schema.json",
|
||||
"resultSchemaRef": "schemas/scum-live/player-session-enrichment-read.result.schema.json",
|
||||
"maxRows": 1,
|
||||
"timeoutMs": 2000,
|
||||
"maxResultBytes": 32768
|
||||
}
|
||||
]
|
||||
},
|
||||
"permissions": [
|
||||
@@ -480,6 +542,22 @@
|
||||
{
|
||||
"path": "assets/scum-live/login-log-parser.json",
|
||||
"mode": 384
|
||||
},
|
||||
{
|
||||
"path": "assets/scum-live/queries/players-read.json",
|
||||
"mode": 384
|
||||
},
|
||||
{
|
||||
"path": "assets/scum-live/queries/player-details-read.json",
|
||||
"mode": 384
|
||||
},
|
||||
{
|
||||
"path": "assets/scum-live/queries/player-economy-read.json",
|
||||
"mode": 384
|
||||
},
|
||||
{
|
||||
"path": "assets/scum-live/queries/player-session-enrichment-read.json",
|
||||
"mode": 384
|
||||
}
|
||||
],
|
||||
"productionLifecycle": {
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerDetailsReadParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["externalPlayerId"],
|
||||
"properties": {
|
||||
"externalPlayerId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" }
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerDetailsReadResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["externalPlayerId", "idType", "provider", "userCreationTime", "userLastLoginTime", "isBanned", "profileId", "displayName", "profileType", "prisonerId", "prisonerUserProfileId", "prisonerLastSaveTime", "entityId", "profileXmlLength"],
|
||||
"properties": {
|
||||
"externalPlayerId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" },
|
||||
"idType": { "type": "string", "minLength": 1, "maxLength": 32 },
|
||||
"provider": { "type": "string", "minLength": 1, "maxLength": 32 },
|
||||
"userCreationTime": { "type": "string", "minLength": 1, "maxLength": 64 },
|
||||
"userLastLoginTime": { "type": "string", "minLength": 1, "maxLength": 64 },
|
||||
"isBanned": { "type": "integer", "minimum": 0, "maximum": 1 },
|
||||
"profileId": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"displayName": { "type": ["string", "null"], "minLength": 1, "maxLength": 80 },
|
||||
"profileType": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"prisonerId": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"prisonerUserProfileId": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"prisonerLastSaveTime": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"entityId": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"profileXmlLength": { "type": ["integer", "null"], "minimum": 0, "maximum": 1048576 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerEconomyReadParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["externalPlayerId", "limit"],
|
||||
"properties": {
|
||||
"externalPlayerId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" },
|
||||
"limit": { "type": "integer", "minimum": 1, "maximum": 16 }
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerEconomyReadResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 16,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["externalPlayerId", "profileId", "bankAccountId", "currencyRowId", "currencyType", "accountBalance"],
|
||||
"properties": {
|
||||
"externalPlayerId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" },
|
||||
"profileId": { "type": "integer", "minimum": 0, "maximum": 2147483647 },
|
||||
"bankAccountId": { "type": "integer", "minimum": 0, "maximum": 2147483647 },
|
||||
"currencyRowId": { "type": "integer", "minimum": 0, "maximum": 2147483647 },
|
||||
"currencyType": { "type": "integer", "minimum": 0, "maximum": 2147483647 },
|
||||
"accountBalance": { "type": ["integer", "null"], "minimum": -2147483648, "maximum": 2147483647 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerSessionEnrichmentReadParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["externalPlayerId"],
|
||||
"properties": {
|
||||
"externalPlayerId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" }
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayerSessionEnrichmentReadResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["externalPlayerId", "idType", "provider", "userCreationTime", "userLastLoginTime", "isBanned", "profileId", "displayName", "profileType", "prisonerId"],
|
||||
"properties": {
|
||||
"externalPlayerId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" },
|
||||
"idType": { "type": "string", "minLength": 1, "maxLength": 32 },
|
||||
"provider": { "type": "string", "minLength": 1, "maxLength": 32 },
|
||||
"userCreationTime": { "type": "string", "minLength": 1, "maxLength": 64 },
|
||||
"userLastLoginTime": { "type": "string", "minLength": 1, "maxLength": 64 },
|
||||
"isBanned": { "type": "integer", "minimum": 0, "maximum": 1 },
|
||||
"profileId": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"displayName": { "type": ["string", "null"], "minLength": 1, "maxLength": 80 },
|
||||
"profileType": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"prisonerId": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayersReadParameters",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["limit", "offset"],
|
||||
"properties": {
|
||||
"limit": { "type": "integer", "minimum": 1, "maximum": 100 },
|
||||
"offset": { "type": "integer", "minimum": 0, "maximum": 1000000 }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "SCUMPlayersReadResult",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["rows"],
|
||||
"properties": {
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"maxItems": 100,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["externalPlayerId", "idType", "provider", "userCreationTime", "userLastLoginTime", "isBanned", "profileId", "displayName", "profileType", "prisonerId", "entityId"],
|
||||
"properties": {
|
||||
"externalPlayerId": { "type": "string", "minLength": 1, "maxLength": 96, "pattern": "^[A-Za-z0-9_.:-]{1,96}$" },
|
||||
"idType": { "type": "string", "minLength": 1, "maxLength": 32 },
|
||||
"provider": { "type": "string", "minLength": 1, "maxLength": 32 },
|
||||
"userCreationTime": { "type": "string", "minLength": 1, "maxLength": 64 },
|
||||
"userLastLoginTime": { "type": "string", "minLength": 1, "maxLength": 64 },
|
||||
"isBanned": { "type": "integer", "minimum": 0, "maximum": 1 },
|
||||
"profileId": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"displayName": { "type": ["string", "null"], "minLength": 1, "maxLength": 80 },
|
||||
"profileType": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"prisonerId": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 },
|
||||
"entityId": { "type": ["integer", "null"], "minimum": 0, "maximum": 2147483647 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,6 +218,32 @@ describe("plugin manifest validation", () => {
|
||||
expect(JSON.stringify(manifest.scumLiveData).toLowerCase()).not.toMatch(/select\s+.+from|sqlite:\/\/|mysql:\/\/|password|credential|socket|hostpath/);
|
||||
});
|
||||
|
||||
it("packages SCUM player read query assets with exact bounded result schemas", () => {
|
||||
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
|
||||
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as GamePluginManifest & { scumLiveData: SCUMLiveDataManifestDeclaration };
|
||||
const assetPaths = new Set(manifest.assetFiles?.map((file) => file.path) ?? []);
|
||||
const queries = manifest.scumLiveData.sqliteQueries ?? [];
|
||||
expect(queries.map((query) => query.key)).toEqual(["scum-players-read", "scum-player-details-read", "scum-player-economy-read", "scum-player-session-enrichment-read"]);
|
||||
|
||||
for (const query of queries) {
|
||||
expect(assetPaths.has(query.assetPath)).toBe(true);
|
||||
const assetPath = path.join(pluginDir, query.assetPath);
|
||||
const actualDigest = `sha256:${crypto.createHash("sha256").update(fs.readFileSync(assetPath)).digest("hex")}`;
|
||||
expect(query.digest).toBe(actualDigest);
|
||||
const asset = JSON.parse(fs.readFileSync(assetPath, "utf8")) as { requiredSchemaFingerprint?: string; statement?: string; safety?: { queryOnly?: boolean; readOnlyConnection?: boolean } };
|
||||
expect(asset.requiredSchemaFingerprint).toBe(query.requiredSchemaFingerprint);
|
||||
expect(asset.safety).toMatchObject({ queryOnly: true, readOnlyConnection: true });
|
||||
expect(asset.statement).toMatch(/^(WITH|SELECT)\b/i);
|
||||
expect(asset.statement).not.toMatch(/;|\b(INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|ATTACH)\b/i);
|
||||
|
||||
for (const schemaRef of [query.parameterSchemaRef, query.resultSchemaRef]) {
|
||||
expect(fs.existsSync(path.join(pluginDir, schemaRef))).toBe(true);
|
||||
}
|
||||
const resultSchema = JSON.parse(fs.readFileSync(path.join(pluginDir, query.resultSchemaRef), "utf8")) as { properties?: { rows?: { maxItems?: number } } };
|
||||
expect(resultSchema.properties?.rows?.maxItems).toBeLessThanOrEqual(query.maxRows);
|
||||
}
|
||||
});
|
||||
|
||||
it("requires SCUM schema probe targets to have generated Run workspace data targets", () => {
|
||||
const errors = validateTemporaryScumCompanionManifest((manifest) => {
|
||||
manifest.runtimeProfiles.dataTargets = [];
|
||||
@@ -238,7 +264,7 @@ describe("plugin manifest validation", () => {
|
||||
const fingerprint = `sha256:${"f".repeat(64)}`;
|
||||
const assetPaths = [
|
||||
"assets/scum-live/login-parser.json",
|
||||
"assets/scum-live/queries/players-read.json",
|
||||
"assets/scum-live/queries/fixture-players-read.json",
|
||||
"assets/scum-live/rcon/gift-grant.json",
|
||||
"assets/scum-live/mutations/profile-xml-patch.json",
|
||||
"assets/scum-live/map/island.png",
|
||||
|
||||
Reference in New Issue
Block a user