// Command fluid is the FLUID operator CLI. // // It reads and writes the evidence store directly rather than going through the // control-plane API, so that an operator can still inspect an interface's // history when the control plane is down. Auditability must not depend on the // availability of the thing being audited. package main import ( "context" "errors" "flag" "fmt" "os" "path/filepath" "strings" ) const usage = `fluid — FLUID operator CLI Usage: fluid [--store PATH] [--interface ID] [arguments] Commands: intent put Record an interface evolution intent version intent activate Make a recorded version the governing intent intent show Show the active or a named intent version revision publish Publish a signed revision descriptor revision list List published revisions revision show Show one revision descriptor policy put Install a routing policy policy show Show the current routing policy events Show audit events telemetry Show recorded telemetry audit trace Reconstruct the history behind a revision Global flags: --store PATH Evidence store path (default $FLUID_STORE or ./fluid.db) --interface ID Interface identifier (default $FLUID_INTERFACE) ` func main() { if err := run(os.Args[1:]); err != nil { if errors.Is(err, flag.ErrHelp) { os.Exit(0) } fmt.Fprintln(os.Stderr, "fluid:", err) os.Exit(1) } } type globals struct { store string iface string remaining []string } func parseGlobals(args []string) (globals, error) { g := globals{ store: envOr("FLUID_STORE", "fluid.db"), iface: os.Getenv("FLUID_INTERFACE"), } i := 0 for i < len(args) { switch args[i] { case "--store": if i+1 >= len(args) { return g, errors.New("--store needs a value") } g.store, i = args[i+1], i+2 case "--interface": if i+1 >= len(args) { return g, errors.New("--interface needs a value") } g.iface, i = args[i+1], i+2 case "-h", "--help", "help": fmt.Print(usage) return g, flag.ErrHelp default: if strings.HasPrefix(args[i], "--") { return g, fmt.Errorf("unknown global flag %q", args[i]) } g.remaining = args[i:] return g, nil } } g.remaining = nil return g, nil } func run(args []string) error { g, err := parseGlobals(args) if err != nil { return err } if len(g.remaining) == 0 { fmt.Print(usage) return nil } ctx := context.Background() cmd, rest := g.remaining[0], g.remaining[1:] switch cmd { case "intent": return runIntent(ctx, g, rest) case "revision": return runRevision(ctx, g, rest) case "policy": return runPolicy(ctx, g, rest) case "events": return runEvents(ctx, g, rest) case "telemetry": return runTelemetry(ctx, g, rest) case "audit": return runAudit(ctx, g, rest) default: return fmt.Errorf("unknown command %q (try `fluid help`)", cmd) } } func envOr(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback } // requireInterface fails clearly rather than silently operating on the wrong // interface's history. func (g globals) requireInterface() (string, error) { if g.iface == "" { return "", errors.New("no interface selected: pass --interface or set FLUID_INTERFACE") } return g.iface, nil } func (g globals) storePath() string { if abs, err := filepath.Abs(g.store); err == nil { return abs } return g.store }