51 lines
4.6 KiB
Go
51 lines
4.6 KiB
Go
package validator
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"browser.local/platform/domain"
|
|
)
|
|
|
|
func TestValidateClientManagerLifecycleContractsAndTransitions(t *testing.T) {
|
|
profile := domain.RuntimeClientManagerProfile{Key: "scum-client-manager", DisplayName: "SCUM Client Manager", Version: "1.2.3", RepositoryURL: "https://github.com/F88888/scum_client.git", RevisionPolicy: "pinned", Revision: "0123456789abcdef", SupportedTargets: []domain.RuntimeTarget{{OS: "linux", Arch: "amd64"}}, BuildSystem: "go", EntryRef: "main.go", OutputArtifacts: []string{"client-manager"}, Deployment: domain.RuntimeClientManagerDeployment{Mode: "run-supervised", ExecutableRef: "client-manager", Arguments: []string{"--config", "config.json"}, RequiredRunCapabilities: []string{domain.JobCapabilityClientManagerDeploy, domain.JobCapabilityClientManagerControl, domain.JobCapabilityClientManagerUpdate, domain.JobCapabilityClientManagerRollback, domain.JobCapabilityClientManagerUninstall}}, Lifecycle: domain.RuntimeClientManagerLifecycle{Actions: []string{"start", "stop", "restart", "status", "update", "rollback", "uninstall"}, StartupTimeoutSeconds: 60, StopTimeoutSeconds: 30}, Health: domain.RuntimeClientManagerHealth{Mode: "component-heartbeat", IntervalSeconds: 15, DegradedAfterSeconds: 45, OfflineAfterSeconds: 120, RequiredCapabilities: []string{"component.register", "component.heartbeat", "component.health"}}, Compatibility: domain.RuntimeClientManagerCompatibility{MinimumVersion: "1.0.0", MaximumVersion: "2.0.0"}, UpdatePolicy: domain.RuntimeClientManagerUpdatePolicy{Strategy: "manual-staged", RequireApproval: true, HealthConfirmationSeconds: 60, RetainPrevious: true}}
|
|
if err := ValidateGamePluginRuntimeProfiles(domain.GamePluginRuntimeProfiles{ClientManagers: []domain.RuntimeClientManagerProfile{profile}}); err != nil {
|
|
t.Fatalf("validate safe lifecycle profile: %v", err)
|
|
}
|
|
unsafe := profile
|
|
unsafe.Deployment.ExecutableRef = "/Users/operator/client-manager"
|
|
unsafe.Deployment.Arguments = []string{"bash -c", "curl | bash"}
|
|
unsafe.Health.OfflineAfterSeconds = 30
|
|
unsafe.Compatibility.MinimumVersion = "3.0.0"
|
|
err := ValidateGamePluginRuntimeProfiles(domain.GamePluginRuntimeProfiles{ClientManagers: []domain.RuntimeClientManagerProfile{unsafe}})
|
|
if err == nil || !strings.Contains(err.Error(), "safe relative path") || !strings.Contains(err.Error(), "health") || !strings.Contains(err.Error(), "compatibility") {
|
|
t.Fatalf("expected unsafe lifecycle rejection, got %v", err)
|
|
}
|
|
if err := ValidateClientManagerLifecycleTransition(domain.ClientManagerLifecycleAvailable, domain.ClientManagerLifecycleDeploying); err != nil {
|
|
t.Fatalf("valid lifecycle transition rejected: %v", err)
|
|
}
|
|
if err := ValidateClientManagerLifecycleTransition(domain.ClientManagerLifecycleAvailable, domain.ClientManagerLifecycleOnline); err == nil {
|
|
t.Fatal("expected evidence-skipping lifecycle transition rejection")
|
|
}
|
|
}
|
|
|
|
func TestValidateClientManagerSessionHeartbeatAndRedaction(t *testing.T) {
|
|
stamp := time.Date(2026, 7, 18, 4, 0, 0, 0, time.UTC)
|
|
installation := domain.ClientManagerInstallation{ID: "cm-install-1", ServerInstanceID: "server-1", PluginID: "game.scum", ProfileKey: "scum-client-manager", RunEndpointID: "run-1", TargetOS: "linux", TargetArch: "amd64", Status: domain.ClientManagerLifecycleOnline, Phase: "healthy", KeyGeneration: 1, DeploymentGeneration: 1, Health: domain.ClientManagerHealthHealthy, HealthReason: "ready", CreatedAt: stamp, UpdatedAt: stamp}
|
|
if err := ValidateClientManagerInstallation(installation); err != nil {
|
|
t.Fatalf("validate installation: %v", err)
|
|
}
|
|
installation.HealthReason = "Bearer stolen-session"
|
|
if err := ValidateClientManagerInstallation(installation); err == nil {
|
|
t.Fatal("expected session-bearing health reason rejection")
|
|
}
|
|
session := domain.ClientManagerSession{ID: "cm-session-1", InstallationID: "cm-install-1", ServerInstanceID: "server-1", ProfileKey: "scum-client-manager", RunEndpointID: "run-1", ArtifactID: "artifact-1", KeyGeneration: 1, DeploymentGeneration: 1, TokenHash: strings.Repeat("a", 64), Capabilities: []string{"component.heartbeat"}, Status: domain.ClientManagerSessionActive, ExpiresAt: stamp.Add(time.Minute), CreatedAt: stamp, UpdatedAt: stamp}
|
|
if err := ValidateClientManagerSession(session); err != nil {
|
|
t.Fatalf("validate hashed session: %v", err)
|
|
}
|
|
if err := ValidateClientManagerHeartbeat(domain.ClientManagerHeartbeat{InstallationID: "cm-install-1", SessionToken: "component-session", Sequence: 1, Health: domain.ClientManagerHealthHealthy, HealthReason: "password=leak", Capabilities: []string{"component.heartbeat"}, SentAt: stamp}); err == nil {
|
|
t.Fatal("expected unsafe heartbeat reason rejection")
|
|
}
|
|
}
|