Warning-gated Org Deletion #607

Merged
tobru merged 26 commits from design/warning-gated-deletion into main 2026-07-14 05:56:09 +00:00
Owner

Add design to prevent unexpected trial-org auto-deletion (org-64 incident): make a recorded deletion warning, sent at least one grace period (in business days) ago, a hard precondition for deletion, with the warning BCC'd to a configurable address and Odoo trial dates sourced from the same frozen effective deletion date

Add design to prevent unexpected trial-org auto-deletion (org-64 incident): make a recorded deletion warning, sent at least one grace period (in business days) ago, a hard precondition for deletion, with the warning BCC'd to a configurable address and Odoo trial dates sourced from the same frozen effective deletion date
Add design to prevent unexpected trial-org auto-deletion (org-64 incident):
make a recorded deletion warning, sent at least one grace period (in business
days) ago, a hard precondition for deletion, with the warning BCC'd to a
configurable address and Odoo trial dates sourced from the same frozen
effective deletion date.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(frontend): render instance ID as HTML in delete confirmation help text
Some checks failed
Tests / test (push) Failing after 1m26s
d8ba063312
The delete confirmation help text was a plain string, which Django
auto-escapes on render, showing literal <strong> tags. Use format_html
to mark it safe while escaping the interpolated instance name.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bite-sized TDD tasks: business-day helper, effective_deletion_date and
is_ready_for_deletion gate, at-expiry deletion warning with BCC and Odoo push,
warning reset on extension, cleanup gate, deletion_confirmation recording, and
safe-linger logging.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(staff): accurate scheduled-deletion date and reminder states in lifecycle
All checks were successful
Tests / test (push) Successful in 1m23s
3a639bbee1
tobru changed title from WIP: Warning-gated Org Deletion to Warning-gated Org Deletion 2026-07-13 09:17:41 +00:00
fix(core): close warning-gated deletion race and billing gaps
All checks were successful
Tests / test (push) Successful in 1m26s
b8967930d6
Code-review fixes before merge:

- A deletion_warning recorded at or before the current expiration_date
  belongs to a previous validity window and now counts as no warning
  (filtered in deletion_warning_sent_at). Replaces _reset_stale_warning,
  whose extend-then-re-expire race let hourly cleanup delete an org with
  no fresh warning - the org-64 class this feature exists to prevent.
- The warning key, recipient sends and save commit atomically under one
  select_for_update transaction: a crash mid-send strands no key,
  overlapping runs cannot double-send, and no stale in-memory dict is
  written back over concurrent changes.
- Reminder queryset excludes archived orgs, which matched the open-ended
  warning condition forever and re-pushed decommissioned sale orders.
- Cleanup keeps the Odoo free window ahead (teardown push) for
  past-deadline unwarned orgs so a linger never becomes billable, and
  defers the reminder task so the warning follows a pause within
  minutes instead of at the next daily run.
- Warning emails render their deadline as if warned now; previews and
  dry runs no longer show expiration-anchored past dates.
- grace_period_days=0 means delete right after warning; the staff
  timeline checks "is not None" instead of truthiness.
- Fold duplicate absolute_url helper; hoist scoped test imports.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tobru merged commit 6a53550aa4 into main 2026-07-14 05:56:09 +00:00
tobru deleted branch design/warning-gated-deletion 2026-07-14 05:56:09 +00:00
Sign in to join this conversation.
No description provided.