Describe the issue
The 3.x → 4.0 upgrade guide item 4 (allowEnvironmentSwitchViaUrl defaults to false in production, plus the reload-password requirement) says "?reload=true requires a non-empty reloadPassword" — but doesn't say where reloadPassword must be set.
Real behavior: the fail-closed check in vendor/wheels/events/init/security.cfm reads from application.wheels.reloadPassword, which is populated from set(reloadPassword="...") in config/settings.cfm — not from a reloadPassword=... line in .env.
3.x apps that source reloadPassword from .env (titan does this; the 4.0 starter-app _env template implies it; many real-world apps do) will see this warning at every boot even after they "fix" it by setting the value in .env:
WARN Wheels: reloadPassword is empty — URL-based environment switching and application reload are disabled until a password is set in config/settings.cfm
The user has to learn the framework's expectation by reading the warning message body, not the upgrade guide.
Why this matters
The whole flow looks like a fail-closed security feature working as intended, but it's actually a documentation gap that leaves the security feature disabled in production for any app that just sets reloadPassword=xxx in .env and expects it to flow through.
Suggested fix
Either:
-
Make the framework read .env for reloadPassword as a fallback. In events/init/security.cfm (or wherever the fail-closed check lives), fall back to application.env.reloadPassword if application.wheels.reloadPassword is empty.
-
Document the path explicitly. In the upgrade guide's item 4, include:
// config/settings.cfm
set(reloadPassword = env("WHEELS_RELOAD_PASSWORD"));
plus a note that env() is the canonical way to wire .env values into framework settings. Also add this line to the wheels new starter-app config/settings.cfm template so fresh scaffolds work out of the box.
The 4.0 starter-app template's config/settings.cfm currently doesn't have a set(reloadPassword=...) line either, so this affects fresh-app users too.
Reproducer
# In any 4.0 app's .env:
reloadPassword=abc123
# Boot the server:
wheels start
# Observe wheels_security.log:
WARN Wheels: reloadPassword is empty — URL-based environment switching and application reload are disabled until a password is set in config/settings.cfm
# Despite reloadPassword=abc123 being present in .env. ?reload=true&password=abc123 is silently disabled.
The workaround I'm using on titan: add set(reloadPassword = env("reloadPassword", "")) to config/settings.cfm. The fallback empty string keeps the fail-closed behavior if the env var is missing, which is the secure default.
Environment
- Wheels: 4.0.0-SNAPSHOT+1779
🤖 Filed by Claude Code while assisting with a 4.0 upgrade testbed
Describe the issue
The 3.x → 4.0 upgrade guide item 4 (
allowEnvironmentSwitchViaUrldefaults to false in production, plus the reload-password requirement) says "?reload=truerequires a non-emptyreloadPassword" — but doesn't say wherereloadPasswordmust be set.Real behavior: the fail-closed check in
vendor/wheels/events/init/security.cfmreads fromapplication.wheels.reloadPassword, which is populated fromset(reloadPassword="...")inconfig/settings.cfm— not from areloadPassword=...line in.env.3.x apps that source
reloadPasswordfrom.env(titan does this; the 4.0 starter-app_envtemplate implies it; many real-world apps do) will see this warning at every boot even after they "fix" it by setting the value in.env:The user has to learn the framework's expectation by reading the warning message body, not the upgrade guide.
Why this matters
The whole flow looks like a fail-closed security feature working as intended, but it's actually a documentation gap that leaves the security feature disabled in production for any app that just sets
reloadPassword=xxxin.envand expects it to flow through.Suggested fix
Either:
Make the framework read
.envforreloadPasswordas a fallback. Inevents/init/security.cfm(or wherever the fail-closed check lives), fall back toapplication.env.reloadPasswordifapplication.wheels.reloadPasswordis empty.Document the path explicitly. In the upgrade guide's item 4, include:
// config/settings.cfm set(reloadPassword = env("WHEELS_RELOAD_PASSWORD"));plus a note that
env()is the canonical way to wire.envvalues into framework settings. Also add this line to thewheels newstarter-appconfig/settings.cfmtemplate so fresh scaffolds work out of the box.The 4.0 starter-app template's
config/settings.cfmcurrently doesn't have aset(reloadPassword=...)line either, so this affects fresh-app users too.Reproducer
The workaround I'm using on titan: add
set(reloadPassword = env("reloadPassword", ""))toconfig/settings.cfm. The fallback empty string keeps the fail-closed behavior if the env var is missing, which is the secure default.Environment
🤖 Filed by Claude Code while assisting with a 4.0 upgrade testbed