mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 15:02:04 +00:00
fix(api,lib): consent before reuse, tighter inputs and caches that tell on themselves
Per-status texts check AI consent before the unchanged-data refresh can re-stamp them, the comprehensive fingerprint folds in the comparison baseline and generation language so toggling either regenerates once, and profile, threshold and source-priority writes evict the analytics, targets and derived caches they feed. CSV export neutralises spreadsheet formula prefixes on free-text cells while numeric columns stay typed, the derived batch validates its type token against the measurement enum and carries a per-user rate limit, and a dose synced from the phone app counts as the interactive write it is. Background cache refresh failures log a structured event instead of vanishing, the warm queue runs visit-triggered jobs alongside the nightly walk, the formatter memo evicts one entry instead of flushing wholesale with its option objects frozen, the targets cold build bounds its fan-out, and time in bed unions every writer's envelope while stages stay with the richest recorder.
This commit is contained in:
1 parent
95f21bfa4d
commit
f790e14edd
40 files changed
+1141
-287
No files matched your search
@@ -13,13 +13,17 @@
|
||||
*
|
||||
* Bearer-auth + cookie-auth both work via the shared `requireAuth()`
|
||||
* helper. The analytics aggregator reads this row on every call and
|
||||
* the read path is cheap (one column) — no caching layer to flush.
|
||||
* the read path is cheap (one column). The PUT flushes the per-user
|
||||
* profile-derived caches (`invalidateUserProfile`) because the ladder
|
||||
* decides which source's rows the cached targets / derived / analytics
|
||||
* payloads were built from.
|
||||
*/
|
||||
import { apiHandler, requireAuth, HttpError } from "@/lib/api-handler";
|
||||
import { apiSuccess, getClientIp } from "@/lib/api-response";
|
||||
import { annotate } from "@/lib/logging/context";
|
||||
import { auditLog } from "@/lib/auth/audit";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { invalidateUserProfile } from "@/lib/cache/invalidate";
|
||||
import {
|
||||
parseSourcePriority,
|
||||
sourcePrioritySchema,
|
||||
@@ -77,6 +81,12 @@ export const PUT = apiHandler(async (req: Request) => {
|
||||
data: { sourcePriorityJson: parsed.data },
|
||||
});
|
||||
|
||||
// The priority ladder drives every aggregator's source pick (the
|
||||
// analytics rank SQL, the rollup read-swap, the targets grid's sleep
|
||||
// dedup) — drop the cached payloads so the reorder reflects on the
|
||||
// next read instead of after the TTL.
|
||||
invalidateUserProfile(user.id);
|
||||
|
||||
await auditLog("user.source-priority.update", {
|
||||
userId: user.id,
|
||||
ipAddress: getClientIp(req),
|
||||
|
||||
Reference in new issue
Block a user