Files
HealthLog/src/__tests__/proxy-well-known-public.test.ts
T
Marc-André Bombeck 7bef199039 v1.4.33 — polish and reliability
Quality-leap release between two HealthKit milestones. The headline is a P0 hotfix for the `/api/analytics` 500 that broke the Insights mother page for any account with more than a few thousand measurements: the six per-metric status helpers were spreading the entire numeric history into `Math.min` / `Math.max`, which trips a stack overflow once a single argument list exceeds the V8 spread cap. Both the surfaced symptom and the latent risk in five sibling helpers were folded onto a reduce-based min/max path.

Around that hotfix landed a deep polish pass: the Insights mother page now defers three below-the-fold blocks behind `next/dynamic` to trim the cold mount cost, the analytics endpoint gained a `?slice=summaries` slim slice that the per-metric sub-pages now ride, the Coach snapshot builder picked up a 60 s LRU keyed on `(userId, scope)`, the Settings shell consolidated three duplicate copies of the about / notifications / about-dropdown surfaces, the navigation strip dropped a redundant "Home" group label and a colliding "Notifications" sibling, every icon-only button on the medications and admin surfaces gained an accessible name, every Progress bar gained one too, three pages had their heading hierarchy repaired to a sequential h1 → h2 → h3, the mobile Coach FAB now hides while a chart tooltip is open so it cannot occlude the read-out, and the auth shell normalised every authenticated route to a single `max-w-screen-xl` container.

Also lands the Apple App Site Association handler at `/.well-known/apple-app-site-association` on every host that fronts the app, advertising the iOS bundle's App ID prefix (S8WDX4W5KX.dev.healthlog.app) under `webcredentials.apps` so the passkey ceremony shares cleanly between the web origin and the iOS app.

The release closes nineteen issues from a five-surface audit + a runtime bug-hunt pass, plus six follow-up tracks of polish across the affected surfaces.
2026-05-16 19:46:43 +02:00

75 lines
2.9 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import { NextRequest } from "next/server";
/**
* v1.4.33 — `/.well-known/*` is a credential-free IETF discovery
* namespace (RFC 8615). Apple in particular reads
* `/.well-known/apple-app-site-association` without a session to wire
* Web Credentials (passkey sharing) and Universal Links to the iOS
* bundle. This guard locks the proxy allowlist in place so a future
* refactor of `src/proxy.ts` can't silently re-gate the namespace
* behind a session cookie and break the Apple CDN fetch.
*/
vi.mock("@/lib/process-type", () => ({
shouldRunWeb: () => true,
}));
import { proxy } from "../proxy";
function makeRequest(
pathname: string,
cookies: Record<string, string> = {},
): NextRequest {
const cookieHeader = Object.entries(cookies)
.map(([k, v]) => `${k}=${v}`)
.join("; ");
return new NextRequest(`http://localhost${pathname}`, {
headers: cookieHeader ? { cookie: cookieHeader } : {},
});
}
describe("proxy.ts /.well-known/* public-allowlist (v1.4.33)", () => {
it("does not 307 unauthenticated requests for the AASA file", () => {
const res = proxy(makeRequest("/.well-known/apple-app-site-association"));
expect(res.status).toBe(200);
expect(res.headers.get("location")).toBeNull();
});
it("does not 307 a pending-onboarding session away from the AASA file", () => {
// Apple's CDN fetch carries no cookies, so this branch is mainly
// a belt-and-braces check; the redirect would only fire for a
// human visitor who happened to have a half-finished onboarding
// session and typed the URL by hand. Either way the asset must
// answer 200 with the JSON body unchanged.
const res = proxy(
makeRequest("/.well-known/apple-app-site-association", {
healthlog_session: "sess-1",
hl_onboarding: "pending",
}),
);
expect(res.status).toBe(200);
expect(res.headers.get("location")).toBeNull();
});
it("admits any other future /.well-known/* discovery file", () => {
// The allowlist entry is a `/.well-known/` prefix so future
// additions (e.g. `/.well-known/security.txt` or
// `/.well-known/openid-configuration`) don't need a second proxy
// edit. This check fails the moment the prefix is tightened to
// a literal `/.well-known/apple-app-site-association` only.
const res = proxy(makeRequest("/.well-known/security.txt"));
expect(res.status).toBe(200);
expect(res.headers.get("location")).toBeNull();
});
it("still redirects unauthenticated requests for protected pages", () => {
// Negative check — confirms the test fixture would catch a real
// regression. `/insights` is not public; an unauthenticated visit
// must still 307 to /auth/login.
const res = proxy(makeRequest("/insights"));
expect([307, 308]).toContain(res.status);
expect(res.headers.get("location")).toMatch(/\/auth\/login/);
});
});