mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
`User.glucoseUnit` has existed since v1.2 and around thirty surfaces read it — the dashboard tiles, the glucose page, the targets panel, the CSV and FHIR exports, the doctor report, the Coach snapshot, the low-reading push copy. Nothing could ever write it. No route, no schema, no field on any form, so every account resolved to the mg/dL default and the mmol/L half of the app was unreachable code. Anyone who reads glucose in mmol/L converted in their head on every screen. This is the missing end: a `GET`/`PATCH /api/auth/me/glucose-unit` scalar on the pattern the unit-preference endpoint next door established, and a dropdown in the profile form beside it. Deliberately its own control rather than a branch of metric/imperial: metric countries are split on which unit they read glucose in, so one dropdown would get half of them wrong. Storage is untouched and stays untouched. Every reading is written in mg/dL by every ingest path and the unit only selects a display branch, so nothing already recorded is reinterpreted. The entry form moved with the preference, which is the half that could have hurt: it asks in the chosen unit and inverts through `toCanonicalMgdl` on submit, so a 5.3 typed by an mmol/L reader is filed as 95 mg/dL rather than as 5.3 — a value the plausibility band accepts in silence and every surface reads back as a severe hypo. The contract gains the endpoint and nothing else; the account payload already carried the field.
96 lines
4.1 KiB
TypeScript
96 lines
4.1 KiB
TypeScript
/**
|
|
* Query keys — auth session, passkeys, and per-user account preferences.
|
|
* Part of the centralized factory; aggregated in `./index.ts`.
|
|
*/
|
|
export const authKeys = {
|
|
auth: () => ["auth"] as const,
|
|
/**
|
|
* v1.4.40 W-RSC — the `useAuth` hook's `["auth", "me"]` shape was a
|
|
* recurring source of factory drift (audit H1 — "`useAuth` uses
|
|
* `["auth", "me"]` but `queryKeys.auth()` returns `["auth"]`"). Both
|
|
* shapes share the `["auth"]` prefix so existing prefix-invalidations
|
|
* still match, but the centralised name makes the call site
|
|
* obviously factory-routed.
|
|
*/
|
|
authMe: () => ["auth", "me"] as const,
|
|
authRegistrationStatus: () => ["auth", "registration-status"] as const,
|
|
authOidcStatus: () => ["auth", "oidc", "status"] as const,
|
|
/**
|
|
* v1.4.40 W-RSC — Settings → AI surfaces and the targets editor
|
|
* subscribe to the user-thresholds API. Centralise the key so a
|
|
* future rename (e.g. `["user","limits"]`) doesn't drift across the
|
|
* three call sites (settings/thresholds-editor-section,
|
|
* settings/ai-section, targets/target-edit-sheet).
|
|
*/
|
|
userThresholds: () => ["user", "thresholds"] as const,
|
|
/**
|
|
* v1.7.0 — Settings → Display metric/imperial control reads its
|
|
* current value from `GET /api/auth/me/unit-preference`. The PATCH
|
|
* mutation also invalidates `authMe()` so `useAuth().unitPreference`
|
|
* (and every chart display transform that keys off it) re-renders
|
|
* without a manual reload.
|
|
*/
|
|
userUnitPreference: () => ["user", "unit-preference"] as const,
|
|
/**
|
|
* The mg/dL vs mmol/L glucose display control behind
|
|
* `GET /api/auth/me/glucose-unit`. A separate axis from the
|
|
* metric/imperial preference above — metric countries are split on
|
|
* which one they read glucose in — so it carries its own key. The
|
|
* PATCH also invalidates `authMe()`, since every glucose surface
|
|
* resolves the unit from the account payload rather than from here.
|
|
*/
|
|
userGlucoseUnit: () => ["user", "glucose-unit"] as const,
|
|
|
|
passkeys: () => ["passkeys"] as const,
|
|
|
|
/**
|
|
* v1.23 — the user-facing active-session list behind
|
|
* `GET /api/auth/me/sessions`. Revoking a single session or signing out
|
|
* everywhere invalidates this key so the surface re-reads the live set.
|
|
*/
|
|
sessions: () => ["auth", "sessions"] as const,
|
|
|
|
/**
|
|
* v1.23 — the shared security-activity feed behind
|
|
* `GET /api/auth/me/security-activity` (logins, MFA, password change,
|
|
* session revoke, exports, deletions). Consumed by the account-security
|
|
* surface and the privacy dashboard.
|
|
*/
|
|
securityActivity: () => ["auth", "security-activity"] as const,
|
|
|
|
/**
|
|
* v1.23 — the security settings hub reads second-factor status (TOTP
|
|
* enabled, recovery codes remaining, registered security keys, passkey-nudge
|
|
* dismissal) from `GET /api/auth/me/mfa`. Mutations that change a factor
|
|
* invalidate this key so the hub reflects the new state immediately.
|
|
*/
|
|
mfaStatus: () => ["auth", "mfa", "status"] as const,
|
|
|
|
/**
|
|
* v1.23 — the "remember this device" trusted-device list behind
|
|
* `GET /api/auth/me/trusted-devices`. Revoking a device (or all of them)
|
|
* invalidates this key so the surface re-reads the live set.
|
|
*/
|
|
trustedDevices: () => ["auth", "trusted-devices"] as const,
|
|
|
|
userAiProvider: () => ["user", "ai-provider"] as const,
|
|
userProfile: () => ["user", "profile"] as const,
|
|
/**
|
|
* v1.7.0 — the roaming notification prefs blob behind
|
|
* `GET/PATCH /api/auth/me/notification-prefs` (medication delivery
|
|
* default + mood reminder hour). Distinct from
|
|
* `notificationsPreferences()` (the per-event push toggles on the
|
|
* `/notifications` page) so the two never collide in the cache.
|
|
*/
|
|
authNotificationPrefs: () => ["auth", "me", "notification-prefs"] as const,
|
|
|
|
/**
|
|
* v1.4.25 W5e — per-user, per-metric-class source priority. The
|
|
* Settings → Sources surface reads + writes this key; saving
|
|
* invalidates `analytics()` because the cumulative-metric aggregator
|
|
* folds the new priority into the SLEEP_DURATION daily total
|
|
* immediately.
|
|
*/
|
|
sourcePriority: () => ["auth", "source-priority"] as const,
|
|
};
|