feat(scum): gate live data on schema evidence

This commit is contained in:
npc0-hue
2026-08-11 13:28:36 +08:00
parent e5d26e5420
commit a58da47c60
18 changed files with 1265 additions and 3 deletions
+53
View File
@@ -399,6 +399,28 @@ type GameMapTrajectoryDeclarationBody struct {
RetentionSeconds int `json:"retentionSeconds"`
}
type SCUMSchemaProbeDeclarationBody struct {
Capability string `json:"capability"`
TargetKey string `json:"targetKey"`
Bounds SCUMSchemaProbeBoundsDTO `json:"bounds"`
}
type SCUMLiveDataCapabilityGateBody struct {
Capability string `json:"capability"`
Gate string `json:"gate"`
AdapterVersion string `json:"adapterVersion"`
RequiredSchemaFingerprint string `json:"requiredSchemaFingerprint,omitempty"`
RequiredAssetDigests []string `json:"requiredAssetDigests,omitempty"`
EvidenceStatus string `json:"evidenceStatus"`
SafeReason string `json:"safeReason"`
}
type SCUMLiveDataManifestBody struct {
SchemaVersion string `json:"schemaVersion"`
Probe SCUMSchemaProbeDeclarationBody `json:"probe"`
CapabilityGates []SCUMLiveDataCapabilityGateBody `json:"capabilityGates"`
}
type GamePluginManifestBody struct {
ID string `json:"id"`
Name string `json:"name"`
@@ -419,6 +441,7 @@ type GamePluginManifestBody struct {
RemoteAccess GamePluginRemoteAccessBody `json:"remoteAccess,omitempty"`
RuntimeProfiles GamePluginRuntimeProfilesBody `json:"runtimeProfiles,omitempty"`
GameClientBridge GameClientBridgeManifestBody `json:"gameClientBridge,omitempty"`
SCUMLiveData SCUMLiveDataManifestBody `json:"scumLiveData,omitempty"`
MapTrajectories *GameMapTrajectoryDeclarationBody `json:"mapTrajectories,omitempty"`
}
@@ -458,6 +481,7 @@ type GamePluginCreateRequest struct {
RemoteAccess GamePluginRemoteAccessBody `json:"remoteAccess,omitempty"`
RuntimeProfiles GamePluginRuntimeProfilesBody `json:"runtimeProfiles,omitempty"`
GameClientBridge GameClientBridgeManifestBody `json:"gameClientBridge,omitempty"`
SCUMLiveData SCUMLiveDataManifestBody `json:"scumLiveData,omitempty"`
MapTrajectories *GameMapTrajectoryDeclarationBody `json:"mapTrajectories,omitempty"`
ValidationViolations []string `json:"validationViolations,omitempty"`
}
@@ -486,6 +510,7 @@ type GamePluginResponse struct {
RemoteAccess GamePluginRemoteAccessBody `json:"remoteAccess,omitempty"`
RuntimeProfiles GamePluginRuntimeProfilesResponseBody `json:"runtimeProfiles,omitempty"`
GameClientBridge GameClientBridgeManifestBody `json:"gameClientBridge,omitempty"`
SCUMLiveData *SCUMLiveDataManifestBody `json:"scumLiveData,omitempty"`
MapTrajectories *GameMapTrajectoryDeclarationBody `json:"mapTrajectories,omitempty"`
ValidationViolations []string `json:"validationViolations,omitempty"`
Status domain.GamePluginStatus `json:"status"`
@@ -1082,11 +1107,20 @@ func (request GamePluginManifestRegistrationRequest) ToDomain() domain.GamePlugi
RemoteAccess: request.Manifest.RemoteAccess.ToDomain(),
RuntimeProfiles: request.Manifest.RuntimeProfiles.ToDomain(),
GameClientBridge: request.Manifest.GameClientBridge.ToDomain(),
SCUMLiveData: request.Manifest.SCUMLiveData.ToDomain(),
MapTrajectories: mapTrajectoryDeclarationToDomain(request.Manifest.MapTrajectories),
},
}
}
func (body SCUMLiveDataManifestBody) ToDomain() domain.SCUMLiveDataManifest {
gates := make([]domain.SCUMLiveDataCapabilityGateDeclaration, len(body.CapabilityGates))
for index, gate := range body.CapabilityGates {
gates[index] = domain.SCUMLiveDataCapabilityGateDeclaration{Capability: domain.SCUMDataCapability(gate.Capability), Gate: domain.SCUMCapabilityGateState(gate.Gate), AdapterVersion: gate.AdapterVersion, RequiredSchemaFingerprint: gate.RequiredSchemaFingerprint, RequiredAssetDigests: domain.CopyStringSlice(gate.RequiredAssetDigests), EvidenceStatus: domain.SCUMCapabilityEvidenceStatus(gate.EvidenceStatus), SafeReason: gate.SafeReason}
}
return domain.SCUMLiveDataManifest{SchemaVersion: body.SchemaVersion, Probe: domain.SCUMSchemaProbeDeclaration{Capability: body.Probe.Capability, TargetKey: body.Probe.TargetKey, Bounds: scumProbeBoundsToDomain(body.Probe.Bounds)}, CapabilityGates: gates}
}
func pluginAssetFilesToDomain(files []PluginAssetFileBody) []domain.PluginAssetFile {
if files == nil {
return nil
@@ -1268,6 +1302,7 @@ func (request GamePluginCreateRequest) ToDomain() domain.GamePlugin {
RemoteAccess: request.RemoteAccess.ToDomain(),
RuntimeProfiles: request.RuntimeProfiles.ToDomain(),
GameClientBridge: request.GameClientBridge.ToDomain(),
SCUMLiveData: request.SCUMLiveData.ToDomain(),
MapTrajectories: mapTrajectoryDeclarationToDomain(request.MapTrajectories),
ValidationViolations: domain.CopyStringSlice(request.ValidationViolations),
}
@@ -1521,6 +1556,7 @@ func GamePluginFromDomain(plugin domain.GamePlugin) GamePluginResponse {
RemoteAccess: remoteAccessFromDomain(plugin.RemoteAccess),
RuntimeProfiles: runtimeProfilesFromDomain(plugin.RuntimeProfiles),
GameClientBridge: gameClientBridgeManifestFromDomain(plugin.GameClientBridge),
SCUMLiveData: scumLiveDataManifestPtrFromDomain(plugin.SCUMLiveData),
MapTrajectories: mapTrajectoryDeclarationFromDomain(plugin.MapTrajectories),
ValidationViolations: plugin.ValidationViolations,
Status: plugin.Status,
@@ -1625,6 +1661,23 @@ func productionLifecycleFromDomain(lifecycle domain.GamePluginProductionLifecycl
return GamePluginProductionLifecycleBody{Operations: lifecycle.Operations, DependencyPolicy: lifecycle.DependencyPolicy, ApprovalRequired: lifecycle.ApprovalRequired}
}
func scumLiveDataManifestFromDomain(value domain.SCUMLiveDataManifest) SCUMLiveDataManifestBody {
value = domain.CopySCUMLiveDataManifest(value)
gates := make([]SCUMLiveDataCapabilityGateBody, len(value.CapabilityGates))
for index, gate := range value.CapabilityGates {
gates[index] = SCUMLiveDataCapabilityGateBody{Capability: string(gate.Capability), Gate: string(gate.Gate), AdapterVersion: gate.AdapterVersion, RequiredSchemaFingerprint: gate.RequiredSchemaFingerprint, RequiredAssetDigests: domain.CopyStringSlice(gate.RequiredAssetDigests), EvidenceStatus: string(gate.EvidenceStatus), SafeReason: gate.SafeReason}
}
return SCUMLiveDataManifestBody{SchemaVersion: value.SchemaVersion, Probe: SCUMSchemaProbeDeclarationBody{Capability: value.Probe.Capability, TargetKey: value.Probe.TargetKey, Bounds: scumProbeBoundsFromDomain(value.Probe.Bounds)}, CapabilityGates: gates}
}
func scumLiveDataManifestPtrFromDomain(value domain.SCUMLiveDataManifest) *SCUMLiveDataManifestBody {
if value.SchemaVersion == "" && value.Probe.Capability == "" && len(value.CapabilityGates) == 0 {
return nil
}
body := scumLiveDataManifestFromDomain(value)
return &body
}
func gameClientBridgeManifestFromDomain(value domain.GameClientBridgeManifest) GameClientBridgeManifestBody {
value = domain.CopyGameClientBridgeManifest(value)
commands := make([]GameClientBridgeCommandDeclarationBody, len(value.Commands))