mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
Consolidated hotfix landing the findings from a six-axis audit
covering mobile security, UX + accessibility, code quality + docs,
README + discoverability, web performance, and mobile-deep responsive
behaviour. None of the changes break the public API or the existing
data shape; every fix is additive and SAFE under the v1.4.34.x web
freeze. Full audit reports live in `.planning/round-audit-*.md`.
Security
- Password rotation now wipes API tokens + refresh tokens in the
same `$transaction` as session revocation. A stolen iOS Bearer no
longer survives a user-initiated password change or an admin reset.
- `/.well-known/` proxy bypass tightened to an explicit-allowlist
`Set`. Stale `/api/auth/codex/callback` PUBLIC_PATHS entry dropped.
- HSTS gains `preload`. Withings host removed from the global CSP
and gated to the integration's own routes.
- `getClientIp` warns once per process on `TRUST_PROXY_HOPS`/XFF
mismatch + exposes a tagged helper for tighter universal buckets.
- Service worker rejects off-origin notification-click URLs. Offline
fallback body switched to a locale-neutral icon. Manifest gains
`scope`, `id`, `display_override`.
UX + accessibility
- i18n leaks closed on Dialog/Sheet close-X, ChartSkeleton's loading
announcement, and the notifications-section breadcrumb.
- Focus rings on bottom-nav, the More overflow button, and the
mobile top-bar user menu.
- Tap-target floor: Input / NativeSelect / Select / DateTimeInput
switch to `h-11 sm:h-10`.
- Admin chip-strip auto-scroll-into-view (matches v1.4.33 settings).
- List-page subtitles visible on mobile.
- Insights empty-state CTA vocabulary normalised so the link opens
the right measurement form (was silently failing for
BODY_TEMPERATURE / BLOOD_GLUCOSE / PULSE).
Mobile-deep
- `viewport.themeColor` reacts to light/dark mode.
- TopBar + Coach FAB reserve safe-area-inset-top / -bottom for
notched iPhones.
- Sonner toaster switches to `theme="system"`.
Code quality
- `SESSION_SECRET` dropped — the env var was documented as required
but never read by code. Three secrets, not four. Self-hosters
upgrading can delete the existing line.
- `toJson<T>()` helper consolidates seven Prisma JSON-cast sites.
- `db-compat.ts` gains a header docstring naming it the
schema-bootstrap path.
- Passkey response types adopted from `@simplewebauthn/server`;
`any` + eslint-disable pragmas drop out.
- Zero-TODO CI gate added at `.github/workflows/no-todo-markers.yml`.
Documentation + discoverability
- README rework: How-it-compares matrix, Apple Health + AI Coach
promoted to standalone Key-Features bullets, status block, latest
release + GHCR badges, OpenAPI pointer, three-secret Quick Start.
- openGraph + twitter cards now carry `images` and a
`summary_large_image` Twitter card.
- GitHub repo metadata: description tightened from 290 to 156
chars + keyword-front, `homepageUrl` flipped from a personal
tenant to the demo site, six generic / PII-adjacent topics
swapped for six high-intent ones.
- Five new user-facing docs: `docs/self-hosting/getting-started.md`,
`docs/self-hosting/reverse-proxy.md`,
`docs/integrations/apple-health.md`,
`docs/integrations/withings.md`,
`docs/integrations/ai-providers.md`.
- `docs/README.md` clarifies the docs tree as internal playbooks
vs the user-facing `docs.healthlog.dev` site.
64 lines
2.3 KiB
TypeScript
64 lines
2.3 KiB
TypeScript
"use client";
|
|
|
|
import * as React from "react";
|
|
|
|
import { Input } from "@/components/ui/input";
|
|
import { cn } from "@/lib/utils";
|
|
import { useTranslations } from "@/lib/i18n/context";
|
|
|
|
/**
|
|
* Native date input that hints the active locale via `lang=`. Browsers
|
|
* use this hint to render the calendar widget in dd.MM.yyyy / MM/dd/yyyy
|
|
* order, which is the user-visible format we want to follow the app's
|
|
* EN/DE preference. Wrapping the prop here keeps every callsite from
|
|
* having to pull `locale` out of `useTranslations()` just to feed it
|
|
* back into the same JSX prop, and guarantees a future date input
|
|
* cannot silently regress by forgetting the hint.
|
|
*
|
|
* v1.4.33 — height parity with `<Input>` and `<NativeSelect>`.
|
|
*
|
|
* Mobile Safari + Android Chrome give `type="date"` (and
|
|
* `type="datetime-local"`) an intrinsic chrome that puffs the
|
|
* field past Tailwind's `h-10`, so the DOB cell on
|
|
* `/settings/account` rendered ~6 px taller than its row siblings
|
|
* and roughly 12 px wider on the Pixel-5 mobile-pass screenshots.
|
|
* `appearance-none` switches the native widget off, then
|
|
* `min-h-10` re-asserts the contract that every other input
|
|
* primitive ships. The `:webkit-date-and-time-value` shadow rule
|
|
* forces the embedded value text to occupy at least one full line
|
|
* even when iOS shrinks its placeholder, so the field looks
|
|
* identical on both engines.
|
|
*/
|
|
// v1.4.34 IW-G — match the `<Input>` mobile floor (44 px) so date and
|
|
// datetime fields don't sit below the WCAG 2.5.5 target-size minimum
|
|
// on Pixel-5-class viewports. Desktop falls back to the 40 px norm.
|
|
const DATE_INPUT_HEIGHT_CLASSES =
|
|
"appearance-none min-h-11 h-11 sm:min-h-10 sm:h-10 [&::-webkit-date-and-time-value]:min-h-[1.5em]";
|
|
|
|
type InputProps = React.ComponentProps<typeof Input>;
|
|
type DateInputProps = Omit<InputProps, "type" | "lang">;
|
|
|
|
export function DateInput({ className, ...props }: DateInputProps) {
|
|
const { locale } = useTranslations();
|
|
return (
|
|
<Input
|
|
type="date"
|
|
lang={locale}
|
|
className={cn(DATE_INPUT_HEIGHT_CLASSES, className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function DateTimeInput({ className, ...props }: DateInputProps) {
|
|
const { locale } = useTranslations();
|
|
return (
|
|
<Input
|
|
type="datetime-local"
|
|
lang={locale}
|
|
className={cn(DATE_INPUT_HEIGHT_CLASSES, className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|