PUT /api/admin/settings refuses any empty text value:
if(typeofraw!=='string'||raw.trim()===''){returnres.status(400).json({error:`${name} cannot be empty`});}
That is right for two of the four text settings and wrong for the other two.
Setting
Fallback
Empty is…
greetingFormat
Hi {{firstName}},
wrong — an empty format renders every greeting as nothing, which reads as a bug in the email
greetingFallback
Hi,
wrong, same reason
intakeNotifyEmail
''
the documented default, meaning "do not notify"
intakeCeilingResetAt
''
the documented default, meaning "no reset recorded"
So intakeNotifyEmail can be set but never cleared. Once an address is in there, turning intake notifications back off through the admin is impossible — the only way is a direct DELETE against admin_settings. Same for the ceiling reset timestamp.
My bug, introduced in #224: I added a text setting whose whole design says empty is a working configuration, into a validator that had been written when every text setting had to be non-empty, and did not notice the two disagreed.
Fix
Whether empty is allowed belongs with the setting, not with the type. Add a flag to the DEFINITIONS row — the same place the type and fallback already live, so a new setting declares it once and nothing else needs to know.
The blanket check stays the default, because for a setting with a non-empty fallback, refusing empty is correct and is the case the message was written for.
Verification
Setting intakeNotifyEmail to '' succeeds and getSettings() then reports ''. Setting greetingFormat to '' is still refused. Found while clearing the code smells for #181.
`PUT /api/admin/settings` refuses any empty text value:
```ts
if (typeof raw !== 'string' || raw.trim() === '') {
return res.status(400).json({ error: `${name} cannot be empty` });
}
```
That is right for two of the four text settings and wrong for the other two.
| Setting | Fallback | Empty is… |
|---|---|---|
| `greetingFormat` | `Hi {{firstName}},` | wrong — an empty format renders every greeting as nothing, which reads as a bug in the email |
| `greetingFallback` | `Hi,` | wrong, same reason |
| `intakeNotifyEmail` | `''` | **the documented default**, meaning "do not notify" |
| `intakeCeilingResetAt` | `''` | **the documented default**, meaning "no reset recorded" |
So `intakeNotifyEmail` can be set but never cleared. Once an address is in there, turning intake notifications back off through the admin is impossible — the only way is a direct `DELETE` against `admin_settings`. Same for the ceiling reset timestamp.
My bug, introduced in #224: I added a text setting whose whole design says empty is a working configuration, into a validator that had been written when every text setting had to be non-empty, and did not notice the two disagreed.
## Fix
Whether empty is allowed belongs with the setting, not with the type. Add a flag to the `DEFINITIONS` row — the same place the type and fallback already live, so a new setting declares it once and nothing else needs to know.
The blanket check stays the default, because for a setting with a non-empty fallback, refusing empty is correct and is the case the message was written for.
## Verification
Setting `intakeNotifyEmail` to `''` succeeds and `getSettings()` then reports `''`. Setting `greetingFormat` to `''` is still refused. Found while clearing the code smells for #181.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
PUT /api/admin/settingsrefuses any empty text value:That is right for two of the four text settings and wrong for the other two.
greetingFormatHi {{firstName}},greetingFallbackHi,intakeNotifyEmail''intakeCeilingResetAt''So
intakeNotifyEmailcan be set but never cleared. Once an address is in there, turning intake notifications back off through the admin is impossible — the only way is a directDELETEagainstadmin_settings. Same for the ceiling reset timestamp.My bug, introduced in #224: I added a text setting whose whole design says empty is a working configuration, into a validator that had been written when every text setting had to be non-empty, and did not notice the two disagreed.
Fix
Whether empty is allowed belongs with the setting, not with the type. Add a flag to the
DEFINITIONSrow — the same place the type and fallback already live, so a new setting declares it once and nothing else needs to know.The blanket check stays the default, because for a setting with a non-empty fallback, refusing empty is correct and is the case the message was written for.
Verification
Setting
intakeNotifyEmailto''succeeds andgetSettings()then reports''. SettinggreetingFormatto''is still refused. Found while clearing the code smells for #181.