mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
refactor(v1.4.15): apply simplify-review safe suggestions
Drop dead exports + misleading comments + unreachable defaults flagged by phase-D simplify review (autonomous-yes items only): - channel-state: drop unused TEST_CONSTANTS re-export - retry-policy: drop unused RejectKind type alias - achievements: drop misleading "fallback" comment on exhaustive switch - notification-status-card: drop unreachable default in stateBadgeFor - withings: export isWithingsRefreshReauthFailure + dedupe inline classifier in /api/withings/status route - codex-slug-cache: drop test-only inspectCodexSlugCache helper; tests read getCachedCodexSlug() instead Findings 1, 2, 8, 9 deferred to v1.4.16 (require product call). Finding 11 is an explicit anti-finding. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
895c9f3b3a
commit
cd3b890067
9 files changed
+11
-51
No files matched your search
@@ -5,6 +5,7 @@ import { apiSuccess } from "@/lib/api-response";
|
|||||||
import { decrypt, encrypt } from "@/lib/crypto";
|
import { decrypt, encrypt } from "@/lib/crypto";
|
||||||
import { getUserWithingsCredentials } from "@/lib/withings/credentials";
|
import { getUserWithingsCredentials } from "@/lib/withings/credentials";
|
||||||
import { refreshAccessToken } from "@/lib/withings/client";
|
import { refreshAccessToken } from "@/lib/withings/client";
|
||||||
|
import { isWithingsRefreshReauthFailure } from "@/lib/withings/sync";
|
||||||
import { markReauthRequired } from "@/lib/integrations/status";
|
import { markReauthRequired } from "@/lib/integrations/status";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,17 +81,7 @@ export const GET = apiHandler(async () => {
|
|||||||
// the user reconnects. We mirror the same status-code parsing
|
// the user reconnects. We mirror the same status-code parsing
|
||||||
// the sync path does.
|
// the sync path does.
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
const statusMatch = /Withings\s+\w+\s+error:\s*(\d+)/.exec(message);
|
if (isWithingsRefreshReauthFailure(message)) {
|
||||||
const statusCode = statusMatch
|
|
||||||
? Number.parseInt(statusMatch[1], 10)
|
|
||||||
: NaN;
|
|
||||||
const isReauth =
|
|
||||||
Number.isFinite(statusCode) &&
|
|
||||||
(statusCode === 100 ||
|
|
||||||
statusCode === 101 ||
|
|
||||||
statusCode === 102 ||
|
|
||||||
(statusCode >= 200 && statusCode <= 299));
|
|
||||||
if (isReauth) {
|
|
||||||
await markReauthRequired(user.id, "withings", message).catch(() => {});
|
await markReauthRequired(user.id, "withings", message).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -327,7 +327,6 @@ function stateBadgeFor(
|
|||||||
icon: <Clock className="h-3 w-3" aria-hidden />,
|
icon: <Clock className="h-3 w-3" aria-hidden />,
|
||||||
};
|
};
|
||||||
case "manually_disabled":
|
case "manually_disabled":
|
||||||
default:
|
|
||||||
return {
|
return {
|
||||||
label: t("settings.notificationStatus.stateManuallyDisabled"),
|
label: t("settings.notificationStatus.stateManuallyDisabled"),
|
||||||
variant: "secondary",
|
variant: "secondary",
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
setCachedCodexSlug,
|
setCachedCodexSlug,
|
||||||
invalidateCachedCodexSlug,
|
invalidateCachedCodexSlug,
|
||||||
clearCodexSlugCache,
|
clearCodexSlugCache,
|
||||||
inspectCodexSlugCache,
|
|
||||||
CODEX_SLUG_CACHE_TTL_MS,
|
CODEX_SLUG_CACHE_TTL_MS,
|
||||||
} from "../codex-slug-cache";
|
} from "../codex-slug-cache";
|
||||||
|
|
||||||
@@ -19,7 +18,6 @@ describe("Codex slug cache", () => {
|
|||||||
|
|
||||||
it("starts empty", () => {
|
it("starts empty", () => {
|
||||||
expect(getCachedCodexSlug()).toBeNull();
|
expect(getCachedCodexSlug()).toBeNull();
|
||||||
expect(inspectCodexSlugCache()).toBeNull();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("set + get returns the cached slug within TTL", () => {
|
it("set + get returns the cached slug within TTL", () => {
|
||||||
@@ -43,8 +41,8 @@ describe("Codex slug cache", () => {
|
|||||||
it("expired entry is evicted on read", () => {
|
it("expired entry is evicted on read", () => {
|
||||||
setCachedCodexSlug("gpt-5.3-codex", 1_000);
|
setCachedCodexSlug("gpt-5.3-codex", 1_000);
|
||||||
getCachedCodexSlug(1_000 + CODEX_SLUG_CACHE_TTL_MS + 1);
|
getCachedCodexSlug(1_000 + CODEX_SLUG_CACHE_TTL_MS + 1);
|
||||||
// Subsequent inspect should be null too.
|
// Subsequent get should be null too (no resurrection).
|
||||||
expect(inspectCodexSlugCache(1_000 + CODEX_SLUG_CACHE_TTL_MS + 1)).toBeNull();
|
expect(getCachedCodexSlug(1_000 + CODEX_SLUG_CACHE_TTL_MS + 1)).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("invalidate clears the slot", () => {
|
it("invalidate clears the slot", () => {
|
||||||
@@ -58,10 +56,4 @@ describe("Codex slug cache", () => {
|
|||||||
setCachedCodexSlug("b", 2_000);
|
setCachedCodexSlug("b", 2_000);
|
||||||
expect(getCachedCodexSlug(2_500)).toBe("b");
|
expect(getCachedCodexSlug(2_500)).toBe("b");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("inspect reports age in ms", () => {
|
|
||||||
setCachedCodexSlug("gpt-5.3-codex", 1_000);
|
|
||||||
const inspected = inspectCodexSlugCache(1_500);
|
|
||||||
expect(inspected).toEqual({ slug: "gpt-5.3-codex", ageMs: 500 });
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
@@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|||||||
import { CodexClient, __test } from "../codex-client";
|
import { CodexClient, __test } from "../codex-client";
|
||||||
import {
|
import {
|
||||||
clearCodexSlugCache,
|
clearCodexSlugCache,
|
||||||
inspectCodexSlugCache,
|
getCachedCodexSlug,
|
||||||
setCachedCodexSlug,
|
setCachedCodexSlug,
|
||||||
CODEX_SLUG_CACHE_TTL_MS,
|
CODEX_SLUG_CACHE_TTL_MS,
|
||||||
} from "../codex-slug-cache";
|
} from "../codex-slug-cache";
|
||||||
@@ -105,7 +105,7 @@ describe("Codex slug fallback chain", () => {
|
|||||||
expect(diagnostics?.cacheState).toBe("miss");
|
expect(diagnostics?.cacheState).toBe("miss");
|
||||||
expect(diagnostics?.workingSlug).toBe("gpt-5.3-codex");
|
expect(diagnostics?.workingSlug).toBe("gpt-5.3-codex");
|
||||||
|
|
||||||
expect(inspectCodexSlugCache()?.slug).toBe("gpt-5.3-codex");
|
expect(getCachedCodexSlug()).toBe("gpt-5.3-codex");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("walks past first slug on 'not supported when using Codex with a ChatGPT account' 400", async () => {
|
it("walks past first slug on 'not supported when using Codex with a ChatGPT account' 400", async () => {
|
||||||
@@ -134,7 +134,7 @@ describe("Codex slug fallback chain", () => {
|
|||||||
expect(diagnostics?.workingSlug).toBe("gpt-5.3-codex");
|
expect(diagnostics?.workingSlug).toBe("gpt-5.3-codex");
|
||||||
|
|
||||||
// The working slug — not the rejected one — is now cached.
|
// The working slug — not the rejected one — is now cached.
|
||||||
expect(inspectCodexSlugCache()?.slug).toBe("gpt-5.3-codex");
|
expect(getCachedCodexSlug()).toBe("gpt-5.3-codex");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("walks past first slug on 400 with model_not_found body", async () => {
|
it("walks past first slug on 400 with model_not_found body", async () => {
|
||||||
@@ -302,7 +302,7 @@ describe("Codex slug fallback chain", () => {
|
|||||||
|
|
||||||
it("cache invalidated when cached slug starts rejecting", async () => {
|
it("cache invalidated when cached slug starts rejecting", async () => {
|
||||||
setCachedCodexSlug("gpt-5-codex");
|
setCachedCodexSlug("gpt-5-codex");
|
||||||
expect(inspectCodexSlugCache()?.slug).toBe("gpt-5-codex");
|
expect(getCachedCodexSlug()).toBe("gpt-5-codex");
|
||||||
|
|
||||||
const mockFetch = vi
|
const mockFetch = vi
|
||||||
.fn()
|
.fn()
|
||||||
@@ -320,7 +320,7 @@ describe("Codex slug fallback chain", () => {
|
|||||||
|
|
||||||
// After walking to "gpt-5.3-codex" (the next entry after the
|
// After walking to "gpt-5.3-codex" (the next entry after the
|
||||||
// cached one), the cache is updated to the new working slug.
|
// cached one), the cache is updated to the new working slug.
|
||||||
expect(inspectCodexSlugCache()?.slug).toBe("gpt-5.3-codex");
|
expect(getCachedCodexSlug()).toBe("gpt-5.3-codex");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("isSlugRejection helper recognises canonical rejection bodies", () => {
|
it("isSlugRejection helper recognises canonical rejection bodies", () => {
|
||||||
|
|||||||
@@ -59,16 +59,4 @@ export function clearCodexSlugCache(): void {
|
|||||||
cache.clear();
|
cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Diagnostic helper — exposes (slug, ageMs) for Wide-Event annotation.
|
|
||||||
* Returns null when nothing is cached.
|
|
||||||
*/
|
|
||||||
export function inspectCodexSlugCache(
|
|
||||||
now: number = Date.now(),
|
|
||||||
): { slug: string; ageMs: number } | null {
|
|
||||||
const entry = cache.get(CACHE_KEY);
|
|
||||||
if (!entry) return null;
|
|
||||||
return { slug: entry.slug, ageMs: now - entry.cachedAtMs };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const CODEX_SLUG_CACHE_TTL_MS = CACHE_TTL_MS;
|
export const CODEX_SLUG_CACHE_TTL_MS = CACHE_TTL_MS;
|
||||||
@@ -41,11 +41,6 @@ export interface AchievementDefinition {
|
|||||||
format: "count" | "days" | "percent";
|
format: "count" | "days" | "percent";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Stable metric → category mapping. Add a metric here when it joins the
|
|
||||||
* `AchievementMetricKey` union; the page falls back to "engagement" if
|
|
||||||
* a future definition slips through, so there is no silent drop-off.
|
|
||||||
*/
|
|
||||||
export function getAchievementCategory(
|
export function getAchievementCategory(
|
||||||
metric: AchievementMetricKey,
|
metric: AchievementMetricKey,
|
||||||
): AchievementCategory {
|
): AchievementCategory {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
import { prisma } from "@/lib/db";
|
import { prisma } from "@/lib/db";
|
||||||
import { auditLog } from "@/lib/auth/audit";
|
import { auditLog } from "@/lib/auth/audit";
|
||||||
import {
|
import {
|
||||||
MAX_CONSECUTIVE_FAILURES,
|
|
||||||
nextRetryAt,
|
nextRetryAt,
|
||||||
shouldAutoDisableAfterTransient,
|
shouldAutoDisableAfterTransient,
|
||||||
type SendOutcome,
|
type SendOutcome,
|
||||||
@@ -167,5 +166,3 @@ export function isChannelInCooldown(
|
|||||||
): boolean {
|
): boolean {
|
||||||
return channel.nextRetryAt !== null && channel.nextRetryAt > now;
|
return channel.nextRetryAt !== null && channel.nextRetryAt > now;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TEST_CONSTANTS = { MAX_CONSECUTIVE_FAILURES } as const;
|
|
||||||
@@ -25,8 +25,6 @@
|
|||||||
* response that doesn't match the hard-reject rules.
|
* response that doesn't match the hard-reject rules.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export type RejectKind = "hard" | "soft" | "ok";
|
|
||||||
|
|
||||||
export interface SendOutcome {
|
export interface SendOutcome {
|
||||||
ok: boolean;
|
ok: boolean;
|
||||||
/** True iff the upstream signaled a permanent failure (410, blocked-by-user, …). */
|
/** True iff the upstream signaled a permanent failure (410, blocked-by-user, …). */
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ export async function syncUserMeasurements(
|
|||||||
* The error message format from `refreshAccessToken()` is
|
* The error message format from `refreshAccessToken()` is
|
||||||
* "Withings refresh error: <status> - <error>".
|
* "Withings refresh error: <status> - <error>".
|
||||||
*/
|
*/
|
||||||
function isWithingsRefreshReauthFailure(message: string): boolean {
|
export function isWithingsRefreshReauthFailure(message: string): boolean {
|
||||||
const status = extractWithingsStatus(message);
|
const status = extractWithingsStatus(message);
|
||||||
if (!status) return false;
|
if (!status) return false;
|
||||||
const n = Number.parseInt(status, 10);
|
const n = Number.parseInt(status, 10);
|
||||||
@@ -247,7 +247,7 @@ function isWithingsRefreshReauthFailure(message: string): boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractWithingsStatus(message: string): string | undefined {
|
export function extractWithingsStatus(message: string): string | undefined {
|
||||||
// Captures the digit run after "Withings <verb> error:" — same shape
|
// Captures the digit run after "Withings <verb> error:" — same shape
|
||||||
// exchangeCode and refreshAccessToken use.
|
// exchangeCode and refreshAccessToken use.
|
||||||
const m = /Withings\s+\w+\s+error:\s*(\d+)/.exec(message);
|
const m = /Withings\s+\w+\s+error:\s*(\d+)/.exec(message);
|
||||||
|
|||||||
Reference in new issue
Block a user