Skip to content

feat: enforce snapshot retention policy #97

@pparage

Description

@pparage

Problem

The retention policy is configurable but never enforced. GET/PUT /v1/admin/retention (app/routes/v1/admin/retention.py:36-40) reads/writes keep_count and keep_days to <workspace_root>/retention.json, but no code consumes that file:

  • Snapshot.expired (app/core/models.py:133) is never set to True anywhere in the codebase — it is only read to refuse rollback against an already-expired snapshot.
  • app/main.py:61-66 registers only the orphan-reconcile apscheduler job; there is no retention/expiry/purge job.

Impact

  • Snapshots accumulate indefinitely → unbounded Proxmox storage growth.
  • The retention UI control is a no-op, which is misleading to operators.

Proposed work

  1. Add a periodic apscheduler job (alongside orphan reconcile in app/main.py lifespan) that reads the policy and marks/deletes stale snapshots.
  2. Compute staleness from keep_count (N most-recent) and keep_days (younger than D days); set Snapshot.expired = True and/or enqueue delete attempts.

Evidence

  • app/routes/v1/admin/retention.py — policy persisted, no enforcement path
  • app/core/models.py:133Snapshot.expired never written
  • app/main.py:61-66 — only orphan-reconcile job scheduled

Related (minor, can fold in here)

app/core/locks.py docstring states stale-lock cleanup() runs "from apscheduler every interval", but cleanup_stale_locks() is not registered as a scheduled job (stale locks are still evicted on acquire(), so this is low-risk). If a retention job is added, consider registering lock cleanup on the same scheduler to match the docstring.

Surfaced by a code audit; confirmed in the dev branch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    feattrack_axis-01State management and operational integrity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions