feat(intake): settings for the submission ceiling (#227)

A count type beside the existing hours, text and choice readers. resolveHours would have worked — it is parseFloat with a positive guard — but calling a submission ceiling an "hours" setting is a lie in the type name that every later reader has to decode. Whole numbers only, so a ceiling of 12.5 is a typo rather than a preference, and a malformed value falls back rather than yielding a NaN that compares false against everything and silently disables the limit.

resetDb is widened to clear intake_ settings as well as email_ ones. It deliberately does not truncate admin_settings, so a ceiling of 1 left behind by one suite would make every later suite's submissions refuse with a 503, in files that never mention a ceiling. The comment there already records that exact failure happening once with an email template subject, which reached the favorite-alert tests and failed five of them somewhere else entirely.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 16:19:45 -05:00
co-authored by Claude Opus 5
parent 722ff91378
commit 22215f32eb
3 changed files with 43 additions and 4 deletions
@@ -33,7 +33,10 @@ describe('GET /api/admin/settings', () => {
draftingModel: 'claude-sonnet-5',
// Empty by default: nowhere to send the intake notification is a working
// configuration, and means simply do not send one (#224).
intakeNotifyEmail: ''
intakeNotifyEmail: '',
intakeDailyCeiling: 100,
intakeLinkAlertThreshold: 20,
intakeCeilingResetAt: ''
});
});
});
+7 -1
View File
@@ -40,7 +40,13 @@ export async function resetDb(): Promise<void> {
// it silently changes the mail every later suite asserts on. That is not
// hypothetical: a subject of "Gone" written by the template tests reached the
// favorite-alert tests and made five of them fail somewhere else entirely.
await testPool.query(`DELETE FROM admin_settings WHERE key LIKE 'email\_%'`);
//
// Same reasoning, same failure, for the intake settings (#227): a ceiling of
// 1 left behind by the ceiling suite makes every later submission refuse with
// a 503, in files that never mention a ceiling.
await testPool.query(
`DELETE FROM admin_settings WHERE key LIKE 'email\_%' OR key LIKE 'intake\_%'`
);
}
export async function closeDb(): Promise<void> {