Skip to content

fix: re-check topology per sample, quote --useafter, unbuffer stdout - #10

Open
lesandie wants to merge 2 commits into
fix/useage-floorfrom
fix/remaining-hardening
Open

fix: re-check topology per sample, quote --useafter, unbuffer stdout#10
lesandie wants to merge 2 commits into
fix/useage-floorfrom
fix/remaining-hardening

Conversation

@lesandie

Copy link
Copy Markdown
Member

Stacked on #9. Order: #6#7#9 → this. Clears the three items left in TODO.md from the deletion-scope audit.

1. Topology re-checked per sample (delete path)

The preflight was point-in-time, run once, while the anti-join loop can run for hours. A replica dropping out mid-run takes its references with it, so blobs it alone holds start looking orphaned — and nothing noticed. Now re-verified before each sample, failing closed.

ch_client is free at that point: the previous sample's stream has closed, so this does not reintroduce SESSION_IS_LOCKED.

Cost is one clusterAllReplicas(cluster, system.one) count per sample (4 by default).

Note on the mutation suite: M7 ("remove the preflight call") now survives, because it removes only the top-level call and the per-sample check still covers it. That is redundancy, not a regression — removing both call sites fails test_delete_runs_preflight_before_touching_s3 and test_topology_is_rechecked_for_every_sample. Verified explicitly.

2. --useafter quoted

Interpolated bare, so the value landed as a SQL identifier — the only unquoted value in the anti-join WHERE. The strict xfail from #6 flipped to XPASS and became a real test, which is what strict xfail is for. Added test_useafter_escapes_quotes for embedded quotes.

3. PYTHONUNBUFFERED=1 in the image

stdout is a pipe under Kubernetes so print() was block-buffered, and Python's default SIGTERM handling exits without flushing. A Job killed at activeDeadlineSeconds lost its buffered tail including the closing s3gc: OK, and the dev-automation shell echoes interleaved wrongly against it. Logger records were never affected — StreamHandler.emit() flushes per record.

Checks

pytest -m "not dev_cluster"    112 passed  (xfail count now 0)
render.py + kubeconform        clean
both preflight sites removed   2 tests fail, as intended

TODO.md is down to the three items that predate this work.

🤖 Generated with Claude Code

lesandie and others added 2 commits August 22, 2026 12:06
Clears the three hardening items left over from the deletion-scope audit.

Topology is re-checked before every sample rather than once per run. The
preflight was a point-in-time check while the anti-join loop can run for hours;
a replica that dropped out mid-run took its references with it, so blobs it
alone held started looking orphaned and nothing noticed. ch_client is free at
that point -- the previous sample's stream has closed. Removing both preflight
call sites now fails two tests; removing either one alone is covered by the
other, so the old M7 mutation is obsolete rather than surviving.

--useafter is quoted as a SQL string literal. It was interpolated bare, so an
operator-supplied value landed as an identifier -- the only unquoted value in
the anti-join WHERE clause. The strict xfail recorded for it flipped to XPASS
and became a real test, which is what strict xfail is for.

The image sets PYTHONUNBUFFERED=1. stdout is a pipe under Kubernetes so print()
was block-buffered, and Python's default SIGTERM handling exits without
flushing: a Job killed at activeDeadlineSeconds lost its buffered tail,
including the closing "s3gc: OK", and the dev-automation shell echoes
interleaved wrongly against it. Logger records were never affected --
StreamHandler.emit() flushes per record.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Since the per-sample topology re-check landed, do_use() has two
preflight_cluster() call sites and the top-level one is redundant. That makes
the M7 mutation survive the suite -- removing either site alone is covered by
the other. Not a defect: removing both still fails two tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lesandie lesandie self-assigned this Aug 22, 2026
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