Repository navigation
feat: UK GDPR complaints and Meta deletion workflow, inbound rate limits, DSAR erasure - #42
Merged
Merged
Conversation
Share pages read results via the Admin SDK, so the public read rule only enabled listing every lead transcript with the public web config.
…a data deletion workflow
The deletion endpoint queried non-existent top-level prospects and webhooks
collections and deleted users/{uid} without its subcollections, so personal
data survived while the endpoint reported success. Recursively delete the
uid-keyed trees (users, leads, reminders) and owned agents, conversations,
results and Meta channel index docs, and return 500 before deleting the Auth
user if erasure fails so the request can be retried.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
3 of 4 tasks
The deployed Firebase sendReminders job never read users/{uid}/smsSuppressed, so leads who texted STOP kept getting reminders. Mark those reminders skipped instead.
POST /api/agency/remove rewrote any user's role and agencyId without checking they were in memberUids, so one owner could strip another agency owner's role. Return 404 for non-members and write nothing.
Account deletion logged and ignored a failed Stripe cancel, then erased the user, leaving a subscription that billed forever with no account to cancel it from. Skip the cancel when Stripe already shows it ended, and otherwise return 502 before erasing anything.
Invite emails linked straight to GET /api/agency/accept, which needs a bearer token a link click never sends, so every invite failed with 401. Link to a new /invite page outside the /settings auth redirect: it signs the invitee in, then calls the accept API. Build the link with getBaseUrl() instead of a possibly empty NEXT_PUBLIC_BASE_URL.
GET /api/agents/:id/sequences had no auth check, so anyone with an agent id (exposed on share links) could read an owner's sales copy. Apply the same owner check the PUT route uses; a missing agent now returns 404.
GET /api/result/:id returned the whole result doc, including ownerEmail, ownerUid and agentId, to anyone with a share link. Nothing in the app calls it; the /r/[id] page reads results server-side.
The callback deleted meta_channel_index by Meta's app-scoped user id, but that collection is keyed by page and Instagram account ids, so nothing was ever erased while the request was recorded as completed. Record it as pending, email support to handle it, and show the real status on the status page.
The host runs Node 26 against the 22.x engines pin, so yarn refused to start the dev server for the browser preview.
# Conflicts: # app/api/[[...path]]/route.js # app/legal/data-deletion/page.js
Mcgyver-ai
pushed a commit
that referenced
this pull request
Oct 20, 2026
Resolves the route.js conflicts with #42 by taking main's side: GET /api/result/:id stays deleted, and main's retrieve-first Stripe cancel in DELETE /api/account replaces the branch's version. toPublicResult and its test go with the deleted route. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018sQyAmPXx4AVoEa3XZmC6b
Mcgyver-ai
pushed a commit
that referenced
this pull request
Oct 20, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018sQyAmPXx4AVoEa3XZmC6b
2 of 3 tasks
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Opens review for the commits on
fix/firestore-results-lockdownthat aren't onmainyet. They were written in an earlier session.502b8bdfeat(api): inbound webhooks and inbound-token ingestion get their own rate limits (lib/rateLimit.js), separate from the anonymous per-IP cap.fd2f4eefeat(compliance): UK GDPR / DUA Act 2025 complaints page, updated privacy and terms pages, the Meta data-deletion callback and status endpoint, andlib/auditLog.js.ec63cd5fix(api): DSAR account deletion erases all of the user's Firestore data (eraseUserData).aeac0afchore(agents): specialist agency skills and a solo maker profile under.agents/.e0bded4docs(tasks): session logs for the above.f8c1d22fix(security): deny client reads onresults. This is already onmainas the squash-merged fix(security): deny client reads on results collection #35, so it adds no diff.For reviewers
mainatd9a2c09, before fix(security): deny client reads on results collection #35 and feat(dev): run local dev against Firebase emulators #36 were squash-merged, so parts of the diff may already be onmain. It merges into currentmainwithout conflicts.eraseUserDataand the account-deletion route, and fix: verify GHL webhooks with documented signature scheme #39, fix: close authz and SSRF holes in API routes #40 and fix: UK GDPR/PECR erasure, deletion callback and SMS opt-out #41 each append to the end of TASKS.md. Expect to resolve conflicts in whichever PR merges second.Test plan
yarn buildpasses. Not run for this PR; CI's Build check covers it.