package domain import "time" type SCUMDataCapability string const ( SCUMDataCapabilitySchemaProbe SCUMDataCapability = "schema-probe" SCUMDataCapabilityPlayerRead SCUMDataCapability = "players.read" SCUMDataCapabilityPlayerDetailRead SCUMDataCapability = "player-details.read" SCUMDataCapabilitySquadRead SCUMDataCapability = "squads.read" SCUMDataCapabilitySquadMemberRead SCUMDataCapability = "squad-members.read" SCUMDataCapabilityVehicleRead SCUMDataCapability = "vehicles.read" SCUMDataCapabilityFlagRead SCUMDataCapability = "flags.read" SCUMDataCapabilityPositionRead SCUMDataCapability = "positions.read" SCUMDataCapabilityProfileXMLWrite SCUMDataCapability = "profile-xml.write" SCUMDataCapabilityEconomyCommand SCUMDataCapability = "economy-command.write" SCUMDataCapabilityGiftCommand SCUMDataCapability = "gift-command.write" ) type SCUMCapabilityEvidenceStatus string const ( SCUMSchemaProbeStatusSucceeded SCUMCapabilityEvidenceStatus = "succeeded" SCUMCapabilityEvidenceMissing SCUMCapabilityEvidenceStatus = "missing" SCUMCapabilityEvidenceCompatible SCUMCapabilityEvidenceStatus = "compatible" SCUMCapabilityEvidenceIncompatible SCUMCapabilityEvidenceStatus = "incompatible" SCUMCapabilityEvidenceFailed SCUMCapabilityEvidenceStatus = "failed" ) type SCUMCapabilityGateState string const ( SCUMCapabilityGateEnabled SCUMCapabilityGateState = "enabled" SCUMCapabilityGateDisabled SCUMCapabilityGateState = "disabled" ) type SCUMSafeErrorCode string const ( SCUMSafeErrorNone SCUMSafeErrorCode = "none" SCUMSafeErrorProbeExecutorAbsent SCUMSafeErrorCode = "probe_executor_absent" SCUMSafeErrorProbeMissing SCUMSafeErrorCode = "probe_missing" SCUMSafeErrorProbeFailed SCUMSafeErrorCode = "probe_failed" SCUMSafeErrorSchemaIncompatible SCUMSafeErrorCode = "schema_incompatible" SCUMSafeErrorBindingMismatch SCUMSafeErrorCode = "binding_mismatch" SCUMSafeErrorAdapterMismatch SCUMSafeErrorCode = "adapter_mismatch" SCUMSafeErrorFingerprintMismatch SCUMSafeErrorCode = "fingerprint_mismatch" SCUMSafeErrorDigestMismatch SCUMSafeErrorCode = "digest_mismatch" SCUMSafeErrorEvidenceExpired SCUMSafeErrorCode = "evidence_expired" SCUMSafeErrorInvalidProbePayload SCUMSafeErrorCode = "invalid_probe_payload" SCUMSafeErrorInvalidRequest SCUMSafeErrorCode = "invalid_request" SCUMSafeErrorTargetUnavailable SCUMSafeErrorCode = "target_unavailable" SCUMSafeErrorSourceUnavailable SCUMSafeErrorCode = "source_unavailable" SCUMSafeErrorSQLiteOpenFailed SCUMSafeErrorCode = "sqlite_open_failed" SCUMSafeErrorSQLiteReadFailed SCUMSafeErrorCode = "sqlite_read_failed" SCUMSafeErrorDatabaseBusy SCUMSafeErrorCode = "database_busy" SCUMSafeErrorTimeout SCUMSafeErrorCode = "timeout" SCUMSafeErrorCancelled SCUMSafeErrorCode = "cancelled" SCUMSafeErrorSourceChanged SCUMSafeErrorCode = "source_changed" SCUMSafeErrorResultLimitExceeded SCUMSafeErrorCode = "result_limit_exceeded" SCUMSafeErrorTemplateMissing SCUMSafeErrorCode = "template_missing" SCUMSafeErrorTemplateMismatch SCUMSafeErrorCode = "template_digest_mismatch" SCUMSafeErrorParameterInvalid SCUMSafeErrorCode = "parameter_schema_invalid" SCUMSafeErrorRowLimitExceeded SCUMSafeErrorCode = "row_limit_exceeded" SCUMSafeErrorResultSchemaInvalid SCUMSafeErrorCode = "result_schema_invalid" SCUMSafeErrorMutationGuardMismatch SCUMSafeErrorCode = "mutation_guard_mismatch" SCUMSafeErrorMutationBackupUnavailable SCUMSafeErrorCode = "mutation_backup_unavailable" SCUMSafeErrorMutationOfflineRequired SCUMSafeErrorCode = "mutation_offline_required" SCUMSafeErrorMutationConfirmationMissing SCUMSafeErrorCode = "mutation_confirmation_missing" SCUMSafeErrorMutationPatchInvalid SCUMSafeErrorCode = "mutation_patch_invalid" SCUMSafeErrorAffectedRowsMismatch SCUMSafeErrorCode = "affected_rows_mismatch" SCUMSafeErrorReadbackMismatch SCUMSafeErrorCode = "readback_mismatch" SCUMSafeErrorRollbackFailed SCUMSafeErrorCode = "rollback_failed" ) type SCUMTerminalResultStatus string const ( SCUMTerminalResultSucceeded SCUMTerminalResultStatus = "succeeded" SCUMTerminalResultFailed SCUMTerminalResultStatus = "failed" SCUMTerminalResultCancelled SCUMTerminalResultStatus = "cancelled" ) type SCUMRCONConfirmationStatus string const ( SCUMRCONConfirmationConfirmed SCUMRCONConfirmationStatus = "confirmed" SCUMRCONConfirmationFailed SCUMRCONConfirmationStatus = "failed" SCUMRCONConfirmationUnknown SCUMRCONConfirmationStatus = "unknown" ) type SCUMMutationReadbackStatus string const ( SCUMMutationReadbackConfirmed SCUMMutationReadbackStatus = "confirmed" SCUMMutationReadbackFailed SCUMMutationReadbackStatus = "failed" SCUMMutationReadbackConflict SCUMMutationReadbackStatus = "conflict" SCUMMutationReadbackUnknown SCUMMutationReadbackStatus = "unknown" ) type SCUMSafeError struct { Code SCUMSafeErrorCode Message string Retryable bool } type SCUMBindingIdentity struct { ServerInstanceID string RunBindingID string RunEndpointID string PluginID string PluginVersion string AdapterVersion string GameVersion string DatabaseIdentity string } type SCUMSchemaProbeBounds struct { MaxObjects int MaxColumnsPerObject int MaxIndexesPerObject int MaxForeignKeys int MaxCardinalityReads int MaxSampleRows int TimeoutMS int MaxResultBytes int } func DefaultSCUMSchemaProbeBounds() SCUMSchemaProbeBounds { return SCUMSchemaProbeBounds{MaxObjects: 256, MaxColumnsPerObject: 128, MaxIndexesPerObject: 64, MaxForeignKeys: 64, MaxCardinalityReads: 64, MaxSampleRows: 3, TimeoutMS: 5000, MaxResultBytes: 512 * 1024} } type SCUMSQLiteTemplateBounds struct { MaxParameters int MaxRows int TimeoutMS int BusyTimeoutMS int MaxResultBytes int } func DefaultSCUMSQLiteTemplateBounds() SCUMSQLiteTemplateBounds { return SCUMSQLiteTemplateBounds{MaxParameters: 64, MaxRows: 500, TimeoutMS: 5000, BusyTimeoutMS: 250, MaxResultBytes: 1024 * 1024} } type SCUMTypedRCONTemplateBounds struct { MaxPayloadBytes int TimeoutMS int MaxResponseBytes int MaxConfirmRecords int } func DefaultSCUMTypedRCONTemplateBounds() SCUMTypedRCONTemplateBounds { return SCUMTypedRCONTemplateBounds{MaxPayloadBytes: 2048, TimeoutMS: 5000, MaxResponseBytes: 16 * 1024, MaxConfirmRecords: 16} } type SCUMGuardedMutationBounds struct { MaxPayloadBytes int TimeoutMS int BusyTimeoutMS int MaxReadbackBytes int MaxAffectedRows int } func DefaultSCUMGuardedMutationBounds() SCUMGuardedMutationBounds { return SCUMGuardedMutationBounds{MaxPayloadBytes: 4096, TimeoutMS: 5000, BusyTimeoutMS: 250, MaxReadbackBytes: 16 * 1024, MaxAffectedRows: 1} } type SCUMParsedLogBatchBounds struct { MaxEvents int MaxPayloadBytes int MaxLineBytes int MaxResultBytes int } func DefaultSCUMParsedLogBatchBounds() SCUMParsedLogBatchBounds { return SCUMParsedLogBatchBounds{MaxEvents: 256, MaxPayloadBytes: 16 * 1024, MaxLineBytes: 4096, MaxResultBytes: 256 * 1024} } type SCUMLogTailState string const ( SCUMLogTailAdvanced SCUMLogTailState = "advanced" SCUMLogTailRotated SCUMLogTailState = "rotated" SCUMLogTailTruncated SCUMLogTailState = "truncated" SCUMLogTailRestarted SCUMLogTailState = "restarted" SCUMLogTailPartial SCUMLogTailState = "partial-buffered" SCUMLogTailReplayed SCUMLogTailState = "replayed" ) type SCUMParsedLogCursor struct { SourceIdentityDigest string StreamGeneration string Sequence uint64 } type SCUMParsedLogEvent struct { EventType string OccurredAt time.Time Cursor SCUMParsedLogCursor LogicalEventDigest string EventDigest string PayloadDigest string Payload map[string]any } type SCUMSchemaProbeRequest struct { RequestID string JobID string Binding SCUMBindingIdentity Bounds SCUMSchemaProbeBounds RequestedAt time.Time } type SCUMSQLiteTemplateRequest struct { RequestID string JobID string Binding SCUMBindingIdentity Capability SCUMDataCapability TargetKey string TemplateKey string AdapterVersion string RequiredSchemaFingerprint string AssetDigest string ParameterDigest string Parameters map[string]any Bounds SCUMSQLiteTemplateBounds RequestedAt time.Time } type SCUMTypedRCONTemplateRequest struct { RequestID string JobID string Binding SCUMBindingIdentity Capability SCUMDataCapability TransportKey string TargetKey string TemplateKey string AdapterVersion string RequiredSchemaFingerprint string AssetDigest string PayloadDigest string ConfirmationDigest string TargetIdentityDigest string IdempotencyKey string Payload map[string]any ReviewReason string Bounds SCUMTypedRCONTemplateBounds RequestedAt time.Time } type SCUMGuardedMutationRequest struct { RequestID string JobID string Binding SCUMBindingIdentity Capability SCUMDataCapability TargetKey string TemplateKey string AdapterVersion string RequiredSchemaFingerprint string AssetDigest string TargetIdentityDigest string ExpectedRowDigest string ExpectedValueDigest string ExpectedXMLDigest string PatchDigest string BackupEvidenceDigest string OfflineEvidenceDigest string DangerConfirmationDigest string ReadbackExpectationDigest string IdempotencyKey string Payload map[string]any ReviewReason string Bounds SCUMGuardedMutationBounds RequestedAt time.Time } type SCUMSchemaProbeDeclaration struct { Capability string TargetKey string Bounds SCUMSchemaProbeBounds } type SCUMLiveDataCapabilityGateDeclaration struct { Capability SCUMDataCapability Gate SCUMCapabilityGateState AdapterVersion string RequiredSchemaFingerprint string RequiredAssetDigests []string EvidenceStatus SCUMCapabilityEvidenceStatus SafeReason string } type SCUMLiveDataManifest struct { SchemaVersion string Probe SCUMSchemaProbeDeclaration CapabilityGates []SCUMLiveDataCapabilityGateDeclaration } type SCUMSchemaColumnEvidence struct { NameFingerprint string DeclaredType string Nullable *bool PrimaryKey bool Ordinal int } type SCUMSchemaIndexEvidence struct { NameFingerprint string Unique bool ColumnHashes []string } type SCUMSchemaForeignKeyEvidence struct { FromColumnHash string ToObjectHash string ToColumnHash string } type SCUMSchemaObjectEvidence struct { ObjectHash string Kind string NameFingerprint string DeclaredColumns []SCUMSchemaColumnEvidence Indexes []SCUMSchemaIndexEvidence ForeignKeys []SCUMSchemaForeignKeyEvidence ApproximateRows *int64 SampleFingerprints []string } type SCUMSchemaProbeResult struct { RequestID string JobID string Binding SCUMBindingIdentity Status SCUMCapabilityEvidenceStatus SourceFingerprint string SchemaFingerprint string ObservedAt time.Time ResultDigest string Objects []SCUMSchemaObjectEvidence SafeError SCUMSafeError Limits SCUMSchemaProbeBounds } type SCUMSQLiteTemplateResult struct { RequestID string JobID string Binding SCUMBindingIdentity Status SCUMTerminalResultStatus Capability SCUMDataCapability TargetKey string TemplateKey string AdapterVersion string SchemaFingerprint string AssetDigest string ParameterDigest string SourceFingerprint string ObservedAt time.Time ResultDigest string RowCount int Rows []map[string]any Truncated bool SafeError SCUMSafeError Limits SCUMSQLiteTemplateBounds } type SCUMTypedRCONTemplateResult struct { RequestID string JobID string Binding SCUMBindingIdentity Status SCUMTerminalResultStatus Capability SCUMDataCapability TransportKey string TargetKey string TemplateKey string AdapterVersion string SchemaFingerprint string AssetDigest string PayloadDigest string ConfirmationDigest string TargetIdentityDigest string ObservedAt time.Time ResultDigest string ResponseDigest string ConfirmationStatus SCUMRCONConfirmationStatus ConfirmationDigestID string SafeSummary string SafeError SCUMSafeError Limits SCUMTypedRCONTemplateBounds } type SCUMGuardedMutationResult struct { RequestID string JobID string Binding SCUMBindingIdentity Status SCUMTerminalResultStatus Capability SCUMDataCapability TargetKey string TemplateKey string AdapterVersion string SchemaFingerprint string AssetDigest string SourceFingerprint string TargetIdentityDigest string ExpectedRowDigest string ExpectedValueDigest string ExpectedXMLDigest string PatchDigest string BackupEvidenceDigest string OfflineEvidenceDigest string DangerConfirmationDigest string ReadbackExpectationDigest string ObservedAt time.Time ResultDigest string BeforeDigest string AfterDigest string ReadbackDigest string AffectedRows int ReadbackStatus SCUMMutationReadbackStatus SafeSummary string SafeError SCUMSafeError Limits SCUMGuardedMutationBounds } type SCUMParsedLogBatchResult struct { RequestID string JobID string Binding SCUMBindingIdentity Status SCUMTerminalResultStatus SourceKey string StreamKey string ParserKey string ParserVersion string AdapterVersion string AssetDigest string ParserDigest string ObservedAt time.Time ResultDigest string FirstCursor SCUMParsedLogCursor LastCursor SCUMParsedLogCursor TailState SCUMLogTailState PartialLineBuffered bool Replay bool EventCount int Events []SCUMParsedLogEvent SafeSummary string SafeError SCUMSafeError Limits SCUMParsedLogBatchBounds } type SCUMCapabilityRequirement struct { Capability SCUMDataCapability AdapterVersion string SchemaFingerprint string AssetDigests []string } type SCUMCapabilityEvidence struct { Capability SCUMDataCapability Status SCUMCapabilityEvidenceStatus Binding SCUMBindingIdentity AdapterVersion string SchemaFingerprint string ProbeResultDigest string AssetDigests []string ObservedAt time.Time ExpiresAt time.Time SafeError SCUMSafeError } type SCUMCapabilityGate struct { Capability SCUMDataCapability State SCUMCapabilityGateState Enabled bool ReasonCode SCUMSafeErrorCode Reason string Evidence SCUMCapabilityEvidence } func EvaluateSCUMCapabilityGate(requirement SCUMCapabilityRequirement, evidence SCUMCapabilityEvidence, active SCUMBindingIdentity, probeExecutorAvailable bool, now time.Time) SCUMCapabilityGate { gate := SCUMCapabilityGate{Capability: requirement.Capability, State: SCUMCapabilityGateDisabled, ReasonCode: SCUMSafeErrorProbeMissing, Reason: "current-service evidence is required before this SCUM capability can run"} if !probeExecutorAvailable { gate.ReasonCode = SCUMSafeErrorProbeExecutorAbsent gate.Reason = "bound Run does not expose the generic SQLite schema-probe executor" return gate } if evidence.Status == SCUMCapabilityEvidenceMissing || evidence.Capability == "" { return gate } gate.Evidence = CopySCUMCapabilityEvidence(evidence) if evidence.Status == SCUMCapabilityEvidenceFailed { gate.ReasonCode = SCUMSafeErrorProbeFailed gate.Reason = safeReason(evidence.SafeError.Message, "last schema probe failed") return gate } if evidence.Status == SCUMCapabilityEvidenceIncompatible { gate.ReasonCode = SCUMSafeErrorSchemaIncompatible gate.Reason = safeReason(evidence.SafeError.Message, "current schema is incompatible with the plugin adapter") return gate } if evidence.Capability != requirement.Capability { gate.ReasonCode = SCUMSafeErrorSchemaIncompatible gate.Reason = "capability evidence does not match the requested SCUM capability" return gate } if !sameSCUMBinding(evidence.Binding, active) { gate.ReasonCode = SCUMSafeErrorBindingMismatch gate.Reason = "evidence belongs to a different server, Run binding, plugin, adapter, game, or database identity" return gate } if evidence.AdapterVersion != requirement.AdapterVersion { gate.ReasonCode = SCUMSafeErrorAdapterMismatch gate.Reason = "evidence adapter version does not match the plugin requirement" return gate } if evidence.SchemaFingerprint == "" || evidence.SchemaFingerprint != requirement.SchemaFingerprint { gate.ReasonCode = SCUMSafeErrorFingerprintMismatch gate.Reason = "schema fingerprint does not match the plugin requirement" return gate } if !containsAllStrings(evidence.AssetDigests, requirement.AssetDigests) { gate.ReasonCode = SCUMSafeErrorDigestMismatch gate.Reason = "packaged asset digest does not match the compatible evidence" return gate } if !evidence.ExpiresAt.IsZero() && !now.IsZero() && !now.Before(evidence.ExpiresAt) { gate.ReasonCode = SCUMSafeErrorEvidenceExpired gate.Reason = "current-service evidence has expired and must be probed again" return gate } gate.State = SCUMCapabilityGateEnabled gate.Enabled = true gate.ReasonCode = SCUMSafeErrorNone gate.Reason = "current-service evidence matches the versioned plugin adapter" return gate } func CopySCUMCapabilityEvidence(value SCUMCapabilityEvidence) SCUMCapabilityEvidence { value.AssetDigests = append([]string(nil), value.AssetDigests...) return value } func CopySCUMSQLiteTemplateRequestPtr(value *SCUMSQLiteTemplateRequest) *SCUMSQLiteTemplateRequest { if value == nil { return nil } copy := *value copy.Parameters = CopySCUMValueMap(value.Parameters) return © } func CopySCUMTypedRCONTemplateRequestPtr(value *SCUMTypedRCONTemplateRequest) *SCUMTypedRCONTemplateRequest { if value == nil { return nil } copy := *value copy.Payload = CopySCUMValueMap(value.Payload) return © } func CopySCUMGuardedMutationRequestPtr(value *SCUMGuardedMutationRequest) *SCUMGuardedMutationRequest { if value == nil { return nil } copy := *value copy.Payload = CopySCUMValueMap(value.Payload) return © } func CopySCUMSQLiteTemplateResultPtr(value *SCUMSQLiteTemplateResult) *SCUMSQLiteTemplateResult { if value == nil { return nil } copy := *value copy.Rows = CopySCUMRows(value.Rows) return © } func CopySCUMTypedRCONTemplateResultPtr(value *SCUMTypedRCONTemplateResult) *SCUMTypedRCONTemplateResult { if value == nil { return nil } copy := *value return © } func CopySCUMGuardedMutationResultPtr(value *SCUMGuardedMutationResult) *SCUMGuardedMutationResult { if value == nil { return nil } copy := *value return © } func CopySCUMParsedLogBatchResultPtr(value *SCUMParsedLogBatchResult) *SCUMParsedLogBatchResult { if value == nil { return nil } copy := *value copy.Events = CopySCUMParsedLogEvents(value.Events) return © } func CopySCUMParsedLogEvents(events []SCUMParsedLogEvent) []SCUMParsedLogEvent { if events == nil { return nil } copy := make([]SCUMParsedLogEvent, len(events)) for index, event := range events { copy[index] = event copy[index].Payload = CopySCUMValueMap(event.Payload) } return copy } func CopySCUMValueMap(value map[string]any) map[string]any { if value == nil { return nil } copy := make(map[string]any, len(value)) for key, item := range value { copy[key] = item } return copy } func CopySCUMRows(rows []map[string]any) []map[string]any { if rows == nil { return nil } copy := make([]map[string]any, len(rows)) for index, row := range rows { copy[index] = CopySCUMValueMap(row) } return copy } func CopySCUMSchemaProbeResult(value SCUMSchemaProbeResult) SCUMSchemaProbeResult { value.Objects = append([]SCUMSchemaObjectEvidence(nil), value.Objects...) for index := range value.Objects { value.Objects[index].DeclaredColumns = append([]SCUMSchemaColumnEvidence(nil), value.Objects[index].DeclaredColumns...) value.Objects[index].Indexes = append([]SCUMSchemaIndexEvidence(nil), value.Objects[index].Indexes...) value.Objects[index].ForeignKeys = append([]SCUMSchemaForeignKeyEvidence(nil), value.Objects[index].ForeignKeys...) value.Objects[index].SampleFingerprints = append([]string(nil), value.Objects[index].SampleFingerprints...) for idx := range value.Objects[index].Indexes { value.Objects[index].Indexes[idx].ColumnHashes = append([]string(nil), value.Objects[index].Indexes[idx].ColumnHashes...) } } return value } func CopySCUMSchemaProbeRequestPtr(value *SCUMSchemaProbeRequest) *SCUMSchemaProbeRequest { if value == nil { return nil } copy := *value return © } func CopySCUMSchemaProbeResultPtr(value *SCUMSchemaProbeResult) *SCUMSchemaProbeResult { if value == nil { return nil } copy := CopySCUMSchemaProbeResult(*value) return © } func CopySCUMLiveDataManifest(value SCUMLiveDataManifest) SCUMLiveDataManifest { value.CapabilityGates = append([]SCUMLiveDataCapabilityGateDeclaration(nil), value.CapabilityGates...) for index := range value.CapabilityGates { value.CapabilityGates[index].RequiredAssetDigests = append([]string(nil), value.CapabilityGates[index].RequiredAssetDigests...) } return value } func sameSCUMBinding(a SCUMBindingIdentity, b SCUMBindingIdentity) bool { return a.ServerInstanceID == b.ServerInstanceID && a.RunBindingID == b.RunBindingID && a.RunEndpointID == b.RunEndpointID && a.PluginID == b.PluginID && a.PluginVersion == b.PluginVersion && a.AdapterVersion == b.AdapterVersion && a.GameVersion == b.GameVersion && a.DatabaseIdentity == b.DatabaseIdentity } func containsAllStrings(values []string, required []string) bool { set := map[string]struct{}{} for _, value := range values { set[value] = struct{}{} } for _, value := range required { if _, ok := set[value]; !ok { return false } } return true } func safeReason(value string, fallback string) string { if value == "" { return fallback } return value }