功能修改

This commit is contained in:
npc0-hue
2026-07-20 16:42:33 +08:00
parent 48b8ad8d6c
commit a0e69417db
224 changed files with 22015 additions and 884 deletions
@@ -0,0 +1,131 @@
package service
import (
"strings"
"testing"
"browser.local/platform/domain"
)
func TestClientManagerLifecycleInputIncludesGeneratedCompanionConfig(t *testing.T) {
svc, ownerSession, instance := newDistributionTestFixture(t)
plugin, err := svc.store.GamePlugins().Get(instance.PluginID)
if err != nil {
t.Fatalf("get plugin: %v", err)
}
capabilities := []string{"component.register", "component.heartbeat", "component.health", "component.control", "game-client.bridge", "logs.stream"}
for index := range plugin.RuntimeProfiles.ClientManagers {
manager := &plugin.RuntimeProfiles.ClientManagers[index]
if manager.Key != "scum-client-manager" {
continue
}
manager.ConfigTemplates = []domain.RuntimeConfigTemplate{{Key: "client-config", TemplateRef: "config.yaml.example", OutputRef: "config.yaml"}}
manager.Health.IntervalSeconds = 30
manager.Health.RequiredCapabilities = domain.CopyStringSlice(capabilities)
}
plugin.GameClientBridge.Companion = domain.GameClientBridgeCompanionDeclaration{
ProfileKey: "scum-client-manager",
ConfigTemplateKey: "client-config",
ConfigSchemaRef: "schemas/companion/config.schema.json",
ConfigFormat: "yaml",
PlatformBaseURLSource: "run-control",
RegistrationProof: "hmac-sha256",
ProofMaterialSource: "component-package",
ProofMaterialEnv: "SCUM_COMPONENT_PROOF",
SessionMode: "component-session",
TLSPolicy: "verify-system-roots",
HeartbeatIntervalSeconds: 30,
CommandPollIntervalSeconds: 5,
RequestTimeoutSeconds: 15,
}
if err := svc.store.GamePlugins().Update(plugin); err != nil {
t.Fatalf("update companion declaration: %v", err)
}
distribution := buildLifecycleDistribution(t, svc, ownerSession, instance, "1.0.0", "companion-config-build-v1")
view, err := svc.DeployClientManagerForSession(ownerSession, domain.ClientManagerDeployRequest{ServerInstanceID: instance.ID, ProfileKey: "scum-client-manager", DistributionID: distribution.ID, IdempotencyKey: "companion-config-deploy-v1"})
if err != nil {
t.Fatalf("queue companion deployment: %v", err)
}
runSession := registerClientManagerRun(t, svc)
claim := claimClientManagerJob(t, svc, runSession, domain.JobCapabilityClientManagerDeploy)
request := domain.ClientManagerLifecycleInputRequest{RunEndpointID: instance.RunEndpointID, SessionToken: runSession, JobID: claim.Job.JobID, LeaseToken: claim.Job.LeaseToken, Attempt: claim.Job.Attempt}
input, err := svc.GetClientManagerLifecycleInput(request)
if err != nil {
t.Fatalf("get companion lifecycle input: %v", err)
}
config := input.CompanionConfig
if config == nil {
t.Fatal("expected generated companion config input")
}
if config.SchemaVersion != 1 || config.ConfigTemplateRef != "config.yaml.example" || config.ConfigOutputRef != "config.yaml" || config.ConfigSchemaRef != "schemas/companion/config.schema.json" {
t.Fatalf("unexpected companion template contract: %+v", config)
}
if config.InstallationID != view.Installation.ID || config.ServerInstanceID != instance.ID || config.PluginID != plugin.ID || config.ProfileKey != "scum-client-manager" || config.ArtifactID != distribution.ArtifactID || config.KeyGeneration != distribution.KeyGeneration || config.DeploymentGeneration != view.Installation.DeploymentGeneration {
t.Fatalf("unexpected companion identity fence: %+v", config)
}
if strings.Join(config.Capabilities, ",") != strings.Join(capabilities, ",") || config.PlatformBaseURLSource != "run-control" || config.RegistrationProof != "hmac-sha256" || config.ProofMaterialEnv != "SCUM_COMPONENT_PROOF" || config.SessionMode != "component-session" || config.TLSPolicy != "verify-system-roots" {
t.Fatalf("unexpected companion registration policy: %+v", config)
}
if config.HeartbeatIntervalSeconds != 30 || config.CommandPollIntervalSeconds != 5 || config.RequestTimeoutSeconds != 15 {
t.Fatalf("unexpected companion timing policy: %+v", config)
}
plugin, err = svc.store.GamePlugins().Get(instance.PluginID)
if err != nil {
t.Fatalf("reload plugin: %v", err)
}
plugin.GameClientBridge.Companion.TLSPolicy = "skip-verification"
if err := svc.store.GamePlugins().Update(plugin); err != nil {
t.Fatalf("persist unsafe companion policy: %v", err)
}
if _, err := svc.GetClientManagerLifecycleInput(request); err == nil || !strings.Contains(err.Error(), "security policy") {
t.Fatalf("expected unsafe persisted policy to fail closed, got %v", err)
}
plugin.GameClientBridge.Companion.TLSPolicy = "verify-system-roots"
plugin.GameClientBridge.Companion.ProofMaterialEnv = "LD_PRELOAD"
if err := svc.store.GamePlugins().Update(plugin); err != nil {
t.Fatalf("persist reserved proof environment: %v", err)
}
if _, err := svc.GetClientManagerLifecycleInput(request); err == nil || !strings.Contains(err.Error(), "proofMaterialEnv") {
t.Fatalf("expected reserved proof environment to fail closed, got %v", err)
}
plugin.GameClientBridge.Companion.ProofMaterialEnv = "SCUM_COMPONENT_PROOF"
for index := range plugin.RuntimeProfiles.ClientManagers {
plugin.RuntimeProfiles.ClientManagers[index].ConfigTemplates = nil
}
if err := svc.store.GamePlugins().Update(plugin); err != nil {
t.Fatalf("remove config template: %v", err)
}
if _, err := svc.GetClientManagerLifecycleInput(request); err == nil || !strings.Contains(err.Error(), "config template") {
t.Fatalf("expected missing template to fail safely, got %v", err)
}
}
func TestClientManagerCompanionConfigInputIsOptionalForOtherProfiles(t *testing.T) {
config, err := clientManagerCompanionConfigInput(
domain.GamePlugin{ID: "game.example", GameClientBridge: domain.GameClientBridgeManifest{Companion: domain.GameClientBridgeCompanionDeclaration{ProfileKey: "bridge-client"}}},
domain.RuntimeClientManagerProfile{Key: "metrics-client"},
domain.ClientManagerInstallation{ProfileKey: "metrics-client"},
"artifact-1",
"1.0.0",
"revision-1",
)
if err != nil || config != nil {
t.Fatalf("expected no companion config for another profile, config=%+v err=%v", config, err)
}
config, err = clientManagerCompanionConfigInput(
domain.GamePlugin{ID: "game.example", GameClientBridge: domain.GameClientBridgeManifest{Companion: domain.GameClientBridgeCompanionDeclaration{ConfigFormat: "yaml"}}},
domain.RuntimeClientManagerProfile{Key: "metrics-client"},
domain.ClientManagerInstallation{ProfileKey: "metrics-client"},
"artifact-1",
"1.0.0",
"revision-1",
)
if err == nil || config != nil || !strings.Contains(err.Error(), "incomplete") {
t.Fatalf("expected partial companion declaration to fail closed, config=%+v err=%v", config, err)
}
}