feat(sla): validate schedule/holiday JSON on write (reject malformed, 422) #420
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/PMS-604-sla-json-validation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Follow-up to PMS-585. The SLA business-hours and holiday-calendar upsert endpoints validated only the
namelength;scheduleandholidayswereserde_json::Valuewith#[serde(default)]and no#[validate(...)], so any JSON shape was accepted and stored. The clock reader then silently skips unknown weekday keys, malformed windows, and unparseable holiday entries, so a typo'd payload is persisted and quietly ignored, distorting SLA due-time math (a day the admin believes is closed, or a holiday that never takes effect).This adds strict write-time validation for both fields. It is a validation gap independent of the JSONB-vs-normalized decision (PMS-585 kept JSONB; see
dev-docs/sla-jsonb-vs-normalized.md).How
parse_weekday_key/parse_hhmmfrom private topub(crate)so the strict validator accepts exactly the key set and time formats the engine parses. The strict writer and the tolerant reader single-source the same helpers and cannot drift.validate_business_schedule(custom validator onUpsertBusinessHoursRequest::schedule): accepts null / empty object (24/7), or a weekday-keyed object whose day values are null, a{start, end}window, or an array of windows with parseableHH:MM(:SS) times andendstrictly afterstart. Everything else is a 422.validate_holiday_list(custom validator onUpsertHolidayCalendarRequest::holidays): accepts null / empty array, or an array of bareYYYY-MM-DDstrings or{date, name}objects with a parseable date. Everything else is a 422.schedule/holidays) so the frontend binds the message inline rather than as a generic banner.Tests
cargo test -p mokosh-server --lib modules::sla::models(10 tests): valid/empty shapes accepted; malformed payloads (non-object schedule, unknown weekday key, non-window day value, missing/unparseable times,end <= start, non-array holidays, non-date entries, impossible dates) rejected; plus one end-to-end.validate()per request confirming the error keys onto the right field.The frontend inline-error wiring (AC3) ships as a separate mokosh-apps PR; the server already surfaces these as field-keyed 422s that the existing form banner shows in the meantime.
Closes PMS-604.
PMS-604. Same gap as the schedule field: `holidays` was an unvalidated `serde_json::Value`, and the clock reader (`parse_holidays`) silently skips unparseable entries. A holiday the admin meant to exclude but mistyped would be stored and quietly ignored, so the SLA clock keeps running on what should be a day off. Add `validate_holiday_list`, mirroring the reader's accepted shapes: null / empty array for "no holidays", otherwise an array whose entries are each a bare "YYYY-MM-DD" string or a {date, name} object with a parseable date. Any other shape or a bad date is rejected with a 422 keyed onto the `holidays` field. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>