feat(scum): gate live data on schema evidence
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"browser.local/platform/domain"
|
||||
)
|
||||
|
||||
type SCUMBindingIdentityDTO struct {
|
||||
ServerInstanceID string `json:"serverInstanceId"`
|
||||
RunBindingID string `json:"runBindingId"`
|
||||
RunEndpointID string `json:"runEndpointId"`
|
||||
PluginID string `json:"pluginId"`
|
||||
PluginVersion string `json:"pluginVersion"`
|
||||
AdapterVersion string `json:"adapterVersion"`
|
||||
GameVersion string `json:"gameVersion"`
|
||||
DatabaseIdentity string `json:"databaseIdentity"`
|
||||
}
|
||||
|
||||
type SCUMSchemaProbeBoundsDTO struct {
|
||||
MaxObjects int `json:"maxObjects"`
|
||||
MaxColumnsPerObject int `json:"maxColumnsPerObject"`
|
||||
MaxIndexesPerObject int `json:"maxIndexesPerObject"`
|
||||
MaxForeignKeys int `json:"maxForeignKeys"`
|
||||
MaxCardinalityReads int `json:"maxCardinalityReads"`
|
||||
MaxSampleRows int `json:"maxSampleRows"`
|
||||
TimeoutMS int `json:"timeoutMs"`
|
||||
MaxResultBytes int `json:"maxResultBytes"`
|
||||
}
|
||||
|
||||
type SCUMSchemaProbeRequestDTO struct {
|
||||
RequestID string `json:"requestId"`
|
||||
JobID string `json:"jobId"`
|
||||
Binding SCUMBindingIdentityDTO `json:"binding"`
|
||||
Bounds SCUMSchemaProbeBoundsDTO `json:"bounds"`
|
||||
RequestedAt time.Time `json:"requestedAt"`
|
||||
}
|
||||
|
||||
type SCUMSafeErrorDTO struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Retryable bool `json:"retryable"`
|
||||
}
|
||||
|
||||
type SCUMSchemaColumnEvidenceDTO struct {
|
||||
NameFingerprint string `json:"nameFingerprint"`
|
||||
DeclaredType string `json:"declaredType"`
|
||||
Nullable *bool `json:"nullable,omitempty"`
|
||||
PrimaryKey bool `json:"primaryKey"`
|
||||
Ordinal int `json:"ordinal"`
|
||||
}
|
||||
|
||||
type SCUMSchemaIndexEvidenceDTO struct {
|
||||
NameFingerprint string `json:"nameFingerprint"`
|
||||
Unique bool `json:"unique"`
|
||||
ColumnHashes []string `json:"columnHashes"`
|
||||
}
|
||||
|
||||
type SCUMSchemaForeignKeyEvidenceDTO struct {
|
||||
FromColumnHash string `json:"fromColumnHash"`
|
||||
ToObjectHash string `json:"toObjectHash"`
|
||||
ToColumnHash string `json:"toColumnHash"`
|
||||
}
|
||||
|
||||
type SCUMSchemaObjectEvidenceDTO struct {
|
||||
ObjectHash string `json:"objectHash"`
|
||||
Kind string `json:"kind"`
|
||||
NameFingerprint string `json:"nameFingerprint"`
|
||||
DeclaredColumns []SCUMSchemaColumnEvidenceDTO `json:"declaredColumns"`
|
||||
Indexes []SCUMSchemaIndexEvidenceDTO `json:"indexes"`
|
||||
ForeignKeys []SCUMSchemaForeignKeyEvidenceDTO `json:"foreignKeys"`
|
||||
ApproximateRows *int64 `json:"approximateRows,omitempty"`
|
||||
SampleFingerprints []string `json:"sampleFingerprints,omitempty"`
|
||||
}
|
||||
|
||||
type SCUMSchemaProbeResultDTO struct {
|
||||
RequestID string `json:"requestId"`
|
||||
JobID string `json:"jobId"`
|
||||
Binding SCUMBindingIdentityDTO `json:"binding"`
|
||||
Status string `json:"status"`
|
||||
SchemaFingerprint string `json:"schemaFingerprint,omitempty"`
|
||||
ObservedAt time.Time `json:"observedAt"`
|
||||
ResultDigest string `json:"resultDigest,omitempty"`
|
||||
Objects []SCUMSchemaObjectEvidenceDTO `json:"objects,omitempty"`
|
||||
SafeError SCUMSafeErrorDTO `json:"safeError,omitempty"`
|
||||
Limits SCUMSchemaProbeBoundsDTO `json:"limits"`
|
||||
}
|
||||
|
||||
type SCUMCapabilityGateDTO struct {
|
||||
Capability string `json:"capability"`
|
||||
State string `json:"state"`
|
||||
Enabled bool `json:"enabled"`
|
||||
ReasonCode string `json:"reasonCode"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
func SCUMSchemaProbeRequestToDomain(value SCUMSchemaProbeRequestDTO) domain.SCUMSchemaProbeRequest {
|
||||
return domain.SCUMSchemaProbeRequest{RequestID: value.RequestID, JobID: value.JobID, Binding: scumBindingIdentityToDomain(value.Binding), Bounds: scumProbeBoundsToDomain(value.Bounds), RequestedAt: value.RequestedAt}
|
||||
}
|
||||
|
||||
func SCUMSchemaProbeResultFromDomain(value domain.SCUMSchemaProbeResult) SCUMSchemaProbeResultDTO {
|
||||
value = domain.CopySCUMSchemaProbeResult(value)
|
||||
objects := make([]SCUMSchemaObjectEvidenceDTO, len(value.Objects))
|
||||
for index, object := range value.Objects {
|
||||
columns := make([]SCUMSchemaColumnEvidenceDTO, len(object.DeclaredColumns))
|
||||
for i, column := range object.DeclaredColumns {
|
||||
columns[i] = SCUMSchemaColumnEvidenceDTO{NameFingerprint: column.NameFingerprint, DeclaredType: column.DeclaredType, Nullable: column.Nullable, PrimaryKey: column.PrimaryKey, Ordinal: column.Ordinal}
|
||||
}
|
||||
indexes := make([]SCUMSchemaIndexEvidenceDTO, len(object.Indexes))
|
||||
for i, item := range object.Indexes {
|
||||
indexes[i] = SCUMSchemaIndexEvidenceDTO{NameFingerprint: item.NameFingerprint, Unique: item.Unique, ColumnHashes: append([]string(nil), item.ColumnHashes...)}
|
||||
}
|
||||
foreignKeys := make([]SCUMSchemaForeignKeyEvidenceDTO, len(object.ForeignKeys))
|
||||
for i, item := range object.ForeignKeys {
|
||||
foreignKeys[i] = SCUMSchemaForeignKeyEvidenceDTO{FromColumnHash: item.FromColumnHash, ToObjectHash: item.ToObjectHash, ToColumnHash: item.ToColumnHash}
|
||||
}
|
||||
objects[index] = SCUMSchemaObjectEvidenceDTO{ObjectHash: object.ObjectHash, Kind: object.Kind, NameFingerprint: object.NameFingerprint, DeclaredColumns: columns, Indexes: indexes, ForeignKeys: foreignKeys, ApproximateRows: object.ApproximateRows, SampleFingerprints: append([]string(nil), object.SampleFingerprints...)}
|
||||
}
|
||||
return SCUMSchemaProbeResultDTO{RequestID: value.RequestID, JobID: value.JobID, Binding: scumBindingIdentityFromDomain(value.Binding), Status: string(value.Status), SchemaFingerprint: value.SchemaFingerprint, ObservedAt: value.ObservedAt, ResultDigest: value.ResultDigest, Objects: objects, SafeError: SCUMSafeErrorDTO{Code: string(value.SafeError.Code), Message: value.SafeError.Message, Retryable: value.SafeError.Retryable}, Limits: scumProbeBoundsFromDomain(value.Limits)}
|
||||
}
|
||||
|
||||
func SCUMCapabilityGateFromDomain(value domain.SCUMCapabilityGate) SCUMCapabilityGateDTO {
|
||||
return SCUMCapabilityGateDTO{Capability: string(value.Capability), State: string(value.State), Enabled: value.Enabled, ReasonCode: string(value.ReasonCode), Reason: value.Reason}
|
||||
}
|
||||
|
||||
func scumBindingIdentityToDomain(value SCUMBindingIdentityDTO) domain.SCUMBindingIdentity {
|
||||
return domain.SCUMBindingIdentity{ServerInstanceID: value.ServerInstanceID, RunBindingID: value.RunBindingID, RunEndpointID: value.RunEndpointID, PluginID: value.PluginID, PluginVersion: value.PluginVersion, AdapterVersion: value.AdapterVersion, GameVersion: value.GameVersion, DatabaseIdentity: value.DatabaseIdentity}
|
||||
}
|
||||
|
||||
func scumBindingIdentityFromDomain(value domain.SCUMBindingIdentity) SCUMBindingIdentityDTO {
|
||||
return SCUMBindingIdentityDTO{ServerInstanceID: value.ServerInstanceID, RunBindingID: value.RunBindingID, RunEndpointID: value.RunEndpointID, PluginID: value.PluginID, PluginVersion: value.PluginVersion, AdapterVersion: value.AdapterVersion, GameVersion: value.GameVersion, DatabaseIdentity: value.DatabaseIdentity}
|
||||
}
|
||||
|
||||
func scumProbeBoundsToDomain(value SCUMSchemaProbeBoundsDTO) domain.SCUMSchemaProbeBounds {
|
||||
return domain.SCUMSchemaProbeBounds{MaxObjects: value.MaxObjects, MaxColumnsPerObject: value.MaxColumnsPerObject, MaxIndexesPerObject: value.MaxIndexesPerObject, MaxForeignKeys: value.MaxForeignKeys, MaxCardinalityReads: value.MaxCardinalityReads, MaxSampleRows: value.MaxSampleRows, TimeoutMS: value.TimeoutMS, MaxResultBytes: value.MaxResultBytes}
|
||||
}
|
||||
|
||||
func scumProbeBoundsFromDomain(value domain.SCUMSchemaProbeBounds) SCUMSchemaProbeBoundsDTO {
|
||||
return SCUMSchemaProbeBoundsDTO{MaxObjects: value.MaxObjects, MaxColumnsPerObject: value.MaxColumnsPerObject, MaxIndexesPerObject: value.MaxIndexesPerObject, MaxForeignKeys: value.MaxForeignKeys, MaxCardinalityReads: value.MaxCardinalityReads, MaxSampleRows: value.MaxSampleRows, TimeoutMS: value.TimeoutMS, MaxResultBytes: value.MaxResultBytes}
|
||||
}
|
||||
Reference in New Issue
Block a user