Skip to content

cold-store-reaper: implement the pending DB-backup retention policy (30 daily / 12 weekly / 12 monthly, trash-not-delete) #939

Closed

Description

@dezren39

Finding

cold-store-reaper's DB-backup retention policy is documented as pending and has no tracking issue: PR #929 shipped put-backup / list-backups with retention enforcement explicitly out of scope, and nothing files the follow-up. Until it lands, DB backups accumulate in Drive forever and pruning is manual.

Found by the pr-diff-review job reviewing PR #929 (cold-store-reaper v2), 2026-10-25.

Evidence

  • PR cold-store-reaper v2: D1 manifest sync, DB-backup class, rehydrator Worker #929 body: "Retention enforcement (30/12/12, trash-not-delete) is explicitly out of scope and noted as pending in the README."
  • Current main (92d0c6ee), pkgs/cold-store-reaper/README.md:98-100: "Retention is NOT enforced yet: the design's 30 daily / 12 weekly / 12 monthly policy (trash, not delete) is pending a later version. Until then, backups accumulate and pruning is manual."
  • Same note in code: pkgs/cold-store-reaper/cold_store.py, put_backup() docstring (line ~672): "Retention enforcement (30 daily / 12 weekly / 12 monthly, trash-not-delete) is NOT implemented yet — see README."
  • Dedupe: gh search issues for "cold-store-reaper", "retention", and "hard stop upload" returns no tracking issue for this follow-up.

Why it matters

put-backup is the always-growing write path of the package (every DB backup of supabase/turso/d1 lands there with a dated name). With no retention and no tracking issue, the folder grows without bound against the project's Drive budget, and the "pending a later version" note is exactly the kind of promised follow-up that gets lost.

Acceptance criteria

  • A prune-backups command (or retention pass in an existing command) implements 30 daily / 12 weekly / 12 monthly per database, moving expired backups to Drive trash (never hard delete), with a --dry-run that lists what would be trashed.
  • Retention decisions are driven by the dated backup names / Drive createdTime already recorded, and are covered by fake-Drive tests (boundary ages: 30th/31st daily, weekly and monthly tiers).
  • README's retention note is updated from "NOT enforced yet" to the enforced behavior.

— filed by the pr-diff-review job (PR #929); triage via the repo-health queue pilot.

Activity

  1. added
    kind/featureNew feature or capability request
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/lowNice to have; do when convenient
    queue/queuedHas a queued task in the Supabase agent queue
    app/cold-store-reaperPackage/app: cold-store-reaper (pkgs/ or apps/ in this repo)
    on Oct 26, 2026
  2. dezren39 commented on Oct 26, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: pr-diff-review job
    • Session / ID: pr-diff-review (cron job_id pr-diff-review) run 2026-10-25 20:37 CDT
    • Found via: filed this run
    • Task: Triage the pending cold-store DB-backup retention follow-up promised by PR cold-store-reaper v2: D1 manifest sync, DB-backup class, rehydrator Worker #929
    • Expectation: effort/s — triage verdict on the finding against current main, then a fix or a documented acceptance
    • Links: source PR evidence is in the issue body; a repo-task/v1 triage packet for this issue is enqueued in repo-health-code-pilot
  3. dezren39 commented on Oct 26, 2026

    @dezren39
    MemberAuthor

    Verified as already implemented — closing with evidence. No code gap was found, so nothing new was built for this issue (checked 2026-10-26 during the #938/#940 close-out, PR #988).

    Acceptance criteria, point by point:

    1. prune-backups command, 30 daily / 12 weekly / 12 monthly per DB, trash-not-delete, dry-run — implemented in v3, PR cold-store-reaper v3: backup retention (prune-backups), get-backup, backup-d1, nightly + drill scripts #965 (merge aa0d6d10d2457d1450aa971bf01773c455cd61f5). prune_backups() computes the keep set as the union of the newest backup of each of the last 30 distinct calendar days, 12 distinct ISO weeks, and 12 distinct calendar months present in the folder; --apply trashes candidates via files.update {trashed: true} (never a permanent delete) and writes one transfer_ledger row per file (direction trash, kind backup-prune). Dry-run is the default.
    2. Decisions driven by the dated names, with fake-Drive boundary tests — the plan is a pure function of the folder listing (filename timestamps parsed from <db>-<YYYYMMDDTHHMMSSZ>-<basename>), never the wall clock; unparseable names are never pruned, only reported. Covered by TestPruneBackups: dry-run plan with an exact expected prune set, apply trashes + ledgers, a 400-file long-history case (oldest pruned, tier boundaries), and all-DBs/unknown-DB handling.
    3. README updated — the old "Retention is NOT enforced yet" note is gone; the README's "Retention (design section 5)" section documents the enforced behavior, and scripts/nightly-backup.sh runs prune-backups --apply as step 3 of every nightly run.

    Live evidence: the first manual nightly run on 2026-10-26 enforced this policy — the two superseded same-day D1 exports (d1-20261026T012730Z…, Drive 1U8To4hx9vKBTIIECDeXMzXtNOwbc5TnE, and d1-20261026T011930Z…, Drive 1wmyVZIEsulqhjnwJbnRgPoUdnbTmldIM) were moved to Drive trash under it (recoverable, not deleted), while the current export was kept.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/cold-store-reaperPackage/app: cold-store-reaper (pkgs/ or apps/ in this repo)kind/featureNew feature or capability requestpriority/lowNice to have; do when convenientqueue/queuedHas a queued task in the Supabase agent queuesource/pr-diff-reviewFiled by the pr-diff-review jobstatus/needs-triageNot yet triaged; needs a first looktask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions