Implement SCUM direct data plane
This commit is contained in:
@@ -21,8 +21,9 @@ func TestSCUMProjectionOperationAndWorkflowAPIsExposeSafeTypedSurfaces(t *testin
|
||||
}
|
||||
plugin := validGamePluginRequest().ToDomain()
|
||||
plugin.DeclaredPermissions = append(plugin.DeclaredPermissions, "server.game-client.command", "server.game-client.read")
|
||||
plugin.RequiredRunCapabilities = append(plugin.RequiredRunCapabilities, domain.JobCapabilityRemoteRunRCONCommand, domain.JobCapabilityRemoteRunProtectedRCON)
|
||||
plugin.RuntimeProfiles.TransportProfiles = []domain.RuntimeTransportProfile{{Key: "scum-management", Kind: "rcon", TargetKey: "scum-management", Capabilities: []string{domain.JobCapabilityRemoteRunRCONCommand, domain.JobCapabilityRemoteRunProtectedRCON}}}
|
||||
plugin.RequiredRunCapabilities = append(plugin.RequiredRunCapabilities, domain.JobCapabilityRemoteRunRCONCommand, domain.JobCapabilityRemoteRunProtectedRCON, domain.JobCapabilityRemoteRunDBSQLiteQuery)
|
||||
plugin.RuntimeProfiles.TransportProfiles = []domain.RuntimeTransportProfile{{Key: "scum-management", Kind: "rcon", TargetKey: "scum-management", Capabilities: []string{domain.JobCapabilityRemoteRunRCONCommand, domain.JobCapabilityRemoteRunProtectedRCON}}, {Key: "scum-data", Kind: "sqlite", TargetKey: "scum-data", Capabilities: []string{domain.JobCapabilityRemoteRunDBSQLiteQuery}}}
|
||||
plugin.GameClientBridge.QueryTemplates = []domain.GameClientBridgeQueryTemplateDeclaration{{Key: "v57.directory.people", Title: "SCUM users", Permission: "server.game-client.read", Engine: "sqlite", TransportKey: "scum-data", TargetKey: "scum-data", ParameterSchemaRef: "schemas/bridge/queries/scum-player-profile.parameters.schema.json", ResultSchemaRef: "schemas/bridge/queries/scum-player-profile.result.schema.json", MaxRows: 200, TimeoutSeconds: 15, RowTarget: &domain.SCUMRowTargetDeclaration{TargetTable: string(domain.SCUMDataSetUsers), UpsertKeys: []string{"profileId"}, ColumnMappings: map[string]string{"profileId": "user_profile_id", "displayName": "display_name"}}}}
|
||||
plugin.GameClientBridge.OperationTemplates = []domain.GameClientBridgeOperationTemplateDeclaration{{Key: "player.fame.set", Title: "Set fame", Permission: "server.game-client.command", ApprovalLevel: domain.GameClientBridgeApprovalLevelOperator, Kind: domain.GameClientBridgeOperationKindRCON, TransportKey: "scum-management", TargetKey: "scum-management", PayloadSchemaRef: "schemas/bridge/player-fame-set.payload.schema.json", TimeoutSeconds: 60, MaxPayloadBytes: 2048, Safety: domain.GameClientBridgeOperationSafety{RequiresApproval: true, RequiresConfirmation: true}}}
|
||||
plugin.GameClientBridge.Retention = domain.GameClientBridgeRetention{KeepForSeconds: 86400, MaxRecords: 1000}
|
||||
if _, err := core.CreateGamePlugin(plugin); err != nil {
|
||||
@@ -40,6 +41,9 @@ func TestSCUMProjectionOperationAndWorkflowAPIsExposeSafeTypedSurfaces(t *testin
|
||||
if _, err := core.ApplySCUMObservationResult(domain.SCUMObservationResult{ServerInstanceID: "server-scum-api", PluginID: plugin.ID, Source: "run.sqlite.read", QueryKey: "scum.player.profile", Sequence: 1, Checksum: "sha256:api-profile", ObservedAt: time.Now().UTC(), Rows: []map[string]any{{"gamePlayerId": "steam-api", "displayName": "API Player", "normalBalance": 25, "x": 1, "y": 2, "z": 3}}}); err != nil {
|
||||
t.Fatalf("seed projection: %v", err)
|
||||
}
|
||||
if _, err := core.ApplySCUMObservationResult(domain.SCUMObservationResult{ServerInstanceID: "server-scum-api", PluginID: plugin.ID, Source: "run.sqlite.read", QueryKey: "v57.directory.people", Sequence: 1, Checksum: "sha256:api-users", ObservedAt: time.Now().UTC(), Rows: []map[string]any{{"user_profile_id": "profile-api", "display_name": "API User"}}}); err != nil {
|
||||
t.Fatalf("seed SCUM users: %v", err)
|
||||
}
|
||||
auth, err := core.LoginUser(domain.UserLogin{Account: "scum-api-owner@example.test", Password: "secret-password"})
|
||||
if err != nil {
|
||||
t.Fatalf("login: %v", err)
|
||||
@@ -49,6 +53,10 @@ func TestSCUMProjectionOperationAndWorkflowAPIsExposeSafeTypedSurfaces(t *testin
|
||||
if players.Count != 1 || players.Items[0].GamePlayerID != "steam-api" || players.Items[0].Position.X != 1 {
|
||||
t.Fatalf("unexpected SCUM players response: %+v", players)
|
||||
}
|
||||
users := getJSONWithAuth[dto.SCUMDataRowListResponse](t, router, "/api/v1/server-instances/server-scum-api/scum/users", auth.SessionID)
|
||||
if users.Count != 1 || users.Items[0].Fields["profileId"] != "profile-api" || users.Items[0].Payload["display_name"] != "API User" {
|
||||
t.Fatalf("unexpected persisted SCUM users response: %+v", users)
|
||||
}
|
||||
operation := postJSONWithAuth[dto.SCUMOperationResponse](t, router, "/api/v1/server-instances/server-scum-api/scum/operations", dto.SCUMOperationRequestBody{TemplateKey: "player.fame.set", PlayerID: "steam-api", Payload: map[string]any{"fame": 12}, Reason: "api typed op", IdempotencyKey: "api-fame-1"}, auth.SessionID)
|
||||
if operation.Status != string(domain.SCUMWorkflowStepWaiting) || operation.TemplateKey != "player.fame.set" {
|
||||
t.Fatalf("unexpected SCUM operation response: %+v", operation)
|
||||
|
||||
Reference in New Issue
Block a user