2026-07-24 11:06:59 +02:00
|
|
|
package config
|
|
|
|
|
|
|
|
|
|
import "log/slog"
|
|
|
|
|
|
|
|
|
|
// This file makes secret-bearing config types safe to log by construction.
|
|
|
|
|
// Without it, "never log secrets" holds only by call-site discipline — a
|
|
|
|
|
// single slog.Info("cfg", "voice", cfg.Voice) would dump the LiveKit key. By
|
|
|
|
|
// implementing slog.LogValuer, secrets are redacted no matter how the value
|
|
|
|
|
// reaches a log record. Non-secret fields stay visible so the logs remain
|
|
|
|
|
// useful for debugging.
|
|
|
|
|
|
|
|
|
|
// redactSecret masks a secret for logging. An empty value stays empty (so an
|
|
|
|
|
// unset credential is still visible as "unset"); anything else becomes a fixed
|
|
|
|
|
// marker that reveals neither the value nor its length.
|
|
|
|
|
func redactSecret(s string) string {
|
|
|
|
|
if s == "" {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return "[REDACTED]"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LogValue redacts the LiveKit API key and secret.
|
|
|
|
|
func (v VoiceConfig) LogValue() slog.Value {
|
|
|
|
|
return slog.GroupValue(
|
|
|
|
|
slog.String("livekit_api_key", redactSecret(v.LiveKitAPIKey)),
|
|
|
|
|
slog.String("livekit_api_secret", redactSecret(v.LiveKitAPISecret)),
|
|
|
|
|
slog.String("livekit_url", v.LiveKitURL),
|
|
|
|
|
slog.String("livekit_binary", v.LiveKitBinaryPath),
|
2026-07-31 15:41:57 +02:00
|
|
|
slog.Bool("auto_download_livekit", v.AutoDownloadLiveKit),
|
|
|
|
|
slog.String("livekit_version", v.LiveKitVersion),
|
2026-07-24 11:06:59 +02:00
|
|
|
slog.String("node_ip", v.NodeIP),
|
|
|
|
|
slog.Bool("advertise_internal_ip", v.AdvertiseInternalIP),
|
|
|
|
|
slog.String("quality", v.Quality),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LogValue redacts the GitHub token.
|
|
|
|
|
func (g GitHubConfig) LogValue() slog.Value {
|
|
|
|
|
return slog.GroupValue(
|
|
|
|
|
slog.String("token", redactSecret(g.Token)),
|
|
|
|
|
slog.String("owner", g.Owner),
|
|
|
|
|
slog.String("repo", g.Repo),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LogValue redacts the Klipy (GIF proxy) API key.
|
|
|
|
|
func (g GIFConfig) LogValue() slog.Value {
|
|
|
|
|
return slog.GroupValue(
|
|
|
|
|
slog.String("api_key", redactSecret(g.APIKey)),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LogValue delegates each section through slog.Any so secret-bearing sections
|
|
|
|
|
// are redacted via their own LogValue even when the whole Config is logged.
|
|
|
|
|
// A section added to Config but not listed here is omitted from the log (safe:
|
|
|
|
|
// it is hidden, never leaked).
|
|
|
|
|
func (c Config) LogValue() slog.Value {
|
|
|
|
|
return slog.GroupValue(
|
|
|
|
|
slog.Any("server", c.Server),
|
|
|
|
|
slog.Any("database", c.Database),
|
|
|
|
|
slog.Any("tls", c.TLS),
|
|
|
|
|
slog.Any("upload", c.Upload),
|
|
|
|
|
slog.Any("voice", c.Voice),
|
|
|
|
|
slog.Any("github", c.GitHub),
|
|
|
|
|
slog.Any("event_persistence", c.EventPersistence),
|
|
|
|
|
slog.Any("telemetry", c.Telemetry),
|
|
|
|
|
slog.Any("plugins", c.Plugins),
|
|
|
|
|
slog.Any("gif", c.GIF),
|
|
|
|
|
slog.Any("logging", c.Logging),
|
|
|
|
|
)
|
|
|
|
|
}
|