mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
feat(api): legacy Withings webhook counter + migration URL in warning
The legacy ?secret=... route stays alive through v1.4.27 so existing Withings subscriptions keep delivering while users re-subscribe. The release-gate cannot tell when "legacy form usage has trended to zero" because the route only emits a fire-and-forget Wide Event warning and the warning text omits the destination URL anyone watching the access log would need. This pass adds: - An in-memory `withings.webhook.legacy_form_total` counter scoped to the process (the right granularity for "since cold-start" usage). - A `getLegacyFormTotal()` accessor + a test-only reset helper so the counter is observable without a backchannel. - A `counters.withingsWebhookLegacyFormTotal` field on the existing `/api/admin/status` payload — the natural surface for ops counters alongside the user / measurement / worker blocks. - The warning text now spells out `/api/withings/webhook/[token]` and the "re-subscribe with the path-segment token form" instruction. - Two new assertions on the webhook test (counter increments on the query path, stays at zero on the header path, warning contains the migration URL) and one new assertion on the admin-status test.
This commit is contained in:
1 parent
6f3b901c3e
commit
9ef1dd6e02
4 files changed
+92
-3
No files matched your search
@@ -44,9 +44,17 @@ vi.mock("@/lib/jobs/worker-status", () => ({
|
||||
})),
|
||||
}));
|
||||
|
||||
// v1.4.25 W21 Fix-K — `/api/admin/status` now reads the legacy-form
|
||||
// counter from the Withings webhook module. Mock it at module boundary
|
||||
// so the test fixture stays deterministic.
|
||||
vi.mock("@/app/api/withings/webhook/route", () => ({
|
||||
getLegacyFormTotal: vi.fn(() => 0),
|
||||
}));
|
||||
|
||||
import { GET } from "../route";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { requireAdmin, HttpError } from "@/lib/api-handler";
|
||||
import { getLegacyFormTotal } from "@/app/api/withings/webhook/route";
|
||||
|
||||
const ADMIN_CTX = {
|
||||
session: { id: "s1", expiresAt: new Date(Date.now() + 3_600_000) },
|
||||
@@ -169,4 +177,13 @@ describe("GET /api/admin/status (integration health summary)", () => {
|
||||
const tokenCallArgs = vi.mocked(prisma.apiToken.count).mock.calls[0]?.[0];
|
||||
expect(tokenCallArgs).toEqual({ where: { revoked: false } });
|
||||
});
|
||||
|
||||
it("surfaces the legacy Withings webhook counter on the counters block (Fix-K sec-M2)", async () => {
|
||||
vi.mocked(getLegacyFormTotal).mockReturnValue(7);
|
||||
const res = await GET();
|
||||
const body = (await res.json()) as {
|
||||
data: { counters: { withingsWebhookLegacyFormTotal: number } };
|
||||
};
|
||||
expect(body.data.counters.withingsWebhookLegacyFormTotal).toBe(7);
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import { apiHandler, requireAdmin } from "@/lib/api-handler";
|
||||
import { apiSuccess } from "@/lib/api-response";
|
||||
import { annotate } from "@/lib/logging/context";
|
||||
import { getWorkerStatus } from "@/lib/jobs/worker-status";
|
||||
import { getLegacyFormTotal } from "@/app/api/withings/webhook/route";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
// Build timestamp (set at build time via next.config)
|
||||
@@ -89,5 +90,11 @@ export const GET = apiHandler(async () => {
|
||||
webPush: webPushConfigured ? { configured: true } : null,
|
||||
bugReport: bugReportConfigured ? { configured: true } : null,
|
||||
},
|
||||
// v1.4.25 W21 Fix-K — in-memory counters that the release-gate can
|
||||
// read to confirm "legacy form usage trending toward zero" before
|
||||
// the v1.4.27 cut of the legacy Withings webhook route.
|
||||
counters: {
|
||||
withingsWebhookLegacyFormTotal: getLegacyFormTotal(),
|
||||
},
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user