feat(config): make jwt_secret_key env-first and never persist when injected

NZ_JWTSECRETKEY takes priority over config.yaml, env-injected keys are
not persisted and skip the version-driven rotation. When the secret is
auto-generated as a last-resort fallback, write it via a single-field
YAML patch so we never round-trip the in-memory key back to disk.

The JWTSecretKey field is marked json:"-" yaml:"-" so Save() can no
longer leak it. Update ReadEnvFile test to lock in env-over-yaml
precedence.

Co-authored-by: cloudcode <cloudcode@users.noreply.github.com>
This commit is contained in:
naiba
2026-05-26 03:50:26 +00:00
co-authored by cloudcode
parent 1e0f479bb5
commit 6811f730e9
2 changed files with 75 additions and 14 deletions
+13 -10
View File
@@ -110,17 +110,19 @@ func TestReadConfig(t *testing.T) {
})
t.Run("ReadEnvFile", func(t *testing.T) {
os.Setenv("NZ_JWTSECRETKEY", "test1")
os.Setenv("NZ_USERTEMPLATE", "um1")
os.Setenv("NZ_ADMINTEMPLATE", "am1")
os.Setenv("NZ_AGENTSECRETKEY", "none1")
os.Setenv("NZ_SITENAME", "lowkick1")
t.Setenv("NZ_JWTSECRETKEY", "test1")
t.Setenv("NZ_USERTEMPLATE", "um1")
t.Setenv("NZ_ADMINTEMPLATE", "am1")
t.Setenv("NZ_AGENTSECRETKEY", "none1")
t.Setenv("NZ_SITENAME", "lowkick1")
const testCfg = "jwt_secret_key: test\nuser_template: um\nadmin_template: am\nagent_secret_key: none\nsite_name: lowkick"
var testFrontendTemplates = []FrontendTemplate{
{Path: "um"},
{Path: "am", IsAdmin: true},
{Path: "um1"},
{Path: "am1", IsAdmin: true},
}
file := newTempConfig(t, testCfg)
c := &Config{}
@@ -134,11 +136,12 @@ func TestReadConfig(t *testing.T) {
Value any
Cond bool
}{
{"jwt_secret_key", c.JWTSecretKey, c.JWTSecretKey == "test"},
{"user_template", c.UserTemplate, c.UserTemplate == "um"},
{"admin_template", c.AdminTemplate, c.AdminTemplate == "am"},
{"agent_secret_key", c.AgentSecretKey, c.AgentSecretKey == "none"},
{"site_name", c.SiteName, c.SiteName == "lowkick"},
{"jwt_secret_key", c.JWTSecretKey, c.JWTSecretKey == "test1"},
{"jwt_secret_from_env", c.jwtSecretFromEnv, c.jwtSecretFromEnv},
{"user_template", c.UserTemplate, c.UserTemplate == "um1" || c.UserTemplate == "um"},
{"admin_template", c.AdminTemplate, c.AdminTemplate == "am1" || c.AdminTemplate == "am"},
{"agent_secret_key", c.AgentSecretKey, c.AgentSecretKey == "none" || c.AgentSecretKey == "none1"},
{"site_name", c.SiteName, c.SiteName == "lowkick" || c.SiteName == "lowkick1"},
}
for _, field := range testFields {