feat: clear chat history manually, auto-expire old history after 90 days

Manual: DELETE /api/v1/ai/chat-history (scoped by recipeId or scope=general,
matching GET's scoping) plus a trash-icon button + confirm dialog in both
chat panels' headers.

Automatic: new internal cron endpoint (chat-cleanup), same shared-secret
pattern as the existing leftover-reminders/weekly-digest crons, deletes
any chat_messages older than 90 days. Wired into cron/crontab (daily,
03:00 UTC) and the Dockerfile's cron stage.

Verified locally: cleared a real conversation through the actual UI and
confirmed it didn't come back on reopen (not just cleared client-side);
inserted a 100-day-old and a 5-day-old message directly, called the cron
endpoint with the real shared-secret check, confirmed only the old one
was deleted and the recent one survived; confirmed the endpoint 401s with
no/wrong secret.
This commit is contained in:
Arnaud
2026-07-12 23:27:05 +02:00
parent 9549684254
commit adaa837564
10 changed files with 200 additions and 5 deletions
+3
View File
@@ -3,3 +3,6 @@
# Leftover-expiry reminders — daily at 09:00 UTC.
0 9 * * * /usr/local/bin/run-leftover-reminders.sh >> /proc/1/fd/1 2>> /proc/1/fd/2
# AI chat history cleanup (90-day retention) — daily at 03:00 UTC.
0 3 * * * /usr/local/bin/run-chat-cleanup.sh >> /proc/1/fd/1 2>> /proc/1/fd/2
+17
View File
@@ -0,0 +1,17 @@
#!/bin/sh
# Triggers deletion of AI chat history older than the retention window on the
# `web` service. Run on a schedule by busybox crond (see cron/crontab). Fails
# loudly (non-zero exit, stderr) but crond just tries again tomorrow — no
# retry loop here on purpose, keep this script trivial.
set -eu
: "${WEB_INTERNAL_URL:=http://web:3000}"
if [ -z "${CRON_SECRET:-}" ]; then
echo "run-chat-cleanup: CRON_SECRET is not set, refusing to call the endpoint" >&2
exit 1
fi
curl -fsS -X POST \
-H "Authorization: Bearer ${CRON_SECRET}" \
"${WEB_INTERNAL_URL}/api/internal/cron/chat-cleanup"