// Package taskutil — system_registry.go // // v0.28.6: System task function registry. // // Built-in Go functions that run as auditable, scheduled tasks instead of // ad-hoc goroutines. Each function receives a context, the full store set, // and returns a structured result. The registry is permanent — system // functions are not replaced by Starlark (v0.29.0). Core platform ops // must not break from bad user code. // // Registration happens at init time from main.go. The executor calls // Get() to look up a function by name at execution time. package taskutil import ( "context" "fmt" "sort" "sync" "switchboard-core/store" ) // SystemFunc is the signature for built-in system task functions. // The function receives a context and the full store set. It returns // a human-readable result string (logged in the task run) and an error. type SystemFunc func(ctx context.Context, stores store.Stores) (string, error) // SystemFuncInfo describes a registered system function. type SystemFuncInfo struct { Name string `json:"name"` Description string `json:"description"` } var ( registryMu sync.RWMutex registry = make(map[string]registryEntry) ) type registryEntry struct { fn SystemFunc description string } // RegisterSystemFunc registers a named system function. // Call during init (before scheduler starts). Not goroutine-safe for writes. func RegisterSystemFunc(name, description string, fn SystemFunc) { registryMu.Lock() defer registryMu.Unlock() registry[name] = registryEntry{fn: fn, description: description} } // GetSystemFunc returns a system function by name. func GetSystemFunc(name string) (SystemFunc, bool) { registryMu.RLock() defer registryMu.RUnlock() e, ok := registry[name] if !ok { return nil, false } return e.fn, true } // ListSystemFuncs returns all registered system function names and descriptions. func ListSystemFuncs() []SystemFuncInfo { registryMu.RLock() defer registryMu.RUnlock() result := make([]SystemFuncInfo, 0, len(registry)) for name, e := range registry { result = append(result, SystemFuncInfo{Name: name, Description: e.description}) } sort.Slice(result, func(i, j int) bool { return result[i].Name < result[j].Name }) return result } // ValidateSystemFunc returns an error if the function name is not registered. func ValidateSystemFunc(name string) error { registryMu.RLock() defer registryMu.RUnlock() if _, ok := registry[name]; !ok { names := make([]string, 0, len(registry)) for n := range registry { names = append(names, n) } sort.Strings(names) return fmt.Errorf("unknown system function %q (available: %v)", name, names) } return nil }