Repository navigation
96e9567a: finish consolidating behaviour-divergent helpers (Berlin today, json/cleanItem, realDate docs) - #329
Merged
Conversation
…iveDates (intake 96e9567a AC2) Follow-up to the AC2 Berlin-today unification: releaseSlots.todayInTimezone, podcast/publication.localDate, and the calendar cardInvite private localDate plus an inline en-CA formatter all recomputed the civil date of an instant. They now delegate to relativeDates.todayIn; releaseSlots.zonedTimeToUtc and its private offset math now delegate to relativeDates.civilToUtc. No consumer-visible behavior change (DST parity pinned by tests).
…rough shared helpers (intake 96e9567a AC4) Follow-up to the AC4 shared-helper consolidation: five true duplicates of http.json/http.noStoreJson/http.jsonResponse/http.parseJsonObjectEventOrEmpty and db/cleanItem remained without a 'Kept separate' rationale. The router, the email-templates and api-token routes, and the api-token and session db modules now use the canonical helpers. Deliberate header/behavior variants (docs CORS, no-referrer, nosniff, error-throwing parseBody) keep their existing 'Kept separate' comments and are untouched.
…gence (intake 96e9567a AC1) realDate (sponsor/finance records) accepts four-digit years 0000-0099 via its parse-based roundtrip; relativeDates.isCalendarDate (task-date gate) rejects them because its Date.UTC roundtrip maps those years onto 1900-1999. Keep both behaviors deliberately: task dates want the stricter gate, and no consumer resolves a relative word onto a year-0099 date. Divergence is now documented at the helper and pinned by tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #259 (the first 96e9567a consolidation pass, merged 2026-11-03). Re-inventoried all four helper families on current main: families (a) and (c) were already consolidated; families (b) and (d) still had true duplicates that the first pass missed, plus one undocumented divergence in (a). This PR finishes the job. No consumer-visible behavior changes.
Per-helper divergence decisions
backend/src/podcast/releaseSlots.ts:99todayInTimezone(timezone, now)relativeDates.todayIn(tz, now)todayIndirectly.backend/src/podcast/publication.ts:75localDate(utcInstant, timezone)(formatToParts join)relativeDates.todayInscheduledAtstrings); body is now a one-line delegation, so there is one formatter. DST parity pinned by tests.backend/src/calendar/cardInvite.ts:558privatelocalDate(iso, timeZone)+ inline en-CA formatter at :355relativeDates.todayInen-CAformat of the same instant); both call sites ofadoptEventDateand the stored-holddatenow use the canonical helper.backend/src/podcast/releaseSlots.tszonedTimeToUtc(date, time, tz)+ privatetimezoneOffsetMsrelativeDates.civilToUtc(day, time, tz)cli/src/format.mjsberlinToday/todayIncli/test/berlin-today.test.mjspinning behavioral parity. Not touched.backend/src/routes/intakeAuth.tsemailDocumentsandsponsorLeadsconsume it;tests/intake-auth.test.ts). Verified, nothing to do.backend/src/router.ts:153privatejsonResponse+JSON_HEADERShttp.jsonResponsebackend/src/routes/emailTemplates.tsjsonhttp.noStoreJsonContent-Type+Cache-Control: no-store) and body.backend/src/routes/apiTokens.ts:97jsonhttp.jsonnoStoreJson/parseJsonObjectBody— this was a leftover.backend/src/routes/emailTemplates.tsparseBody(event)http.parseJsonObjectEventOrEmpty{}, array/primitive/invalid JSON →null, object passthrough.backend/src/db/apiTokens.ts:24genericcleanItem<T>db/cleanItem.cleanItembackend/src/db/sessions.ts:19cleanItemdb/cleanItem.cleanItemcleanDbItem<Session>per thedb/notifications.tsconvention.docs/http.ts,documents/reviews.ts,routes/sponsorDocs.ts,sponsorContracts.ts,sponsorCommunications.ts,sponsorFinance.ts,documentExports.ts,newsletter/markdownPreview.ts,routes/company.ts,routes/offers.ts,db/cards.ts,db/tasks.ts,db/templates.ts,db/intake.tsrelativeDates.isCalendarDatevssponsorCrm/model.realDaterealDate's parse-based roundtrip accepts them,isCalendarDate'sDate.UTCroundtrip rejects them. Kept: task-date resolution wants the stricter gate (no relative word may land on a year-0099 date) and records keep the looser parse gate. Documented at the helper and pinned by tests.Tests
backend/tests/berlin-today.test.ts— new DST-edge parity test routinglocalDate/todayIn/berlinTodaythrough one implementation.backend/tests/podcast-release-slots.test.ts— DST conversion assertions now run against the canonicalcivilToUtc/todayIn.backend/tests/real-date.test.ts— new test pinning the documentedisCalendarDate/realDateyear<0100 divergence.backend/tests/shared-helpers.test.ts,api-tokens.test.ts,sponsor-docs.test.ts,card-calendar-invites.test.ts,intake-auth.test.ts— existing targeted tests prove the rewired consumers are behavior-identical.All targeted tests pass (68 across the 8 files);
tsc --noEmitclean. Full suite deliberately not run locally.Task: 96e9567a