mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
The recurring no-briefing day had a chain of causes, closed end to end: Every failure path in the nightly pregenerate + the comprehensive generator now annotates a queryable cause (several classes — features-error, payload-too-large, aborted, generator-failed — previously bumped a counter with zero trace). A failed nightly warm enqueues one bounded retry ~45 minutes later (singleton per user, existing budgets apply), so a transient provider hiccup heals before morning. A cached payload that carries NO briefing no longer satisfies the 24h POST short-circuit nor the unchanged-content hash gate — a once-stripped briefing could previously block its own regeneration indefinitely. The card surfaces the omission reason persistently (grounding strip, generation failure, not attempted) with a forcing retry. Documentation corrected against code truth: Withings credentials are per-user (the documented env path never existed; the dead example entries and manifest rows are gone, and WITHINGS_WEBHOOK_SECRET is now actually whitelisted in compose — stock deploys could never deliver it); the classic Fitbit portal no longer accepts new registrations; the backup-restore example no longer mints a fresh encryption key and uses pnpm dlx tsx; the TLS guide describes the real client model (two CA-level SPKI pins, any-match, leaf renewals need no build); scaling/admin references fixed; the operator-shared subscription provider is documented.
27 lines
980 B
TypeScript
27 lines
980 B
TypeScript
/**
|
|
* v1.28.30 — does a cached comprehensive payload actually carry a daily
|
|
* briefing?
|
|
*
|
|
* Shared by the generator's content-hash gate and the POST route's 24 h
|
|
* short-circuit: a fresh-but-briefingless cache must not satisfy a
|
|
* briefing-expecting caller for the rest of the day (the "one silent
|
|
* nightly failure + 24 h cache = a full day without a briefing" chain).
|
|
* Unparseable text counts as briefingless — regeneration repairs it.
|
|
*
|
|
* Lives in its own leaf module (no provider-tree imports) so the route
|
|
* can consume it without pulling the whole generation pipeline into its
|
|
* bundle, and tests that mock `comprehensive-generate` keep the real
|
|
* implementation.
|
|
*/
|
|
export function cachedPayloadCarriesBriefing(
|
|
cachedText: string | null | undefined,
|
|
): boolean {
|
|
if (!cachedText) return false;
|
|
try {
|
|
const parsed = JSON.parse(cachedText) as Record<string, unknown>;
|
|
return parsed.dailyBriefing != null;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|