// SPDX-License-Identifier: GPL-3.0-or-later // enodia-sentinel-go is the experimental Phase 1 sidecar. Python remains the // production implementation and behavioral oracle until parity is complete. package main import ( "context" "encoding/json" "flag" "fmt" "os" "os/signal" "syscall" "time" "codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/agent" "codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/config" "codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/model" "codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/system" ) func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, "enodia-sentinel-go:", err) os.Exit(1) } } func run() error { once := flag.Bool("once", false, "emit one sweep and exit") configPath := flag.String("config", "", "Sentinel TOML path (default: ENODIA_CONFIG or /etc/enodia-sentinel.toml)") procRoot := flag.String("proc-root", "/proc", "procfs root") fixture := flag.String("fixture", "", "JSON SystemState fixture (parity/testing only)") host := flag.String("host", "", "override hostname (parity/testing only)") timestamp := flag.String("timestamp", "", "override RFC3339 timestamp (parity/testing only)") flag.Parse() cfg, err := config.Load(*configPath) if err != nil { return err } capture := func() (model.State, error) { return system.Capture(*procRoot) } if *fixture != "" { capture = func() (model.State, error) { var state model.State raw, err := os.ReadFile(*fixture) if err != nil { return state, err } err = json.Unmarshal(raw, &state) return state, err } } runner := agent.New(cfg, capture) if *host != "" { runner.Host = func() (string, error) { return *host, nil } } if *timestamp != "" { fixed, err := time.Parse(time.RFC3339Nano, *timestamp) if err != nil { return fmt.Errorf("timestamp: %w", err) } runner.Now = func() time.Time { return fixed } } ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() encoder := json.NewEncoder(os.Stdout) encoder.SetEscapeHTML(false) return runner.Run(ctx, *once, func(event map[string]any) error { return encoder.Encode(event) }) }