feat: formatted JSON and certificates, errors in the status pane, no scope access list (#19)

**Formatted values.** A revealed value is shown as it reads best: JSON indented, and PEM certificates as subject, issuer, valid dates, names and SHA-1 thumbprint instead of base64. Any other PEM block (a private key in a bundle) is named, `EC PRIVATE KEY (not shown)`, never shown. Anything else shows as before. `y` copies the value exactly as stored, and the hints line says so (`JSON, formatted: y copies it as stored`).

**Errors in the status pane.** This session's errors, newest first, up to 20, with the time and what they were about (`12:32 kv-restricted: 403 Forbidden: …`): lists that couldn't load, values and details that couldn't be read, sources, saving the cache, and whatever the footer flashed (a failed copy) before you moved on. A repeat moves to the top. Sign-ins aren't listed (the footer and the account say those). Only the first line of each, and not kept after quitting. `y` copies one.

**No access list for Databricks scopes.** It was the one request of its own left (one call per scope). Removed with its tests and docs; refusals still say what to check.

**Copying over SSH: checked, nothing to change.** Over SSH (`SSH_TTY`/`SSH_CONNECTION`), `y` copies with OSC 52, and the 30-second clear works the same way. Your tmux (3.7, `set-clipboard on`) passes it through and kitty (`clipboard_control write-clipboard`) accepts it; docs/config.md already says what's needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
Reviewed-on: #19
This commit was merged in pull request #19.
This commit is contained in:
keb committed 2026-10-11 21:16:32 +02:00
1 parent 17054ad0ec
commit b530c043f7
14 files changed
+271 -90

No files matched your search

@@ -140,15 +140,8 @@ func workspaceAPI(t *testing.T, status int) *httptest.Server {
map[string]any{"key": "storage-key", "last_updated_timestamp": 1767225600000},
map[string]any{"key": "client-secret"},
}})
case r.URL.Path == "/api/2.0/secrets/acls/list" && q.Get("scope") == "app":
write(w, 200, map[string]any{"items": []any{
map[string]any{"principal": "users", "permission": "READ"},
map[string]any{"principal": "admins", "permission": "MANAGE"},
}})
case r.URL.Path == "/api/2.0/secrets/list" && q.Get("scope") == "locked":
write(w, 403, map[string]any{"error_code": "PERMISSION_DENIED", "message": "User does not have READ permission on scope locked"})
case r.URL.Path == "/api/2.0/secrets/acls/list" && q.Get("scope") == "locked":
write(w, 403, map[string]any{"error_code": "PERMISSION_DENIED", "message": "User does not have MANAGE permission"})
case r.URL.Path == "/api/2.0/secrets/get" && q.Get("scope") == "app":
write(w, 200, map[string]any{"key": q.Get("key"),
"value": base64.StdEncoding.EncodeToString([]byte("value-of-" + q.Get("key")))})
@@ -301,23 +294,6 @@ func TestClassify(t *testing.T) {
}
}
func TestScopeDetails(t *testing.T) {
p := newTestProvider(t, workspaceAPI(t, 0), nil)
src := provider.Source{ID: "prod"}
attrs, err := p.Details(context.Background(), provider.Container{Source: src, Name: "app"})
if err != nil {
t.Fatal(err)
}
want := []provider.Attr{{Label: "access", Value: "admins · manage"}, {Value: "users · read"}}
if !reflect.DeepEqual(attrs, want) {
t.Errorf("app: %+v", attrs)
}
attrs, err = p.Details(context.Background(), provider.Container{Source: src, Name: "locked"})
if err != nil || len(attrs) != 1 || !strings.Contains(attrs[0].Value, "managers") {
t.Errorf("locked: %+v, %v", attrs, err)
}
}
func TestDeniedSaysWhatToCheck(t *testing.T) {
p := newTestProvider(t, workspaceAPI(t, 0), nil)
_, err := p.Objects(context.Background(), provider.Container{Source: provider.Source{ID: "prod"}, Name: "locked"}, provider.TypeSecret)