feat(soft-delete): gate soft delete behind a temporary SOFT_DELETE release toggle#41166
feat(soft-delete): gate soft delete behind a temporary SOFT_DELETE release toggle#41166mikebridge wants to merge 1 commit into
Conversation
Code Review Agent Run #0cc334Actionable Suggestions - 0Filtered by Review RulesBito filtered these suggestions based on rules created automatically for your feedback. Manage rules.
Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
✅ Deploy Preview for superset-docs-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
3318c24 to
71bc1f2
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #41166 +/- ##
==========================================
- Coverage 64.31% 64.30% -0.01%
==========================================
Files 2652 2652
Lines 144807 144808 +1
Branches 33423 33423
==========================================
- Hits 93126 93119 -7
- Misses 50013 50021 +8
Partials 1668 1668
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Adds a temporary rollout / kill-switch feature flag (`SOFT_DELETE`, default off) so the soft-delete substrate can ship dark and be activated per-deploy once validated — separating deploy from release for a behavior change with cross-entity blast radius. This is deployment scaffolding, not a permanent toggle: it is removed once soft delete is stable, leaving the unconditional "always active" end state. Until an operator opts in, deployments retain legacy DELETE (hard-delete) behavior. Two gate points (both no-op to legacy behavior when off): - `BaseDAO.delete()` routes to soft_delete only when the flag is on; otherwise hard_delete. - The `do_orm_execute` visibility listener attaches no criteria when off. Both write- and read-path gate on the same flag, so they cannot diverge. Restore needs no explicit gate: with the flag off no row carries `deleted_at`, so a restore call has nothing to act on. The flag docstring documents the kill-switch semantics (flipping off after rows are soft-deleted resurrects them — emergency stop, not a clean rollback) and that the import pipeline's existing-row detection is gated transitively via the listener. The `deleted_at` migration stays un-gated (additive). Existing soft-delete unit tests are updated to enable the flag; new tests pin the gate-off path: a mixin model hard-deletes and the listener does not filter. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
71bc1f2 to
0b47f63
Compare
Code Review Agent Run #dc874cActionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
SUMMARY
Adds a temporary rollout / kill-switch feature flag —
SOFT_DELETE(default off) — so the soft-delete substrate can ship dark and be activated per-deploy once validated, separating deploy from release for a behavior change with cross-entity blast radius (DELETE semantics + read-path visibility filtering).This is deployment scaffolding, not a permanent toggle: it is removed once soft delete is stable, leaving the unconditional "always active once deployed" end state. Until an operator opts in, existing deployments retain byte-for-byte legacy
DELETE(hard-delete) behavior.Two gate points, both no-op to legacy behavior when off:
BaseDAO.delete()routes tosoft_delete()only when the flag is on; otherwisehard_delete().do_orm_executevisibility listener attaches nodeleted_at IS NULLcriteria when off.Both the write path and the read path gate on the same flag, so they cannot diverge. Restore needs no explicit gate — with the flag off no row carries
deleted_at, so a restore call has nothing to act on. The flag docstring documents the kill-switch semantics (flipping off after rows are soft-deleted resurrects them — emergency stop, not a clean rollback) and that the import pipeline's existing-row detection is gated transitively via the listener.The
deleted_atmigration (from the substrate PRs) stays un-gated (additive). Removal of this flag + its two gate points is a small follow-up once soaked.THIS IS A RELEASE TOGGLE, NOT A FEATURE FLAG
A common and reasonable objection is "feature flags that change functionality are a maintenance hazard." That objection is about long-lived flags — permanent configuration surface that parameterizes product behavior, branches the test matrix indefinitely, and accumulates as config sprawl. This flag is a different category.
In the Continuous Delivery taxonomy this is a Release Toggle: a transitory toggle whose only job is to decouple deploy from release so a not-yet-validated change can land on
masterand ship dark, then be switched on once trusted — and then deleted. It is not a Permission/Experiment/Ops toggle that lives forever.Why the distinction matters here:
So the change is deliberately scoped as scaffolding with a removal plan, default off, both gate points keyed to the same flag so the write and read paths can't diverge. It exists to make a behavior change with cross-entity reach safe to deploy continuously — not to add a permanent toggle to the product.
TESTING INSTRUCTIONS
Unit tests cover both flag states (default-off and on):
FEATURE_FLAGS = {"SOFT_DELETE": False}(default): aDELETEon aSoftDeleteMixinmodel hard-deletes, and the read-path listener does not hide soft-deleted rows.SOFT_DELETEon:DELETEsoft-deletes and the listener filters soft-deleted rows out of reads (existing substrate behavior).ADDITIONAL INFORMATION
SOFT_DELETE(default off; temporary rollout/kill-switch — to be removed after stabilization)