Files
Agent-System-Backend/cmd/agent-system/account_io_test.go
T
weichen 48649a37ee
ci / vet-and-test (pull_request) Successful in 40s
Preserve account transactions in the versioned Backend branch
Why: Backend PR #185 merged while the dependency migration was open. Its account transactions, audit behavior and migration tests must remain intact when this branch adopts the new main.

Evidence: SELF 343 upstream Go files match after canonical import translation except the two bounded test-reliability corrections; complete Go test and vet passed in /tmp/dependency-backend-after-185-{parity,all-go,vet}-20261014-01a1345f.json.

Impact: Disposable integration fixture first; the actual Backend branch can fast-forward to this tested merge without rewriting other task history. No production account logic is changed relative to the new main.

Refs: Backend PR #196; upstream Backend PR #185; Dev PR #537; R15
2026-10-14 04:17:06 +00:00

159 lines
4.5 KiB
Go

package main
import (
"git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/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 TestOutputFileAppliesToEveryCredentialCommand(t *testing.T) {
for _, sub := range []string{"create", "reset-password", "issue-login-key", "bootstrap-admin"} {
t.Run(sub, func(t *testing.T) {
dir, s := cliStore(t)
if sub != "create" && sub != "bootstrap-admin" {
if e := s.CreateAccount("ada", "Ada", "", false); e != nil {
t.Fatal(e)
}
}
out := filepath.Join(t.TempDir(), "secret")
rc, _ := accountCLI(t, sub, "--data", dir, "--owner", "ada", "--out-file", out)
if rc != 0 {
t.Fatalf("credential command failed: %d", rc)
}
info, e := os.Stat(out)
if e != nil {
t.Fatal("credential output file missing")
}
if info.Mode().Perm() != 0600 {
t.Fatal("credential output permissions are not private")
}
})
}
}
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")
}
})
}
}