Files
HealthLog/eslint-plugins/healthlog/index.js
T
Marc-André Bombeck 7c5ff89def feat(lint): refuse UTC day keys outside the time zone module
`instant.toISOString().slice(0, 10)` and parsing a key back as UTC
midnight are the idioms behind every day-boundary fix this year: the
evening west of UTC and the small hours east of it land on the
neighbouring day. A new rule, healthlog/no-utc-day-key, refuses them in
src/ outside src/lib/tz and tests, and refuses a disable directive for
itself that is not next-line or gives no reason.

The time zone module now names every legitimate form: userDayKey for a
person's day, dateOnlyKey / dateOnlyAtNoonUtc / dayKeyAsUtcMidnight for
date-only values and day labels, daysBetweenDateKeys / weekdayOfDateKey /
isCalendarDateKey / statedDateKey for key arithmetic and parsing.

Of the 133 sites the rule found, 84 are gone. Most moved onto a named
helper with no change in behaviour; these changed behaviour:

- cycle calendar, insights, Coach snapshot and prediction refresh start
  their lookbacks at the first instant of the user's day
- a model-transcribed date like "June 10, 2026" no longer lands a day
  early in a process east of UTC (documents and lab scans)
- a custom report range covers exactly the picked days in the profile
  zone instead of starting the evening before west of UTC
- date-of-birth pickers cap at the user's today, not the UTC one
- an allergy onset date is stored at noon UTC like other date-only values
- the report's cycle summary, the Coach's usual BP range and the intake
  projector's rollup recompute use the user's day
- vaccination dates render as dates instead of the previous evening

49 remain, each with its reason on the line above: 39 UTC by design (15
file name stamps, rollup and object keys, the UTC-day score engines) and
10 marked baseline. A guard test requires a classified reason on every
directive and holds the baseline to a ceiling that only goes down.
2026-10-01 09:59:57 +02:00

47 lines
2.2 KiB
JavaScript

/**
* @fileoverview Aggregates the project-local `healthlog/*` ESLint rules
* into a single plugin object for the flat config.
*
* - `queryKey-factory` — bare-array queryKey / mutationKey bypass guard.
* - `safe-fetch-required` — outbound fetch must route through safeFetch.
* - `api-fetch-required` — client /api/ calls must route through apiFetch.
* - `no-raw-palette-color` — ban raw Tailwind palette utilities in app UI.
* - `spacing-scale` — no pt-/pb- overrides on gap-based Card slots,
* and no off-scale `5` step on a bg-card shell.
* - `job-handler-outcome` — pg-boss bindings route through createAndWork,
* whose handler returns a JobOutcome.
* - `no-default-zone-literal` — the default zone is DEFAULT_TIMEZONE from
* src/lib/tz/format, never written out.
* - `no-utc-day-key` — a day is cut through the tz module, not by
* slicing an ISO string or parsing UTC midnight.
*/
"use strict";
const queryKeyFactory = require("./queryKey-factory.js");
const safeFetchRequired = require("./safe-fetch-required.js");
const apiFetchRequired = require("./api-fetch-required.js");
const noRawPaletteColor = require("./no-raw-palette-color.js");
const spacingScale = require("./spacing-scale.js");
const jobHandlerOutcome = require("./job-handler-outcome.js");
const noDefaultZoneLiteral = require("./no-default-zone-literal.js");
const noUtcDayKey = require("./no-utc-day-key.js");
module.exports = {
rules: {
"queryKey-factory": queryKeyFactory.rules["queryKey-factory"],
"safe-fetch-required": safeFetchRequired,
"api-fetch-required": apiFetchRequired,
"no-raw-palette-color": noRawPaletteColor,
"spacing-scale": spacingScale,
// Same module as `no-raw-palette-color`, registered under a second
// name so the flat config can run the `dracula` check as its own
// named rule (now error-level too; the staged warn phase ended with
// the semantic sweep). See the rule header.
"no-dracula-utility": noRawPaletteColor,
"job-handler-outcome": jobHandlerOutcome,
"no-default-zone-literal": noDefaultZoneLiteral,
"no-utc-day-key": noUtcDayKey,
},
};