// Package banner renders the operator-facing blocks that carry a // plaintext credential. // // A generated password printed as one more structured log line is lost: // a boot writes roughly 45 fx PROVIDE/RUN/HOOK lines around it, and // under `docker run -d` it is one line in a log subject to rotation. A // credential that is shown exactly once has to be findable by eye when // an operator scrolls back, so it is written as a ruled block rather // than as a log record. // // It is deliberately not a log line: it goes straight to the writer the // caller names — standard output for both the first-boot account and // the `resetpw` subcommand — so it is neither levelled, filtered, nor // rendered as JSON by whichever handler internal/logger installed. package banner import ( "fmt" "io" "strings" ) // ruleWidth is the length of the horizontal rules, chosen to fit an // 80-column terminal without wrapping. const ruleWidth = 72 // Credentials writes a ruled block naming an account and its plaintext // password. headline says which event produced it, and note says what // the operator must do about it; both are written verbatim, so a // multi-line note must already be wrapped. func Credentials( w io.Writer, headline, username, password, note string, ) error { rule := strings.Repeat("=", ruleWidth) _, err := fmt.Fprintf( w, "\n%s\n%s\n\n username: %s\n password: %s\n\n%s\n%s\n\n", rule, headline, username, password, note, rule, ) if err != nil { return fmt.Errorf("writing credentials banner: %w", err) } return nil }