package storage import ( "fmt" "os" "path/filepath" "strings" ) type Layout struct { Root string } func New(root string) Layout { return Layout{Root: root} } func (l Layout) Ensure() error { for _, rel := range []string{"events", "live", "logs", "artifacts", "cache", "workspaces", "secrets", "inbox", "active", "schedules"} { if err := os.MkdirAll(filepath.Join(l.Root, rel), 0o755); err != nil { return err } } return nil } func (l Layout) SecretPath(repo, job, name string) (string, error) { for label, value := range map[string]string{"repo": repo, "job": job, "secret": name} { if err := cleanSegment(label, value); err != nil { return "", err } } return filepath.Join(l.Root, "secrets", repo, job, name), nil } func cleanSegment(label, value string) error { if strings.TrimSpace(value) == "" { return fmt.Errorf("empty %s segment", label) } if value != filepath.Base(value) || value == "." || value == ".." || strings.Contains(value, string(filepath.Separator)) { return fmt.Errorf("unsafe %s segment %q", label, value) } return nil }