fix(retention): add cleanup sweeps + CalDAV orphan reconciliation
CI & Build / TypeScript typecheck (push) Successful in 37s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Python tests (push) Successful in 42s
CI & Build / Build & push image (push) Successful in 1m29s

Drift-audit Group 4 (retention / unbounded growth):

- CalDAV pull now reconciles deletions: a previously-synced event whose
  caldav_uid no longer appears remotely within the synced window is
  soft-deleted (one batch_id per run, restorable), so a remote delete
  propagates locally instead of orphaning forever. Guarded on a non-empty
  fetch so a spurious empty result can't wipe every local copy. Also wrap
  the blocking fetch in a 120s wait_for and log run duration.
- Notifications: hourly loop now purges read notifications older than 30d
  (unread kept). Table no longer grows without bound.
- Auth tokens: new daily sweep deletes password-reset / invitation tokens
  whose validity window ended >7d ago; wired via start_auth_token_retention_loop
  in app startup. Both tables previously only flipped used=True, never pruned.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-02 18:55:23 -04:00
parent 5fe0fd126d
commit c363a5a6df
4 changed files with 116 additions and 7 deletions
+2
View File
@@ -148,12 +148,14 @@ def create_app() -> Quart:
async def startup():
import asyncio
from fabledassistant.services.auth import start_auth_token_retention_loop
from fabledassistant.services.embeddings import backfill_note_embeddings
from fabledassistant.services.logging import start_log_retention_loop
from fabledassistant.services.notifications import start_notification_loop
start_log_retention_loop()
start_notification_loop()
start_auth_token_retention_loop()
# Backfill embeddings for any notes that don't have one. Runs in the
# background so it never blocks the server from accepting requests.