feat: safely control Shell Target

This commit is contained in:
proxyctl coordinator
2026-07-17 02:59:41 +08:00
parent 4e3f780eba
commit 12e857932b
15 changed files with 1552 additions and 16 deletions
+48
View File
@@ -0,0 +1,48 @@
// Package target defines the application-facing seam implemented by configuration Targets.
package target
import (
"context"
"proxyctl/internal/profile"
)
// State is the detected state of a Target's actual configuration.
type State string
const (
Enabled State = "Enabled"
Disabled State = "Disabled"
External State = "External"
Drifted State = "Drifted"
)
type Description struct {
Name string
Summary string
Details string
}
type Availability struct {
Available bool
Evidence string
}
type Inspection struct {
State State
Evidence string
}
type OperationResult struct {
Inspection Inspection
Err error
}
// Target hides platform paths and commands from the application and TUI.
type Target interface {
ID() string
Description() Description
Availability(context.Context) Availability
Inspect(context.Context, *profile.Profile) Inspection
SetDesired(context.Context, bool, *profile.Profile) OperationResult
}
+32
View File
@@ -0,0 +1,32 @@
package target_test
import (
"context"
"testing"
"proxyctl/internal/profile"
"proxyctl/internal/target"
)
type seamTarget struct{}
func (seamTarget) ID() string { return "seam" }
func (seamTarget) Description() target.Description {
return target.Description{Name: "Seam", Summary: "summary", Details: "details"}
}
func (seamTarget) Availability(context.Context) target.Availability {
return target.Availability{Available: true, Evidence: "detected"}
}
func (seamTarget) Inspect(context.Context, *profile.Profile) target.Inspection {
return target.Inspection{State: target.Disabled, Evidence: "absent"}
}
func (seamTarget) SetDesired(context.Context, bool, *profile.Profile) target.OperationResult {
return target.OperationResult{Inspection: target.Inspection{State: target.Enabled}}
}
func TestSharedTargetInterfaceDoesNotExposePlatformDetails(t *testing.T) {
var adapter target.Target = seamTarget{}
if adapter.ID() != "seam" || !adapter.Availability(context.Background()).Available {
t.Fatal("Target seam did not expose expected domain behavior")
}
}
+95
View File
@@ -0,0 +1,95 @@
// Package targettest provides the common behavioral contract for real Target adapters.
package targettest
import (
"context"
"errors"
"os"
"strings"
"testing"
"proxyctl/internal/profile"
"proxyctl/internal/target"
)
// Fixture supplies adapter-specific host setup while assertions stay at the Target seam.
type Fixture struct {
Target target.Target
Active *profile.Profile
MakeExternal func(*testing.T)
MakeDrifted func(*testing.T)
PermissionFailure func(*testing.T) target.OperationResult
PartialFailure func(*testing.T) target.OperationResult
RedactionFailure func(*testing.T) target.OperationResult
Secret string
}
type Factory func(*testing.T) Fixture
// Run verifies the state and desired-state behavior shared by every adapter.
// Adapter suites add injected permission and partial-effect failures because their
// failure injection mechanisms necessarily differ.
func Run(t *testing.T, factory Factory) {
t.Helper()
t.Run("common Target contract", func(t *testing.T) {
fixture := factory(t)
ctx := context.Background()
if !fixture.Target.Availability(ctx).Available {
t.Fatal("Target fixture must be available")
}
if got := fixture.Target.Inspect(ctx, fixture.Active).State; got != target.Disabled {
t.Fatalf("initial state = %s, want Disabled", got)
}
if got := fixture.Target.SetDesired(ctx, true, nil); got.Err == nil || !strings.Contains(got.Err.Error(), "Profile management") {
t.Fatalf("nil Active Profile = %#v", got)
}
invalid := &profile.Profile{Name: "invalid", Mode: profile.SingleMode, SingleURL: "ftp://proxy.example:21"}
if got := fixture.Target.SetDesired(ctx, true, invalid); got.Err == nil || got.Inspection.State != target.Disabled {
t.Fatalf("validation failure = %#v", got)
}
if got := fixture.Target.SetDesired(ctx, true, fixture.Active); got.Err != nil || got.Inspection.State != target.Enabled {
t.Fatalf("enable = %#v", got)
}
if got := fixture.Target.SetDesired(ctx, true, fixture.Active); got.Err != nil || got.Inspection.State != target.Enabled {
t.Fatalf("idempotent enable = %#v", got)
}
fixture.MakeDrifted(t)
if got := fixture.Target.Inspect(ctx, fixture.Active).State; got != target.Drifted {
t.Fatalf("drift state = %s", got)
}
if got := fixture.Target.SetDesired(ctx, true, fixture.Active); got.Err != nil || got.Inspection.State != target.Enabled {
t.Fatalf("repair = %#v", got)
}
if got := fixture.Target.SetDesired(ctx, false, nil); got.Err != nil {
t.Fatalf("disable = %#v", got)
}
if got := fixture.Target.SetDesired(ctx, false, nil); got.Err != nil {
t.Fatalf("idempotent disable = %#v", got)
}
external := factory(t)
external.MakeExternal(t)
if got := external.Target.Inspect(ctx, external.Active).State; got != target.External {
t.Fatalf("external state = %s", got)
}
if got := external.Target.SetDesired(ctx, true, external.Active); got.Err != nil {
t.Fatalf("enable over External = %#v", got)
}
if got := external.Target.SetDesired(ctx, false, nil); got.Err != nil || got.Inspection.State != target.External {
t.Fatalf("restore External = %#v", got)
}
permission := fixture.PermissionFailure(t)
if permission.Err == nil || !errors.Is(permission.Err, os.ErrPermission) || permission.Inspection.State != target.Disabled {
t.Fatalf("permission failure = %#v", permission)
}
partial := fixture.PartialFailure(t)
if partial.Err == nil || partial.Inspection.State != target.External {
t.Fatalf("partial failure = %#v", partial)
}
redacted := fixture.RedactionFailure(t)
if redacted.Err == nil || fixture.Secret == "" || strings.Contains(redacted.Err.Error(), fixture.Secret) {
t.Fatalf("secret was not redacted: %#v", redacted)
}
})
}