Move SCUM lifecycle ownership to plugin

This commit is contained in:
npc0-hue
2026-08-01 09:36:12 +08:00
parent bca4f935ba
commit d1249fca85
49 changed files with 795 additions and 566 deletions
+1
View File
@@ -127,6 +127,7 @@ type DistributionBuildInput struct {
SecretRef string
KeyGeneration int
AuthKey string
WorkspaceSeed string
}
type DependencyExecutionInputRequest struct {
+23 -3
View File
@@ -582,8 +582,8 @@ type RuntimeServerPrerequisite struct {
Kind string
}
// RuntimeServerDeploymentProfile is a frozen, game-specific deployment
// template. It contains logical references only; Run resolves them locally.
// RuntimeServerDeploymentProfile is a legacy game-specific deployment template
// declaration kept for backward-compatible manifest decoding.
type RuntimeServerDeploymentProfile struct {
Key string
Version string
@@ -624,6 +624,7 @@ type GamePluginManifest struct {
Capabilities []string
Permissions []string
Actions PluginLifecycleActions
AssetFiles []PluginAssetFile
Pages []GamePluginPage
FileWorkspace PluginFileWorkspace
AI GamePluginManifestAI
@@ -637,6 +638,13 @@ type GamePluginManifest struct {
type GamePluginManifestRegistration struct {
ManifestRef string
Manifest GamePluginManifest
AssetFiles []PluginAssetFile
}
type PluginAssetFile struct {
Path string
Content string
Mode int
}
type GamePlugin struct {
@@ -654,6 +662,7 @@ type GamePlugin struct {
DeclaredPermissions []string
Permissions PluginPermissions
LifecycleActions PluginLifecycleActions
LifecycleAssets []PluginAssetFile
BridgeActions []string
Pages []GamePluginPage
FileWorkspace PluginFileWorkspace
@@ -1057,7 +1066,6 @@ const (
// JobCapabilityDeploymentPlan gates Run implementations that understand
// protected deployment definitions, absolute paths, and custom commands.
JobCapabilityDeploymentPlan = "deployment.plan.v1"
JobCapabilitySCUMDeploymentPlan = "deployment.scum.v1"
JobCapabilityDeploymentShellPosix = "deployment.shell.posix-sh"
JobCapabilityDeploymentShellPowerShell = "deployment.shell.powershell"
JobCapabilityDeploymentShellCmd = "deployment.shell.cmd"
@@ -1648,6 +1656,7 @@ func CopyGamePlugin(plugin GamePlugin) GamePlugin {
plugin.DeclaredPermissions = CopyStringSlice(plugin.DeclaredPermissions)
plugin.SupportedOS = CopyStringSlice(plugin.SupportedOS)
plugin.CreateFields = CopyPluginCreateFields(plugin.CreateFields)
plugin.LifecycleAssets = CopyPluginAssetFiles(plugin.LifecycleAssets)
plugin.BridgeActions = CopyStringSlice(plugin.BridgeActions)
plugin.Pages = CopyGamePluginPageSlice(plugin.Pages)
plugin.FileWorkspace = CopyPluginFileWorkspace(plugin.FileWorkspace)
@@ -1699,9 +1708,19 @@ func CopyPluginMarketplacePluginSlice(plugins []PluginMarketplacePlugin) []Plugi
func CopyGamePluginManifestRegistration(registration GamePluginManifestRegistration) GamePluginManifestRegistration {
registration.Manifest = CopyGamePluginManifest(registration.Manifest)
registration.AssetFiles = CopyPluginAssetFiles(registration.AssetFiles)
return registration
}
func CopyPluginAssetFiles(files []PluginAssetFile) []PluginAssetFile {
if files == nil {
return nil
}
out := make([]PluginAssetFile, len(files))
copy(out, files)
return out
}
func CopyGamePluginManifest(manifest GamePluginManifest) GamePluginManifest {
manifest.Tags = CopyStringSlice(manifest.Tags)
manifest.Server.SupportedOS = CopyStringSlice(manifest.Server.SupportedOS)
@@ -1709,6 +1728,7 @@ func CopyGamePluginManifest(manifest GamePluginManifest) GamePluginManifest {
manifest.Bridge.Actions = CopyStringSlice(manifest.Bridge.Actions)
manifest.Capabilities = CopyStringSlice(manifest.Capabilities)
manifest.Permissions = CopyStringSlice(manifest.Permissions)
manifest.AssetFiles = CopyPluginAssetFiles(manifest.AssetFiles)
manifest.Pages = CopyGamePluginPageSlice(manifest.Pages)
manifest.FileWorkspace = CopyPluginFileWorkspace(manifest.FileWorkspace)
manifest.AI.Purposes = CopyStringSlice(manifest.AI.Purposes)
+7 -6
View File
@@ -111,12 +111,13 @@ Run sessions persist only a token hash, generation, status, expiry, capability f
Installed `GamePlugin` records persist the validated manifest `runtimeProfiles` contract, including discovery, lifecycle, dependency/install, log, transport, and client-manager declarations. One server binding selects one declared lifecycle profile. Platform derives allowed and required logical keys; clients cannot assert `missingKeys` or `status`.
SCUM plugins may additionally declare `runtimeProfiles.serverDeployments`. These
profiles are versioned, freeze into a leased Run assignment, and contain only
logical executable/config markers, field mappings, discovery markers, and
verification checks. A server's `DeploymentProjection` stores bounded evidence
from Run for operator views; protected paths, commands, credentials, process
ids, and sockets never enter that projection.
Plugin lifecycle assets are registered as manifest-declared files plus a
content-bearing registration payload. Platform packages those assets into
generated Run workspaces so plugin action refs such as `actions/install.json`
and script refs such as `bin/scum-start.cmd` are available before the first
install/start job. Game-specific install/update/start policy, including SCUM
SteamCMD app IDs and launch flags, stays in the plugin asset bundle rather than
in platform services or Run executors.
Bindings are used for action gating and future run-side profile resolution. File and MySQL metadata snapshots include them so a platform restart does not make a configured server appear complete or lose its selected profile. API responses expose only logical key names, configured/secret-backed flags, missing keys, and safe reasons. They never expose stored binding values, raw host paths, direct sockets, FTP/RCON passwords, SQL DSNs, component auth keys, or internal secret locations.