You've already forked agentic-coding-workflow
fix(config): redact MasterKey type; drop os.Clearenv; add hex validation test
This commit is contained in:
@@ -4,16 +4,33 @@ package config
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// MasterKey wraps a 32-byte AES master key with redacted formatting to prevent
|
||||
// accidental log/fmt exposure.
|
||||
type MasterKey []byte
|
||||
|
||||
// String redacts when used with %s / fmt.Println.
|
||||
func (k MasterKey) String() string { return "[REDACTED 32B]" }
|
||||
|
||||
// GoString redacts when used with %#v.
|
||||
func (k MasterKey) GoString() string { return "[REDACTED 32B]" }
|
||||
|
||||
// MarshalJSON redacts when serialized to JSON.
|
||||
func (k MasterKey) MarshalJSON() ([]byte, error) { return []byte(`"[REDACTED]"`), nil }
|
||||
|
||||
// LogValue redacts when logged via slog.
|
||||
func (k MasterKey) LogValue() slog.Value { return slog.StringValue("[REDACTED 32B]") }
|
||||
|
||||
// Config 是应用全局配置的根结构。
|
||||
type Config struct {
|
||||
Env string `mapstructure:"env"`
|
||||
DataDir string `mapstructure:"data_dir"`
|
||||
MasterKey []byte // 解码后的 32 字节
|
||||
MasterKey MasterKey `mapstructure:"-"` // 解码后的 32 字节,单独从 master_key 解析
|
||||
HTTP HTTPConfig `mapstructure:"http"`
|
||||
DB DBConfig `mapstructure:"db"`
|
||||
Bootstrap BootstrapConfig `mapstructure:"bootstrap"`
|
||||
@@ -86,7 +103,7 @@ func Load(configFile string) (*Config, error) {
|
||||
if len(key) != 32 {
|
||||
return nil, fmt.Errorf("APP_MASTER_KEY must be 32 bytes (got %d)", len(key))
|
||||
}
|
||||
cfg.MasterKey = key
|
||||
cfg.MasterKey = MasterKey(key)
|
||||
|
||||
if cfg.DB.DSN == "" {
|
||||
return nil, fmt.Errorf("APP_DB_DSN required")
|
||||
|
||||
Reference in New Issue
Block a user