package main import ( "agent-system-backend/internal/store" "bytes" "io" "os" "os/exec" "path/filepath" "testing" ) func accountCLI(t *testing.T, args ...string) (int, string) { t.Helper() out, err := os.CreateTemp(t.TempDir(), "capture-") if err != nil { t.Fatal(err) } defer out.Close() oldOut, oldErr := os.Stdout, os.Stderr os.Stdout = out os.Stderr = out defer func() { os.Stdout = oldOut; os.Stderr = oldErr }() rc := runUser(args) out.Seek(0, 0) raw, err := io.ReadAll(out) if err != nil { t.Fatal(err) } return rc, string(raw) } func cliStore(t *testing.T) (string, *store.Store) { t.Helper() t.Setenv("AGENT_SYSTEM_DSN", "") dir := t.TempDir() s, e := store.OpenSQLite(filepath.Join(dir, "agent-system.db")) if e != nil { t.Fatal(e) } t.Cleanup(func() { s.Close() }) if e := s.EnsureSystemIdentity("fixture", "sqlite"); e != nil { t.Fatal(e) } return dir, s } func TestCreateAndInitializeAccountDoNotRequireCredentialOutput(t *testing.T) { for _, sub := range []string{"create", "initialize-account"} { t.Run(sub, func(t *testing.T) { dir, s := cliStore(t) if _, e := s.BootstrapFirstAdminWrite(store.AccountWrite{Owner: "root", Name: "Root", Actor: "test"}); e != nil { t.Fatal(e) } args := []string{sub, "--data", dir, "--owner", "ada"} if sub == "initialize-account" { a, e := s.CreatePendingAccount("root", "ada", store.AccountProfile{Name: "Ada"}) if e != nil { t.Fatal(e) } args = append(args, "--user-id", a.ID, "--expected-state-version", "1", "--expected-generation", "0") } rc, _ := accountCLI(t, args...) if rc != 0 { t.Fatalf("command failed without credential output file: %d", rc) } }) } } func TestExistingOutputAndConflictingFormatsRefuseBeforeMutation(t *testing.T) { for _, kind := range []string{"existing", "conflicting"} { t.Run(kind, func(t *testing.T) { dir, s := cliStore(t) out := filepath.Join(t.TempDir(), "secret") args := []string{"create", "--data", dir, "--owner", "ada", "--out-file", out} if kind == "existing" { if e := os.WriteFile(out, []byte("existing"), 0600); e != nil { t.Fatal(e) } } else { args = append(args, "--out", filepath.Join(t.TempDir(), "json-secret")) } rc, _ := accountCLI(t, args...) if rc == 0 { t.Fatal("unsafe output selection succeeded") } if _, e := s.GetUser("ada"); e == nil { t.Fatal("output refusal happened after account mutation") } }) } } func TestAPIKeyCreateUsesExclusivePrivateOutput(t *testing.T) { if dir := os.Getenv("U7_APIKEY_CHILD_DIR"); dir != "" { rc := runAPIKey([]string{"create", "--data", dir, "--owner", "ada", "--name", "fixture", "--out-file", os.Getenv("U7_APIKEY_CHILD_OUT")}) if rc != 0 { t.Fatal("apikey create rejected its private output destination") } return } for _, existing := range []bool{false, true} { name := "new" if existing { name = "existing" } t.Run(name, func(t *testing.T) { dir, st := cliStore(t) if err := st.CreateAccount("ada", "Ada", "", false); err != nil { t.Fatal(err) } out := filepath.Join(t.TempDir(), "credential") if existing { if err := os.WriteFile(out, []byte("preserve"), 0600); err != nil { t.Fatal(err) } } cmd := exec.Command(os.Args[0], "-test.run=^TestAPIKeyCreateUsesExclusivePrivateOutput$") cmd.Env = append(os.Environ(), "U7_APIKEY_CHILD_DIR="+dir, "U7_APIKEY_CHILD_OUT="+out) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr err := cmd.Run() if existing { if err == nil { t.Fatal("existing output was overwritten or mutation succeeded") } raw, readErr := os.ReadFile(out) if readErr != nil || string(raw) != "preserve" { t.Fatal("existing output was modified") } keys, listErr := st.ListAPIKeys("ada") if listErr != nil || len(keys) != 0 { t.Fatal("mutation happened before output preflight") } return } if err != nil { t.Fatal("new private output was rejected") } info, statErr := os.Stat(out) if statErr != nil || info.Mode().Perm() != 0600 { t.Fatal("credential output missing or not private") } raw, readErr := os.ReadFile(out) if readErr != nil || len(raw) == 0 { t.Fatal("credential output empty") } if bytes.Contains(stdout.Bytes(), bytes.TrimSpace(raw)) { t.Fatal("credential was written to stdout") } keys, listErr := st.ListAPIKeys("ada") if listErr != nil || len(keys) != 1 { t.Fatal("successful issue was not committed") } }) } }