release: v1.32.0 — hardening and scalability (#580)

* release: prepare v1.32.0

* test: stabilize water capture re-entry
This commit is contained in:
Marc-André Bombeck authored and GitHub committed 2026-07-22 04:14:15 +02:00
1 parent b01822be48
commit 62eb431d66
372 files changed
+25178 -8561

No files matched your search

@@ -151,6 +151,16 @@ describe("withings/callback atomic nonce consumption (M3)", () => {
// Exactly one delete-attempt per leg — the atomic shape collapses
// findUnique + delete into a single round-trip.
expect(deleteMock).toHaveBeenCalledTimes(2);
const upsert = vi.mocked(prisma.withingsConnection.upsert).mock
.calls[0]![0];
expect(upsert.update).toMatchObject({
webhookSubscriptionState: Prisma.DbNull,
webhookSubscriptionRetryAt: expect.any(Date),
});
expect(upsert.create).toMatchObject({
webhookSubscriptionState: Prisma.DbNull,
webhookSubscriptionRetryAt: expect.any(Date),
});
// Exactly one leg landed on `withings=connected`, exactly one
// landed on the replay branch (`withings=error&reason=replay`).
+10 -5
View File
@@ -171,6 +171,7 @@ export const GET = apiHandler(async (request: NextRequest) => {
const tokens = await exchangeCode(code, creds);
const expiresAt = new Date(Date.now() + tokens.expires_in * 1000);
const subscriptionRetryAt = new Date();
// v1.4.25 W5d — persist the OAuth scope we requested. The token
// response doesn't echo the granted scopes back as a top-level
@@ -187,6 +188,8 @@ export const GET = apiHandler(async (request: NextRequest) => {
refreshToken: encrypt(tokens.refresh_token),
tokenExpiresAt: expiresAt,
scope: WITHINGS_OAUTH_SCOPE,
webhookSubscriptionState: Prisma.DbNull,
webhookSubscriptionRetryAt: subscriptionRetryAt,
},
create: {
userId: user.id,
@@ -195,12 +198,14 @@ export const GET = apiHandler(async (request: NextRequest) => {
refreshToken: encrypt(tokens.refresh_token),
tokenExpiresAt: expiresAt,
scope: WITHINGS_OAUTH_SCOPE,
webhookSubscriptionState: Prisma.DbNull,
webhookSubscriptionRetryAt: subscriptionRetryAt,
},
});
// Subscribe to webhooks in background
setupWebhook(user.id).catch((err) =>
getEvent()?.addWarning("Webhook setup failed: " + err),
// Reconcile every category from a clean state after connect/reconnect.
setupWebhook(user.id).catch(() =>
getEvent()?.addWarning("Webhook setup failed"),
);
await auditLog("withings.connect", {
@@ -220,8 +225,8 @@ export const GET = apiHandler(async (request: NextRequest) => {
);
response.cookies.delete(WITHINGS_OAUTH_STATE_COOKIE);
return response;
} catch (err) {
getEvent()?.setError(err);
} catch {
getEvent()?.setError(new Error("Withings callback failed"));
return NextResponse.redirect(
new URL(
"/settings/integrations?withings=error&reason=token",