Skip to content

feat: UK GDPR complaints and Meta deletion workflow, inbound rate limits, DSAR erasure - #42

Merged
Mcgyver-ai merged 16 commits into
mainfrom
fix/firestore-results-lockdown
Oct 19, 2026
Merged

Mcgyver-ai merged 16 commits into
mainfrom
fix/firestore-results-lockdown

Conversation

@Mcgyver-ai

Copy link
Copy Markdown
Owner

Summary

Opens review for the commits on fix/firestore-results-lockdown that aren't on main yet. They were written in an earlier session.

  • 502b8bd feat(api): inbound webhooks and inbound-token ingestion get their own rate limits (lib/rateLimit.js), separate from the anonymous per-IP cap.
  • fd2f4ee feat(compliance): UK GDPR / DUA Act 2025 complaints page, updated privacy and terms pages, the Meta data-deletion callback and status endpoint, and lib/auditLog.js.
  • ec63cd5 fix(api): DSAR account deletion erases all of the user's Firestore data (eraseUserData).
  • aeac0af chore(agents): specialist agency skills and a solo maker profile under .agents/.
  • e0bded4 docs(tasks): session logs for the above.
  • f8c1d22 fix(security): deny client reads on results. This is already on main as the squash-merged fix(security): deny client reads on results collection #35, so it adds no diff.

For reviewers

Test plan

  • yarn build passes. Not run for this PR; CI's Build check covers it.
  • Manually verified locally / in preview

Share pages read results via the Admin SDK, so the public read rule only enabled listing every lead transcript with the public web config.
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.
Copilot AI balanced review requested due to automatic review settings October 17, 2026 12:55
@vercel

vercel Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
dm-forge Ready Ready Preview Oct 19, 2026 7:39am UTC

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread lib/services/accountService.js Resolved
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
Mcgyver-ai merged commit 3cd0056 into main Oct 19, 2026
7 checks passed
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

This branch was successfully deployed

1 active deployment
Preview — 404173dc Deployed Oct 19, 2026 by vercel[bot]
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.

2 participants