Files
Agent-System-Backend/cmd/agent-system/account_io.go
T
weichenandCursor f13e8b1ab7 Commit account changes and audits in one transaction
Why: creating an account and its activation key, and changing a password, were separate commits, so a crash could leave a user without a key or a new password with a still-valid login key.
Evidence: SELF go test ./internal/store including TestConcurrentCreateOneWinner, TestPasswordChangeIsAtomic, TestOpenExistingDoesNotMigrateOrCreate, and TestBootstrapRefusesExistingBusiness. PostgreSQL cases are NOT_RUN locally.
Impact: strict insert returns ErrConflict instead of overwriting. Account CLI opens an existing database without migrating. --dsn and --password still work and warn. capabilities --json does not touch the database.
Refs: docs/svc-deploy/u7-account-tx-audit.md
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 14:49:40 +00:00

90 lines
2.0 KiB
Go

package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"os"
)
func runCapabilities(args []string) int {
fs := flag.NewFlagSet("capabilities", flag.ExitOnError)
asJSON := fs.Bool("json", false, "以 JSON 打印能力,不打开数据库")
_ = fs.Parse(args)
caps := map[string]any{
"accountTransaction": true,
"accountAudit": true,
"accountOpsOpen": true,
"passwordStdin": true,
"dsnFile": true,
"outFile": true,
}
if !*asJSON {
fmt.Fprintln(os.Stderr, "用法:agent-system capabilities --json")
return 2
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(caps); err != nil {
fmt.Fprintln(os.Stderr, "capabilities:", err)
return 1
}
return 0
}
func resolveAccountDSN(flagDSN, dsnFile string) (string, error) {
if flagDSN != "" {
fmt.Fprintln(os.Stderr, "warning: --dsn is deprecated; use AGENT_SYSTEM_DSN or --dsn-file")
}
if dsnFile != "" {
info, err := os.Stat(dsnFile)
if err != nil {
return "", err
}
if info.Mode().Perm() != 0o600 {
return "", fmt.Errorf("dsn file %s must be mode 0600", dsnFile)
}
raw, err := os.ReadFile(dsnFile)
if err != nil {
return "", err
}
return string(trimNewline(raw)), nil
}
if env := os.Getenv("AGENT_SYSTEM_DSN"); env != "" {
return env, nil
}
return flagDSN, nil
}
func resolveAccountPassword(flagPassword string, fromStdin bool) (string, error) {
if flagPassword != "" {
fmt.Fprintln(os.Stderr, "warning: --password is deprecated; use --password-stdin")
}
if !fromStdin {
return flagPassword, nil
}
raw, err := io.ReadAll(os.Stdin)
if err != nil {
return "", err
}
return string(trimNewline(raw)), nil
}
func writeExclusiveSecret(path, body string) error {
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600)
if err != nil {
return err
}
defer f.Close()
_, err = io.WriteString(f, body+"\n")
return err
}
func trimNewline(raw []byte) []byte {
for len(raw) > 0 && (raw[len(raw)-1] == '\n' || raw[len(raw)-1] == '\r') {
raw = raw[:len(raw)-1]
}
return raw
}