feat(cli): agent-readable account list (reduced JSON view)

account list now routes to the agent role; an agent (EMCLI_KEY only) gets a
JSON envelope of name/from/can_send, while the admin keeps the full text
table. account add/edit/remove stay admin-only.

Also emit the agent path's missing-key/open failure as a JSON Failure
envelope (per spec), and update the stale run_test case that asserted the
old admin-only behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-23 21:37:37 +01:00
parent 64ff32ab29
commit 2140d9e173
6 changed files with 151 additions and 18 deletions
+12 -5
View File
@@ -18,9 +18,9 @@ func TestRunUnknownCommand(t *testing.T) {
}
}
func TestRunVersionIsJSONForAgentButTextHere(t *testing.T) {
// `account list` with no DB key should fail closed with a usage/config error,
// proving the key check happens before any DB work.
func TestAccountListMissingKeyFailsClosedAsJSON(t *testing.T) {
// `account list` is an agent command: with no DB key it fails closed before
// any DB work, emitting a JSON config-error envelope that names EMCLI_KEY.
var out, errOut bytes.Buffer
t.Setenv("EMCLI_KEY", "")
t.Setenv("EMCLI_ADMIN_KEY", "")
@@ -28,8 +28,15 @@ func TestRunVersionIsJSONForAgentButTextHere(t *testing.T) {
if code == 0 {
t.Fatal("missing EMCLI_KEY must fail")
}
if !strings.Contains(out.String()+errOut.String(), "EMCLI_ADMIN_KEY") {
t.Fatalf("should mention EMCLI_ADMIN_KEY, got out=%q err=%q", out.String(), errOut.String())
var env map[string]any
if err := json.Unmarshal(out.Bytes(), &env); err != nil {
t.Fatalf("agent account list error must be JSON, got out=%q err=%q", out.String(), errOut.String())
}
if env["error"] != true {
t.Fatalf("want error envelope: %v", env)
}
if !strings.Contains(out.String(), "EMCLI_KEY") {
t.Fatalf("should name the missing EMCLI_KEY, got %q", out.String())
}
}