feat(cli): privacy-aware vault op-log (process, never the secret)

This commit is contained in:
Viktor Barzin 2026-06-24 10:17:50 +00:00
parent 81122f8607
commit 5bae2a3907
2 changed files with 47 additions and 0 deletions

View file

@ -182,6 +182,39 @@ func terminalAllowed(term, termProgram string) bool {
return false
}
// opRecord is one CLI operation. ItemName is accepted for the caller's
// convenience but is INTENTIONALLY never rendered into the log line — auditing
// which of your own logins you opened is itself sensitive, and per-item reads
// are invisible server-side anyway (spec §9a).
type opRecord struct {
User string
Verb string
PID int
PPID int
ParentComm string
ItemName string // never logged
}
func opLogLine(r opRecord) string {
return fmt.Sprintf("user=%s verb=%s pid=%d ppid=%d parent=%s",
r.User, r.Verb, r.PID, r.PPID, r.ParentComm)
}
// parentComm reads /proc/<ppid>/comm (best-effort; "" on failure).
func parentComm(ppid int) string {
b, err := os.ReadFile(fmt.Sprintf("/proc/%d/comm", ppid))
if err != nil {
return ""
}
return strings.TrimSpace(string(b))
}
// writeOpLog appends one privacy-aware line to the user's op-log (best-effort;
// never blocks or fails the command). Goes to syslog so it ships to Loki.
func writeOpLog(r opRecord) {
exec.Command("logger", "-t", "homelab-vault", opLogLine(r)).Run() // best-effort
}
func vaultSetup(args []string) error { return fmt.Errorf("not implemented") }
func vaultStatus(args []string) error { return fmt.Errorf("not implemented") }
func vaultList(args []string) error { return fmt.Errorf("not implemented") }

View file

@ -176,3 +176,17 @@ func TestTerminalAllowed(t *testing.T) {
}
}
}
func TestOpLogLineHasNoSecretOrItem(t *testing.T) {
line := opLogLine(opRecord{User: "emo", Verb: "get", PID: 10, PPID: 9, ParentComm: "claude", ItemName: "Chase Bank"})
for _, must := range []string{"user=emo", "verb=get", "ppid=9", "parent=claude"} {
if !strings.Contains(line, must) {
t.Errorf("op-log missing %q: %s", must, line)
}
}
for _, mustNot := range []string{"Chase", "password", "secret"} {
if strings.Contains(line, mustNot) {
t.Fatalf("op-log LEAKS %q (privacy violation): %s", mustNot, line)
}
}
}