mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
fix(measurements): reject impossible dayKey values (2026-02-30 etc)
The dayKey validator regex matched any YYYY-MM-DD string — including impossible dates like 2026-02-30 or 2026-13-01. `new Date()` silently overflows those values into the following month, so the drill-down returned rows from a different calendar day than the user asked for. No 422 was emitted; the response was syntactically well-formed and pointed at the wrong day. The same helper feeds the admin drain route, so a malformed CLI invocation had the same blast radius. Add a refine that round-trips the parsed Date back to ISO and rejects when the slice no longer matches the input.
This commit is contained in:
1 parent
67ca526708
commit
c2f436720f
2 files changed
+35
No files matched your search
@@ -284,4 +284,23 @@ describe("GET /api/measurements — schema rejections (W10 reconcile)", () => {
|
||||
expect(prisma.measurement.findMany).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
// v1.4.37 W10 H2 — `2026-02-30` is a YYYY-MM-DD string but not a
|
||||
// real calendar date. `new Date()` silently overflows it to March
|
||||
// 2, so the drill-down would point at the wrong day. The validator
|
||||
// refine must reject it at parse time.
|
||||
it("rejects impossible calendar dates on dayKey (2026-02-30)", async () => {
|
||||
const res = await GET(
|
||||
getRequest("type=ACTIVITY_STEPS&dayKey=2026-02-30"),
|
||||
);
|
||||
expect(res.status).toBe(422);
|
||||
expect(prisma.measurement.findMany).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects impossible month on dayKey (2026-13-01)", async () => {
|
||||
const res = await GET(
|
||||
getRequest("type=ACTIVITY_STEPS&dayKey=2026-13-01"),
|
||||
);
|
||||
expect(res.status).toBe(422);
|
||||
expect(prisma.measurement.findMany).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -299,6 +299,22 @@ export const listMeasurementsSchema = z
|
||||
dayKey: z
|
||||
.string()
|
||||
.regex(/^\d{4}-\d{2}-\d{2}$/, "dayKey must be YYYY-MM-DD")
|
||||
// v1.4.37 W10 — a `YYYY-MM-DD` string can satisfy the regex while
|
||||
// still being an impossible calendar date (`2026-02-30`,
|
||||
// `2026-13-01`). `new Date("2026-02-30T00:00:00Z")` silently
|
||||
// overflows to March 2, so the drill-down would return rows from
|
||||
// a different day than the user asked for. The same helper feeds
|
||||
// the admin drain route, so a malformed CLI invocation has the
|
||||
// same blast radius. Reject the impossible shapes at the
|
||||
// validator instead.
|
||||
.refine(
|
||||
(s) => {
|
||||
const parsed = new Date(`${s}T00:00:00Z`);
|
||||
if (Number.isNaN(parsed.getTime())) return false;
|
||||
return s === parsed.toISOString().slice(0, 10);
|
||||
},
|
||||
"dayKey must be a real calendar date (YYYY-MM-DD)",
|
||||
)
|
||||
.optional(),
|
||||
})
|
||||
.refine(
|
||||
|
||||
Reference in new issue
Block a user