Documentation
¶
Overview ¶
Package process provides cross-platform process-group teardown: it kills a process together with its descendants (KillProcessGroup) so agent process trees do not survive the tmux session that launched them.
Index ¶
- Variables
- func CommandIsUnresolvable(cmd string) bool
- func ForceKillProcess(pid int) error
- func IsReservedScriptEnvKey(key string) bool
- func KillProcessGroup(leaderPID int, opts KillOptions) error
- func ReferencesInRepoFiles(cmd, repoRoot string) []string
- func SetProcessGroup(cmd *exec.Cmd)
- type EnvBuilder
- type KillOptions
- type PortAllocator
- type ScriptRunner
- func (r *ScriptRunner) IsRunning(ws *data.Workspace) bool
- func (r *ScriptRunner) LoadConfig(repoPath string) (*WorkspaceConfig, error)
- func (r *ScriptRunner) PortAllocated(ws *data.Workspace) (int, bool)
- func (r *ScriptRunner) ReleaseWorkspace(ws *data.Workspace)
- func (r *ScriptRunner) RunScript(ws *data.Workspace, scriptType ScriptType) (*exec.Cmd, error)
- func (r *ScriptRunner) RunSetup(ws *data.Workspace) error
- func (r *ScriptRunner) Stop(ws *data.Workspace) error
- func (r *ScriptRunner) StopAll()
- func (r *ScriptRunner) TrustRepoScripts(repoPath string) error
- func (r *ScriptRunner) TrustRepoScriptsIfHash(repoPath, expectedHash string) error
- type ScriptTrust
- type ScriptType
- type ScriptsNotTrustedError
- type WorkspaceConfig
Constants ¶
This section is empty.
Variables ¶
var ErrPortRangeExhausted = errors.New("port allocator exhausted")
ErrPortRangeExhausted reports that no valid, non-overlapping port range remains.
var ErrScriptsChangedSincePrompt = errors.New("project scripts changed since trust prompt")
ErrScriptsChangedSincePrompt is returned when a user approves script content after the repo config changed from the content that originally triggered the prompt.
var ErrScriptsNotTrusted = errors.New("project scripts not trusted")
ErrScriptsNotTrusted is returned (wrapped) when a repo's .amux/workspaces.json supplies commands but the user has not approved the current content of that file. It is the sentinel callers test with errors.Is to distinguish a trust skip from a genuine setup failure.
Functions ¶
func CommandIsUnresolvable ¶ added in v0.0.20
CommandIsUnresolvable reports whether cmd contains constructs (variable expansion, command substitution, globs) that prevent static reference detection, so callers can warn that the command may reference files this detector cannot see. It is a coarse signal, not a parser: any occurrence of $, backtick, *, or ? anywhere in the string trips it.
func ForceKillProcess ¶ added in v0.0.14
ForceKillProcess sends SIGKILL to the process group led by pid.
func IsReservedScriptEnvKey ¶ added in v0.0.20
IsReservedScriptEnvKey reports whether key is one of the reserved AMUX_*/ROOT_* names BuildEnv/BuildEnvMap inject (see isReservedScriptEnvKey below for the exact list). It is exported so callers outside this package -- namely the workspace environment-variable editor -- can exclude reserved keys before they are ever shown or persisted, without duplicating or drifting from this list.
func KillProcessGroup ¶ added in v0.0.6
func KillProcessGroup(leaderPID int, opts KillOptions) error
KillProcessGroup sends SIGTERM to a process group, waits for the grace period, then sends SIGKILL if processes are still running. The leaderPID parameter is the process ID of the group leader.
func ReferencesInRepoFiles ¶ added in v0.0.20
ReferencesInRepoFiles best-effort detects paths inside repoRoot that a shell command string appears to reference (e.g. "bash ./scripts/dev.sh"). It is intentionally conservative: it reports likely references, never claims to be complete, and is used to WARN, not to authorize. It returns repo-relative paths that exist as regular files under repoRoot.
It does NOT parse the shell. It splits on whitespace, strips surrounding quotes, skips tokens containing shell metacharacters that make resolution unreliable, and confirms each remaining path-like token resolves to an existing file that stays within repoRoot (no ".." escapes). An empty result means "no in-repo file reference was detected", which is NOT a guarantee that the command runs no repo files; use CommandIsUnresolvable to detect the constructs that hide references from this scan.
func SetProcessGroup ¶ added in v0.0.6
SetProcessGroup configures a command to run in its own process group.
Types ¶
type EnvBuilder ¶
type EnvBuilder struct {
// contains filtered or unexported fields
}
EnvBuilder builds environment variables for script execution
func NewEnvBuilder ¶
func NewEnvBuilder(ports *PortAllocator) *EnvBuilder
NewEnvBuilder creates a new environment builder
func (*EnvBuilder) BuildEnv ¶
func (b *EnvBuilder) BuildEnv(ws *data.Workspace) []string
BuildEnv creates environment variables for a workspace
func (*EnvBuilder) BuildEnvMap ¶
func (b *EnvBuilder) BuildEnvMap(ws *data.Workspace) map[string]string
BuildEnvMap creates a map of environment variables
type KillOptions ¶ added in v0.0.6
type KillOptions struct {
// GracePeriod is how long to wait for SIGTERM before sending SIGKILL.
// Default: 200ms
GracePeriod time.Duration
}
KillOptions configures process group termination behavior.
type PortAllocator ¶
type PortAllocator struct {
// contains filtered or unexported fields
}
PortAllocator manages port allocation for workspaces
func NewPortAllocator ¶
func NewPortAllocator(start, rangeSize int) *PortAllocator
NewPortAllocator creates a new port allocator
func (*PortAllocator) AllocatePort ¶
func (p *PortAllocator) AllocatePort(workspaceRoot string) int
AllocatePort allocates a port range for a workspace
func (*PortAllocator) GetPort ¶
func (p *PortAllocator) GetPort(workspaceRoot string) (int, bool)
GetPort returns the allocated port for a workspace
func (*PortAllocator) PortRange ¶
func (p *PortAllocator) PortRange(workspaceRoot string) (port, rangeEnd int)
PortRange returns the port and range size for a workspace
func (*PortAllocator) ReleasePort ¶
func (p *PortAllocator) ReleasePort(workspaceRoot string)
ReleasePort releases the port allocation for a workspace so the base can be reused.
type ScriptRunner ¶
type ScriptRunner struct {
// contains filtered or unexported fields
}
ScriptRunner manages script execution for workspaces
func NewScriptRunner ¶
func NewScriptRunner(portStart, portRange int) *ScriptRunner
NewScriptRunner creates a new script runner
func (*ScriptRunner) IsRunning ¶
func (r *ScriptRunner) IsRunning(ws *data.Workspace) bool
IsRunning checks if a script is running for a workspace
func (*ScriptRunner) LoadConfig ¶
func (r *ScriptRunner) LoadConfig(repoPath string) (*WorkspaceConfig, error)
LoadConfig loads the workspace configuration from the repo
func (*ScriptRunner) PortAllocated ¶ added in v0.0.20
func (r *ScriptRunner) PortAllocated(ws *data.Workspace) (int, bool)
PortAllocated reports the port base allocated for the workspace, and whether one is currently held. It mirrors PortAllocator.GetPort so callers (and the delete path's tests) can observe release without reaching into the allocator.
func (*ScriptRunner) ReleaseWorkspace ¶ added in v0.0.20
func (r *ScriptRunner) ReleaseWorkspace(ws *data.Workspace)
ReleaseWorkspace releases the workspace's port allocation once no script is running for it, so a deleted workspace's port-range entry does not leak in the allocator's map for the lifetime of the process. It is a no-op while a script is still running so a release can never strand a live script's port; the caller (workspace delete) tears scripts down first. The allocator is keyed by the raw ws.Root (see EnvBuilder.PortRange), so release uses ws.Root directly.
func (*ScriptRunner) RunScript ¶
func (r *ScriptRunner) RunScript(ws *data.Workspace, scriptType ScriptType) (*exec.Cmd, error)
RunScript runs a script for a workspace
func (*ScriptRunner) RunSetup ¶
func (r *ScriptRunner) RunSetup(ws *data.Workspace) error
RunSetup runs the setup scripts for a workspace
func (*ScriptRunner) Stop ¶
func (r *ScriptRunner) Stop(ws *data.Workspace) error
Stop stops the running script for a workspace
func (*ScriptRunner) TrustRepoScripts ¶ added in v0.0.20
func (r *ScriptRunner) TrustRepoScripts(repoPath string) error
TrustRepoScripts records the current content of repoPath's .amux/workspaces.json as approved, so subsequent RunSetup/RunScript calls execute its repo-supplied commands. Approval is content-bound: any later edit to the file re-gates execution until the user trusts it again. A repo with no config file is a no-op (nothing to trust).
func (*ScriptRunner) TrustRepoScriptsIfHash ¶ added in v0.0.20
func (r *ScriptRunner) TrustRepoScriptsIfHash(repoPath, expectedHash string) error
TrustRepoScriptsIfHash records trust only if the repo config still matches the content hash that originally triggered the user approval prompt.
type ScriptTrust ¶ added in v0.0.20
type ScriptTrust struct {
// contains filtered or unexported fields
}
ScriptTrust is the per-user registry of repos whose .amux/workspaces.json content the user has explicitly approved. It maps a normalized repo path to the hex SHA-256 of the config content that was approved, so any later edit to the repo's config invalidates the approval (the hash no longer matches). That hash pins only the .amux/workspaces.json content itself; it does not pin other repo files that an approved command may execute.
The security property it enforces: repo-supplied executable config keys (config.SetupWorkspace / config.RunScript / config.ArchiveScript loaded from .amux/workspaces.json) never execute unless IsTrusted returns true. It is fail-closed — a missing or corrupt registry yields "not trusted". If a future change adds new repo-supplied executable config keys, they must go through the same IsTrusted check.
func NewScriptTrust ¶ added in v0.0.20
func NewScriptTrust(dir string) *ScriptTrust
NewScriptTrust returns a registry whose backing file lives in dir.
func (*ScriptTrust) IsTrusted ¶ added in v0.0.20
func (t *ScriptTrust) IsTrusted(repoPath string, configContent []byte) bool
IsTrusted reports whether the user has approved the current content of repoPath's .amux/workspaces.json. It is fail-closed: a missing or corrupt registry, or any content change since approval, yields false.
type ScriptType ¶
type ScriptType string
ScriptType identifies the type of script
const ( ScriptSetup ScriptType = "setup" ScriptRun ScriptType = "run" ScriptArchive ScriptType = "archive" )
type ScriptsNotTrustedError ¶ added in v0.0.20
ScriptsNotTrustedError carries the hash of the repo config content that was blocked, so the UI can bind a later approval to the exact reviewed content.
func (*ScriptsNotTrustedError) Error ¶ added in v0.0.20
func (e *ScriptsNotTrustedError) Error() string
func (*ScriptsNotTrustedError) Unwrap ¶ added in v0.0.20
func (e *ScriptsNotTrustedError) Unwrap() error
type WorkspaceConfig ¶ added in v0.0.5
type WorkspaceConfig struct {
SetupWorkspace []string `json:"setup-workspace"`
RunScript string `json:"run"`
ArchiveScript string `json:"archive"`
}
WorkspaceConfig holds per-project workspace configuration