Files
orchestra/cmd/orchestra-user/main.go
T
kami 4fbf3ac966 Report queued tasks the scheduling pass never considers
A task in retry backoff was filtered out before the candidate loop, so it
recorded no rejection at all: queued, apparently assignable, and silent. That is
the exact shape that made F5 take a live session to diagnose. It now reports
"retry backoff until <time>".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 23:42:26 +04:00

92 lines
2.1 KiB
Go

// orchestra-user manages browser-operator accounts in Orchestra's embedded
// credential database. Passwords are read from the terminal and hashed inside
// the database; no reusable hash has to be copied into deployment config.
package main
import (
"flag"
"fmt"
"log"
"orchestra/internal/authn"
"os"
"syscall"
"golang.org/x/term"
)
func usage() {
fmt.Fprintln(os.Stderr, "usage:")
fmt.Fprintln(os.Stderr, " orchestra-user set -data DIR -username NAME")
fmt.Fprintln(os.Stderr, " orchestra-user list -data DIR")
}
func readPassword(prompt string) (string, error) {
fmt.Fprint(os.Stderr, prompt)
value, err := term.ReadPassword(int(syscall.Stdin))
fmt.Fprintln(os.Stderr)
return string(value), err
}
func open(data string) *authn.Store {
if data == "" {
log.Fatal("-data is required")
}
users, err := authn.Open(authn.Path(data))
if err != nil {
log.Fatal(err)
}
return users
}
func main() {
if len(os.Args) < 2 {
usage()
os.Exit(2)
}
switch os.Args[1] {
case "set":
flags := flag.NewFlagSet("set", flag.ExitOnError)
data := flags.String("data", "", "Orchestra data directory")
username := flags.String("username", "", "operator username")
_ = flags.Parse(os.Args[2:])
password, err := readPassword("New password: ")
if err != nil {
log.Fatal(err)
}
confirmation, err := readPassword("Confirm password: ")
if err != nil {
log.Fatal(err)
}
if password != confirmation {
log.Fatal("passwords do not match")
}
users := open(*data)
defer users.Close()
user, created, err := users.SetPassword(*username, password)
if err != nil {
log.Fatal(err)
}
if created {
fmt.Printf("created operator %s\n", user.Username)
} else {
fmt.Printf("updated password for %s\n", user.Username)
}
case "list":
flags := flag.NewFlagSet("list", flag.ExitOnError)
data := flags.String("data", "", "Orchestra data directory")
_ = flags.Parse(os.Args[2:])
users := open(*data)
defer users.Close()
list, err := users.Users()
if err != nil {
log.Fatal(err)
}
for _, user := range list {
fmt.Println(user.Username)
}
default:
usage()
os.Exit(2)
}
}