Skip to content

Fix account self-deletion FK violation for users with recorded payments - #122

Merged
n8bar merged 1 commit into
mainfrom
claude/121-account-deletion-full-delete
Jul 3, 2026
Merged

n8bar merged 1 commit into
mainfrom
claude/121-account-deletion-full-delete

Conversation

@n8bar

@n8bar n8bar commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Problem

Deleting an account from /profile runs the DB cascade users → invoices, but invoice_payments.invoice_id and invoice_payments.accounting_invoice_id are deliberately RESTRICT (they block invoice force-deletes that would drop payment history). Any user with a recorded payment therefore hit an FK constraint violation and could not delete their account. Separately, sessions.user_id had no foreign key, so database-driver session rows outlived their user as orphans.

What this does

Account deletion is full deletion per ToS §9: profile, wallet configuration, invoices, and payment/accounting records are all removed, and shared invoice links stop working.

  • User deleting hook (app/Models/User.php): before the users → invoices cascade runs, deletes every invoice_payments row referencing the user's invoices via invoice_id or accounting_invoice_id, soft-deleted invoices included, and forgets the user's dashboard snapshot cache. Payment reattribution is scoped to a single user's invoices, so this never removes rows tied to another user's records. The RESTRICT FKs remain in place — invoice force-deletes stay guarded.
  • ProfileController@destroy: wraps the delete in a DB transaction so the hook's deletes and the user-row cascade succeed or roll back together.
  • Migration (2026_07_03_120000_purge_orphaned_sessions_and_add_sessions_user_foreign_key.php): one-time purge of sessions rows whose user_id points at a no-longer-existing user, then adds a cascading sessions.user_id → users.id foreign key so future account deletions remove the user's session rows at the DB level. Guest sessions keep a null user_id and are unaffected.

Tests

tests/Feature/ProfileTest.php adds:

  • test_user_with_invoices_and_recorded_payments_can_delete_their_account — user with detected, reattributed, and trashed-invoice payments plus a persisted session row deletes their account; asserts user, invoices, clients, payment rows, and session rows are all gone. (Failed with the issue's FK violation before the fix.)
  • test_account_deletion_leaves_other_users_records_untouched — a second user's invoices, payments, and sessions survive the first user's deletion.

Full suite: 375 passed (1801 assertions).

Fixes #121

🤖 Generated with Claude Code

https://claude.ai/code/session_01BBzTGeMigvwBHobeTwbVoa

Account deletion is full deletion (ToS §9), but invoice_payments'
invoice_id/accounting_invoice_id foreign keys are deliberately RESTRICT
(protecting payment history from invoice force-deletes), so the
users -> invoices cascade threw an FK violation for any user with
recorded payments.

- User deleting hook removes the user's invoice_payments rows (both
  source and accounting references, trashed invoices included) before
  the cascade runs; reattribution is same-user scoped, so other users'
  records are never touched. RESTRICT FKs stay in place.
- ProfileController@destroy wraps the delete in a transaction so the
  hook and cascade succeed or roll back together.
- Migration purges sessions rows already orphaned by past deletions and
  adds a cascading sessions.user_id foreign key so future account
  deletions drop the user's session rows at the DB level.
- ProfileTest covers deletion with detected/reattributed/trashed-invoice
  payments plus session rows, and that other users' records survive.

Fixes #121

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BBzTGeMigvwBHobeTwbVoa
@n8bar
n8bar merged commit 9ac5a99 into main Jul 3, 2026
1 check passed
n8bar added a commit that referenced this pull request Jul 3, 2026
…grated)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BBzTGeMigvwBHobeTwbVoa
@n8bar
n8bar deleted the claude/121-account-deletion-full-delete branch August 20, 2026 03:52
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.

Account self-deletion fails (FK violation) for users with recorded payments

1 participant