feat: complete Windows client control and recovery paths

This commit is contained in:
2026-09-06 13:37:32 +00:00
parent 56b15c7f4f
commit 486894557d
38 changed files with 2188 additions and 106 deletions
+72 -6
View File
@@ -17,6 +17,29 @@ var (
ErrUnsupported = errors.New("supervisor operation is unsupported")
)
// StartError carries durable context-selection evidence when a command is
// rejected before a process exists. The runtime records the evidence with
// the rejection event without treating the error as a second public protocol
// type. Unwrap keeps ordinary retry/error classification working.
type StartError struct {
Cause error
WindowsIdentity *rvboxv1.WindowsExecutionIdentity
}
func (err *StartError) Error() string {
if err == nil || err.Cause == nil {
return "supervisor start failed"
}
return err.Cause.Error()
}
func (err *StartError) Unwrap() error {
if err == nil {
return nil
}
return err.Cause
}
type SignalKind uint8
const (
@@ -53,12 +76,55 @@ func (spec StartSpec) Validate() error {
// EffectiveIdentity is immutable process evidence captured before launch.
// Empty user/session fields mean a Session 0 service context.
type EffectiveIdentity struct {
Context string
SessionID uint32
UserSID string
LogonSID string
Elevated bool
Integrity string
Context string
SessionID uint32
SessionUserSID string
UserSID string
LogonSID string
Elevated bool
Integrity string
AttemptedContexts []string
SelectionDetail string
}
// WindowsIdentity converts the platform-neutral evidence to the public
// immutable status/event shape. Unknown contexts are deliberately omitted so
// the portable test supervisor never pretends to be a Windows launch.
func (identity EffectiveIdentity) WindowsIdentity() *rvboxv1.WindowsExecutionIdentity {
result := &rvboxv1.WindowsExecutionIdentity{SessionUserSid: identity.SessionUserSID, EffectiveUserSid: identity.UserSID, SelectionDetail: identity.SelectionDetail}
for _, contextName := range identity.AttemptedContexts {
if context, ok := windowsExecutionContext(contextName); ok {
result.AttemptedContexts = append(result.AttemptedContexts, context)
}
}
if context, ok := windowsExecutionContext(identity.Context); ok {
result.EffectiveContext = &context
if context == rvboxv1.WindowsExecutionContext_WINDOWS_EXECUTION_CONTEXT_ACTIVE_USER || context == rvboxv1.WindowsExecutionContext_WINDOWS_EXECUTION_CONTEXT_ACTIVE_USER_ELEVATED || context == rvboxv1.WindowsExecutionContext_WINDOWS_EXECUTION_CONTEXT_ACTIVE_SYSTEM {
session := identity.SessionID
result.SessionId = &session
}
}
if result.EffectiveContext == nil && len(result.AttemptedContexts) == 0 && result.SelectionDetail == "" && result.SessionUserSid == "" && result.EffectiveUserSid == "" {
return nil
}
return result
}
func windowsExecutionContext(value string) (rvboxv1.WindowsExecutionContext, bool) {
switch value {
case "LOCAL_SERVICE":
return rvboxv1.WindowsExecutionContext_WINDOWS_EXECUTION_CONTEXT_LOCAL_SERVICE, true
case "LOCAL_SYSTEM":
return rvboxv1.WindowsExecutionContext_WINDOWS_EXECUTION_CONTEXT_LOCAL_SYSTEM, true
case "ACTIVE_USER":
return rvboxv1.WindowsExecutionContext_WINDOWS_EXECUTION_CONTEXT_ACTIVE_USER, true
case "ACTIVE_USER_ELEVATED":
return rvboxv1.WindowsExecutionContext_WINDOWS_EXECUTION_CONTEXT_ACTIVE_USER_ELEVATED, true
case "ACTIVE_SYSTEM":
return rvboxv1.WindowsExecutionContext_WINDOWS_EXECUTION_CONTEXT_ACTIVE_SYSTEM, true
default:
return rvboxv1.WindowsExecutionContext_WINDOWS_EXECUTION_CONTEXT_UNSPECIFIED, false
}
}
type Process interface {