Harden subscriber links, account deletion, and external requests - #77
Harden subscriber links, account deletion, and external requests#77philipithomas wants to merge 12 commits into
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 069d485ee7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 52ebd35c20
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Merged #94 into this reliability branch so either merge order preserves the retired Ghost integration. Password signup, Google signup, and verification no longer enqueue Ghost; the legacy job class is an inert drain for existing serialized jobs, including missing-account GlobalIDs. Generic token expiry/revocation, OAuth validation, and account-owned queue cleanup remain covered. Removed the obsolete Ghost HTTP/enqueue expectations and retained the seven retirement regressions. Both isolated suites pass: SOLO and MULTIUSER each 82 tests / 360 assertions, no failures/errors/skips. Zeitwerk passes; Brakeman reports zero warnings (seven existing ignored). All four current-head CI checks pass on ac1b16e: the push and PR test suites and both production Docker smoke checks. The branch remains open and mergeable. CI: https://github.com/contraptionco/postcard/actions/runs/33988642714 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ac1b16ed56
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Account settings crashed because they called a nonexistent provider attribute; the normal Devise current-password check now works, with a password-reset link for Google signups. Subscriber confirmation links remained valid indefinitely and could reactivate someone after removal. Invalid unsubscribe links raised errors, while account deletion missed subscriber email history and archived posts. This adds locked token verification, 48-hour expiry explained in confirmation emails, token revocation on unsubscribe, safe repeated/deleted-subscription unsubscribe responses, and deletion of those account-owned records.
Updates-list cleanup follows the account's audited email changes so historical memberships and their mail do not survive account deletion. It preserves shared recipient rows, other authors' mail, addresses now used by another account, and memberships with subsequent signup, verification, or pending confirmation activity.
The backlog review also identified several small fixes that had no regression coverage: restore Google OAuth state validation, validate and normalize modern custom domains before provider registration, serialize registration JSON, remove the unrelated development localhost domain, set explicit HTTP connection/read/write budgets, prevent queued newsletters from locked accounts, propagate fatal newsletter-delivery exceptions, and handle an unset theme color. These fixes now have focused tests.
Account deletion uses Solid Queue's execution-locking discard API to cancel pending jobs whose serialized GlobalIDs all belong to that account, including feedback mail. It also recognizes the exact legacy signup-newsletter signature. Claimed/current and mixed-account jobs are preserved. Five jobs that process independent records now deserialize each top-level record separately: a missing record is skipped while live records still run, and transient lookup failures remain failed/retryable. The analytics scheduler enqueues one account per job.
The retired Ghost integration removal from #94 is included: password signup, Google signup, and subscriber verification no longer enqueue external newsletter requests, and signup no longer offers the external newsletter checkbox. The legacy job class remains inert so persisted jobs, including deleted-account GlobalIDs, can drain without external requests. Local Postcard updates subscriptions remain intact.
Fresh confirmation after unsubscribe refreshes subscriber ordering; replaying an already-active confirmation does not. Scheduled tracking cleanup retains email unsubscribe records and all unfinished/retryable queue work, using Solid Queue's supported finished-job retention API instead of deleting operational rows by age.
Validation at
c7a7b1d:Fixes #15, fixes #21, fixes #22, fixes #24, fixes #25, fixes #27, fixes #29.
Supersedes the implementations in #52, #55, #57, #58, #61, #62, #65, and #66. The remote-image SSRF work in #16 and CSP rollout in #18 remain separate open work.