package cli import ( "crypto/rand" "encoding/hex" "fmt" "io" "path/filepath" "strings" "time" ) type RunIDGenerator func(time.Time) (string, error) func defaultRunIDGenerator(startedAt time.Time) (string, error) { var suffix [16]byte if _, err := io.ReadFull(rand.Reader, suffix[:]); err != nil { return "", fmt.Errorf("read random run ID suffix: %w", err) } return fmt.Sprintf("run-%d-%s", startedAt.UnixNano(), hex.EncodeToString(suffix[:])), nil } func validateRunID(runID string) error { if runID == "" { return fmt.Errorf("run ID must not be empty") } if runID != strings.TrimSpace(runID) { return fmt.Errorf("run ID %q must not have surrounding whitespace", runID) } if strings.ContainsAny(runID, `/\\`) || filepath.IsAbs(runID) || filepath.Clean(runID) != runID || runID == "." || runID == ".." { return fmt.Errorf("run ID %q must be one safe path component", runID) } return nil }