Skip to content

fix: enforce a 24 hour floor on the deletion age window - #9

Open
lesandie wants to merge 2 commits into
feat/durable-run-logfrom
fix/useage-floor
Open

fix: enforce a 24 hour floor on the deletion age window#9
lesandie wants to merge 2 commits into
feat/durable-run-logfrom
fix/useage-floor

Conversation

@lesandie

@lesandie lesandie commented Aug 22, 2026

Copy link
Copy Markdown
Member

Summary

Sets a 24-hour minimum deletion-age window in both the CLI and Job renderer. dev-automation may use a short window only with its explicit development override.

Fix

The entrypoint now passes --dev-allow-short-useage=true, matching the parser requirement. Regression tests pin the exact arguments.

Validation

  • CI: passed
  • Local: 108 tests passed, 1 expected xfail; rendered manifest validates
  • Live dev Job: collect → dry-run → delete completed successfully

Stacked on #7; #10 follows.

The age window is the only thing standing between a run and live data.
ClickHouse uploads a part's blobs to S3 and registers them in
system.remote_data_paths a moment later; in that window a live blob is absent
from the reference table and looks orphaned, and there is no per-object
re-check before the S3 delete.

`--useage 0` silently removed that protection -- `if args.useage else ""`
emits no clause at all -- the default WAS 0, and render.py accepted it. So the
dangerous configuration was also the out-of-the-box one for anyone who did not
set it explicitly.

--useage now defaults to 24 and is refused below 24, in both s3gc.py and
render.py: the renderer catches it before a Job is applied, the tool catches a
direct CLI run that never passes through the renderer. Refused for --dry-run
too, deliberately: a preview computed over a wider set than the delete would
honour is worse than no preview, because the reviewed number is the one the
customer approves.

A floor rather than a hardcoded constant, because the parameter is only
dangerous downward. Upward it is the "be more careful" lever -- a cluster with
slow merges or long mutations may legitimately want 72 hours or a week.
Removing it would forfeit that and buy nothing the floor does not give.

Development escape hatch, scoped to the one non-production phase.
PHASE=dev-automation seeds and deletes its own fixtures within minutes, so a 24
hour window would make it find nothing and "succeed" vacuously -- worse than
failing. That phase, and only that phase, passes --dev-allow-short-useage; the
collect, dry-run and delete branches never do, and a test asserts it. A run
that uses it logs a warning and writes a warning row to the durable run log, so
it cannot be mistaken for a normal one.

Replaces the test that documented the hazard with tests that enforce it.
All 11 scope mutations remain caught.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lesandie

Copy link
Copy Markdown
Member Author

Review record

Decision taken while reviewing #6, where USEAGE_HOURS=0 was surfaced as the most dangerous finding of the audit: below 24h a run can delete a part between its blob upload to S3 and its registration in system.remote_data_paths. The default was 0 and render.py accepted it, so the dangerous configuration was also the out-of-the-box one.

Decided: hard floor of 24, default 24, enforced in both s3gc.py and render.py.

Rejected: removing the parameter and hardcoding 24. It is only dangerous downward; upward it is the "be more careful" lever for clusters with slow merges or long mutations.

Escape hatch scoped to PHASE=dev-automation, which seeds and deletes its own fixtures within minutes — a 24h window there finds nothing and "succeeds" vacuously, which is worse than failing. No new concept introduced: that phase is already documented as non-production and already requires DELETE_CONFIRMATION. test_only_dev_automation_passes_the_short_window_flag asserts the prod branches never pass the flag.

Verified: 107 passed / 1 xfailed, render + kubeconform clean, #6's eleven scope mutations 11/11 caught.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant