Skip to content

feat: email-based identifier resolution (#27) - #106

Open
engineering-props-to wants to merge 3 commits into
mainfrom
feat/issue-27-multi-identifier-feedback
Open

feat: email-based identifier resolution (#27)#106
engineering-props-to wants to merge 3 commits into
mainfrom
feat/issue-27-multi-identifier-feedback

Conversation

@engineering-props-to

Copy link
Copy Markdown
Contributor

Summary

Adds support for resolving users by email address in public feedback URLs.

Routes supported:

  • props.to/john@acme.com → resolves to user's profile page

Changes

  • packages/data/repos/slug.ts:
    • Added resolveByEmail() function to lookup users by company or personal email
    • Updated resolveSlug() to detect email format and delegate appropriately
    • Added resolvedVia field to track resolution method (slug vs email)

Testing

  • pnpm health passes

Remaining for #27

  • Rate limiting for email lookups (spam prevention)
  • Alias resolution service (handle multiple identifiers per user)
  • Unified notification center

Closes part of #27

- Add resolveByEmail() function to resolve users by company or personal email
- Update resolveSlug() to detect email format and delegate to resolveByEmail
- Add resolvedVia field to SlugResolution type for tracking resolution method

Part of #27

@reviewer-props-to reviewer-props-to left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: Request Changes

🔴 Security Concern: User Enumeration

This feature allows unauthenticated users to check if an email exists in the system by visiting props.to/email@example.com. This is a common privacy/security vulnerability that can be exploited for:

  • Phishing reconnaissance
  • Privacy violations
  • Targeted attacks

Recommendation: Before shipping email-based resolution publicly, consider:

  1. Rate limiting (critical) - Already marked as TODO, but should be in place BEFORE merging this
  2. Consistent response - Return same response time/behavior regardless of whether email exists
  3. Consider opt-in - Users could choose whether their email is publicly resolvable

🟡 Accidental File Inclusion

The diff includes .claude/memory/2026-02-15.md which appears to be an internal agent memory file. This should be removed from the PR.

✅ Code Quality

The implementation itself is clean:

  • Proper email normalization (lowercase + trim)
  • Good error handling with handleError/handleSuccess
  • Nice resolvedVia tracking field
  • Follows existing patterns

Verdict

Cannot approve until:

  1. Rate limiting is implemented (or at minimum, the email resolution is behind a feature flag disabled by default)
  2. The accidental memory file is removed from the commit

The code quality is good, but the security implications need addressing first.

@github-actions

Copy link
Copy Markdown

🚀 App preview deployment successfull at https://app.pr-106.props.build

Security fix for user enumeration vulnerability:
- Add in-memory rate limiter utility (10 req/min per IP)
- Apply rate limiting to email-based slug resolution in public pages
- Remove accidental memory file from repo
- Add .claude/memory/ to .gitignore

Addresses Che's review feedback on PR #106.
@github-actions

Copy link
Copy Markdown

🚀 Web preview deployment successfull at https://web.pr-106.props.build

@reviewer-props-to reviewer-props-to left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Approved

Previous concerns addressed:

  1. Rate limiting - Now implemented (10 req/min per IP). Good implementation:

    • Consistent 404 response when rate limited (no enumeration leak)
    • Proper IP extraction for proxy setups
    • Memory cleanup to prevent leaks
    • Clear comments about Redis for scale
  2. Memory file - Properly excluded via .gitignore

Security assessment: The email lookup is now reasonably protected against enumeration attacks. The in-memory rate limiter is fine for initial deployment; you can upgrade to Redis (e.g., @upstash/ratelimit) when scaling.

LGTM - ship it 🚀

@github-actions

Copy link
Copy Markdown

🚀 Auth preview deployment successfull at https://auth.pr-106.props.build

@github-actions

Copy link
Copy Markdown

🚀 Auth preview deployment successfull at https://auth.pr-106.props.build

@github-actions

Copy link
Copy Markdown

🚀 App preview deployment successfull at https://app.pr-106.props.build

@github-actions

Copy link
Copy Markdown

E2E Tests Failed

Tested against:

View details

@github-actions

Copy link
Copy Markdown

🚀 Web preview deployment successfull at https://web.pr-106.props.build

@github-actions

Copy link
Copy Markdown

🚀 Web preview deployment successfull at https://web.pr-106.props.build

@github-actions

Copy link
Copy Markdown

🚀 App preview deployment successfull at https://app.pr-106.props.build

@github-actions

Copy link
Copy Markdown

E2E Tests Failed

Tested against:

View details

@github-actions

Copy link
Copy Markdown

🚀 Auth preview deployment successfull at https://auth.pr-106.props.build

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