// Command behavision-demo-pack seals a camera list into demo-cameras.enc for a // demo release. It runs on the machine that builds the release and is never // shipped. // // behavision-demo-pack -cameras cameras.json -out demo-cameras.enc // // Prints the unlock code exactly once. It is not stored anywhere; a code you // can look up later is a code anyone with access to the build machine holds. // Lose it and seal again. package main import ( "encoding/json" "flag" "fmt" "os" "github.com/loyaly/behavision-agent/pkg/demo" ) func main() { in := flag.String("cameras", "", "JSON array of cameras (id, host, port, path, username, password) - the PC then runs on its own") enrolCode := flag.String("enrol-code", "", "an installation code from head office - the PC then claims that shop and gets its cameras from there") cloud := flag.String("cloud", "https://mcp.loyaly.ai", "head office, with -enrol-code") out := flag.String("out", "demo-cameras.enc", "sealed bundle to write") flag.Parse() if *in == "" && *enrolCode == "" { fmt.Fprintln(os.Stderr, "usage: behavision-demo-pack (-cameras cameras.json | -enrol-code CODE [-cloud URL]) [-out demo-cameras.enc]") os.Exit(2) } var payload demo.Payload if *in != "" { raw, err := os.ReadFile(*in) if err != nil { die("read cameras: %v", err) } if err := json.Unmarshal(raw, &payload.Cameras); err != nil { die("cameras.json: %v", err) } if len(payload.Cameras) == 0 { die("no cameras in %s", *in) } } payload.EnrolCode = *enrolCode if *enrolCode != "" { payload.CloudBase = *cloud } cams := payload.Cameras for i, c := range cams { switch { case c.ID == "": die("camera %d has no id", i) case c.Host == "": die("camera %q has no host", c.ID) case c.Path == "": die("camera %q has no path - the stream path is the field nobody can guess", c.ID) } } // Re-marshal so only the fields the engine accepts travel, in a stable // shape, whatever extra keys the input happened to carry. plain, err := json.Marshal(payload) if err != nil { die("marshal: %v", err) } code, err := demo.NewCode() if err != nil { die("code: %v", err) } sealed, err := demo.Seal(code, plain) if err != nil { die("seal: %v", err) } if err := os.WriteFile(*out, sealed, 0o644); err != nil { die("write: %v", err) } if payload.EnrolCode != "" { fmt.Printf("\n sealed an installation code for %s into %s (%d bytes)\n\n", payload.CloudBase, *out, len(sealed)) } else { fmt.Printf("\n sealed %d camera(s) into %s (%d bytes)\n\n", len(cams), *out, len(sealed)) } fmt.Printf(" unlock code: %s\n\n", code) fmt.Println(" Shown once. Give it to whoever runs behavision-setup, by voice") fmt.Println(" or message - not in the same place as the zip.") fmt.Println() } func die(format string, args ...any) { fmt.Fprintf(os.Stderr, " "+format+"\n", args...) os.Exit(1) }