feat: l for details; details for vaults, scopes and files; getting started; the age of cached lists (#17)

- `l` goes to the details of what is selected; `enter` still drills in
- vaults, scopes and files show their details (vault settings from the listing, no extra requests)
- with nothing to show, the right pane says how to get started
- a list from the cache says how old it is while it reloads
- what is expiring, in the status pane and `lazysecrets expiring`
- when access is refused, what to check, for Azure and Databricks
- no group list in an account's details, and no Microsoft Graph call for it

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit was merged in pull request #17.
This commit is contained in:
kebandClaude Opus 5.5 committed 2026-10-11 14:24:08 +02:00
1 parent 9b0329e9da
commit 09bacd8438
32 files changed
+1321 -254

No files matched your search

+27 -5
View File
@@ -12,6 +12,7 @@ import (
"context"
"errors"
"fmt"
"strings"
"time"
)
@@ -93,6 +94,8 @@ type Container struct {
// secrets only.
Types []ObjectType
URL string // web page for the container, if any
// Attrs describe it further, from the listing (a vault's settings).
Attrs []Attr `json:",omitempty"`
}
// ObjectTypes returns the container's object types, defaulting to secrets.
@@ -107,6 +110,7 @@ func (c Container) ObjectTypes() []ObjectType {
type Attr struct {
Label string
Value string
Warn bool // worth a look (a plain .env tracked by git): shown in red
}
// Object describes a secret, key or certificate without its value.
@@ -199,9 +203,27 @@ type Account struct {
Copy, CopyLabel string
}
// AccountGroups is implemented by providers that can list the groups
// their account is a member of, directly or through other groups. It
// goes over the network.
type AccountGroups interface {
Groups(ctx context.Context) ([]string, error)
// Denied is a refusal with what to check, from what the service said: a
// role to activate in PIM, access to ask for, the network. Error is the
// refusal, then the checks as a list.
type Denied struct {
Err error
Checks []string
}
func (d *Denied) Error() string {
if len(d.Checks) == 0 {
return d.Err.Error()
}
return d.Err.Error() + "\n\nCheck:\n• " + strings.Join(d.Checks, "\n• ")
}
func (d *Denied) Unwrap() error { return d.Err }
// ContainerDetails is implemented by providers that can say more about a
// container than its listing does: a vault's settings, who has access to
// a scope, how a file is encrypted and what git knows of it. It may go
// over the network; ErrUnsupported means there's nothing more for c.
type ContainerDetails interface {
Details(ctx context.Context, c Container) ([]Attr, error)
}