guide: read-only guided manual-rotation layer (links + worklist + TUI)
Advances the guided-rotation goal without rotating anything. - internal/links: offline change-password URL generation — curated per-service table + RFC 8615 /.well-known/change-password + parent-domain fallback; derives a web host from a credential (git/netrc "user @ host", docker registry, aws) - internal/worklist: secrets-free rotation worklist (source, identity, auto/manual, link) + Markdown renderer - internal/tui: Bubble Tea walk-through (one credential per screen, open link, mark done/skip, progress) — READ-ONLY, enters/stores no secret - cmd: `incredigo worklist` (offline, stdout/--out) and `incredigo guide` (TUI) - tests: link derivation, worklist build/markdown + no-secret-column, TUI navigation/done/quit/view Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package worklist
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"incredigo/internal/discover"
|
||||
)
|
||||
|
||||
func TestBuildAndMarkdown(t *testing.T) {
|
||||
creds := []discover.Credential{
|
||||
{Source: "git", Identity: "alice @ github.com", Kind: discover.KindToken},
|
||||
{Source: "ssh", Identity: "id_ed25519", Kind: discover.KindPrivateKey},
|
||||
{Source: "docker", Identity: "ghcr.io", Kind: discover.KindPassword},
|
||||
}
|
||||
items := Build(creds)
|
||||
if len(items) != 3 {
|
||||
t.Fatalf("got %d items, want 3", len(items))
|
||||
}
|
||||
// No drivers are registered yet, so everything is manual.
|
||||
for _, it := range items {
|
||||
if !it.Manual() {
|
||||
t.Errorf("item %q unexpectedly has driver %q", it.Credential.Identity, it.Driver)
|
||||
}
|
||||
}
|
||||
// github link is curated; ssh has no web page.
|
||||
if items[0].Link.URL != "https://github.com/settings/tokens" {
|
||||
t.Errorf("git link = %q", items[0].Link.URL)
|
||||
}
|
||||
if items[1].Link.URL != "" {
|
||||
t.Errorf("ssh should have no link, got %q", items[1].Link.URL)
|
||||
}
|
||||
|
||||
md := Markdown(items)
|
||||
for _, want := range []string{
|
||||
"# incredigo rotation worklist",
|
||||
"3 credential(s)",
|
||||
"https://github.com/settings/tokens",
|
||||
"alice @ github.com",
|
||||
"— (no web page)", // ssh row
|
||||
} {
|
||||
if !strings.Contains(md, want) {
|
||||
t.Errorf("markdown missing %q\n---\n%s", want, md)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarkdownHasNoSecrets(t *testing.T) {
|
||||
// Identities are pre-redacted; assert the renderer never invents a secret column.
|
||||
items := Build([]discover.Credential{{Source: "aws", Identity: "default / AKIA***"}})
|
||||
md := Markdown(items)
|
||||
if strings.Contains(strings.ToLower(md), "password |") && strings.Contains(md, "secret value") {
|
||||
t.Error("worklist must not contain a secret-value column")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user