Skip to content

feat(affiliates): Implement affiliate program with Stripe Connect#13

Draft
amoscicki wants to merge 28 commits into
mainfrom
AM04/feat/affiliates
Draft

feat(affiliates): Implement affiliate program with Stripe Connect#13
amoscicki wants to merge 28 commits into
mainfrom
AM04/feat/affiliates

Conversation

@amoscicki
Copy link
Copy Markdown
Owner

No description provided.

@amoscicki amoscicki force-pushed the AM04/feat/affiliates branch from 1de114a to 186f77f Compare December 25, 2025 12:00
@amoscicki amoscicki force-pushed the AM03/bugfix/34-profile-image-presigned-urls branch from fd30fdc to f244b7a Compare December 25, 2025 12:03
@amoscicki amoscicki force-pushed the AM04/feat/affiliates branch 2 times, most recently from d8969d4 to d94a9fe Compare December 25, 2025 12:12
@amoscicki amoscicki force-pushed the AM03/bugfix/34-profile-image-presigned-urls branch from f244b7a to cd1a684 Compare December 25, 2025 12:12
@amoscicki amoscicki force-pushed the AM04/feat/affiliates branch from d94a9fe to 332e994 Compare December 25, 2025 12:23
@amoscicki amoscicki force-pushed the AM03/bugfix/34-profile-image-presigned-urls branch from cd1a684 to 0cec8f9 Compare December 25, 2025 12:23
@amoscicki amoscicki force-pushed the AM04/feat/affiliates branch from 332e994 to 123bddb Compare December 25, 2025 13:07
@amoscicki amoscicki force-pushed the AM03/bugfix/34-profile-image-presigned-urls branch from 0cec8f9 to 6e6f5ef Compare December 25, 2025 13:08
@amoscicki amoscicki changed the base branch from AM03/bugfix/34-profile-image-presigned-urls to graphite-base/13 December 27, 2025 23:41
@amoscicki amoscicki changed the base branch from graphite-base/13 to AM02a/fix/dev-mode-and-playwright-tests December 27, 2025 23:48
@amoscicki amoscicki changed the base branch from AM02a/fix/dev-mode-and-playwright-tests to graphite-base/13 December 27, 2025 23:53
@amoscicki amoscicki changed the base branch from graphite-base/13 to AM03/bugfix/34-profile-image-presigned-urls December 27, 2025 23:54
@amoscicki amoscicki force-pushed the AM04/feat/affiliates branch from b9cae4c to 843ef0b Compare December 28, 2025 05:34
@amoscicki amoscicki force-pushed the AM03/bugfix/34-profile-image-presigned-urls branch from a5fc4a7 to eb271f0 Compare December 28, 2025 05:34
@amoscicki amoscicki changed the title feat: Placeholder for affiliates feature feat(affiliates): Implement affiliate program with Stripe Connect Dec 28, 2025
@amoscicki amoscicki force-pushed the AM04/feat/affiliates branch from 843ef0b to 9e83071 Compare December 28, 2025 05:58
@amoscicki amoscicki force-pushed the AM03/bugfix/34-profile-image-presigned-urls branch from eb271f0 to 4de4dff Compare December 28, 2025 05:58
@amoscicki amoscicki force-pushed the AM04/feat/affiliates branch from d16329f to e5f00b3 Compare December 28, 2025 20:52
amoscicki and others added 28 commits December 28, 2025 20:57
- Generate fresh presigned URLs in data-access layer instead of storing
- Profile images now persist indefinitely (no 1-hour expiry)
- Upload only stores imageId (R2 key), not the presigned URL
…mponent

- Add /admin/pricing page for managing course pricing
- Create reusable NumberInputWithControls component with +/- buttons
- Add Pricing link to admin navigation
- Fix pricing display: promo discount as main, affiliate as extra
- Update purchase page to show correct discount hierarchy

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show real referral/conversion history in Activity timeline
- Show real payout history with status colors
- Add avatar images to affiliate table and details sheet
- Add pagination support for referrals and payouts (limit/offset)
- Use NumberInputWithControls for commission rate editing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ements

- Add Stripe Connect OAuth routes for affiliate onboarding
- Update affiliate dashboard with improved layout
- Add affiliate use-cases updates
- Update schema and route tree

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update package.json and pnpm-lock.yaml
- Update vite.config.ts
- Update env.ts with new variables
- Minor UI and client updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… button

- Limit initial load to 10 referrals and 10 payouts
- Add "Load older activity" button to fetch more
- Use useEffect for proper state management
- Track hasMore flags from paginated responses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove complex pagination state management that caused issues
- Use direct data from queries instead of accumulated state
- Show "+ more activity..." indicator when there's more data
- Full pagination can be added later if needed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…se-case

- getAffiliateReferrals and getAffiliatePayouts now return { items, hasMore }
- Update getAffiliateAnalyticsUseCase to extract .items for dashboard

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove duplicate Payment Information / Stripe Connect cards into single card
- Show business name and account type from Stripe API
- Hide Edit button when custom payment links disabled
- Fix misleading messages (instant payouts, not $50 minimum for Stripe)
- Add stripeAccountType column to affiliates schema
- Fetch Stripe account name dynamically in dashboard use-case

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract logMiddleware to dedicated server-logger.ts module
- Add readable function names instead of base64 encoded IDs
- Add configurable scopes (default, payments, auth, affiliates, etc.)
- Support both backward compat (.middleware([logMiddleware])) and
  explicit scopes (.middleware([logMiddleware(LOG_SCOPES.PAYMENTS)]))
- Fix URL-safe base64 decoding for function IDs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add STRIPE_CLIENT_ID for OAuth2 Connect flow
- Add note about STRIPE_PRICE_ID being deprecated
- Remove dev patches section (moved to .dev/)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add stripeAccountStatusEnum and affiliatePaymentMethodEnum
- Add CHECK constraint ensuring discountRate <= commissionRate
- Generate migrations 0051 and 0052
- Add dedicated TOKEN_SIGNING_SECRET env var for token signing
- Create url-sanitizer.ts for XSS protection on URLs
- Update crypto.ts to use new secret instead of STRIPE_WEBHOOK_SECRET
- Refactor to use SendRawEmailCommand for MIME headers
- Add List-Unsubscribe header for better email deliverability
- GET functions now return { success: true, data: ... }
- Add feature flag middleware to Stripe account functions
- Fix pagination in data-access layer
- Update all consumers to access .data from server responses
- Fix Rate input width (w-30) to fit 100%
- Fix onboarding flow to prevent re-registration of existing affiliates
- Improve error handling and logging
- Use URL sanitizer for redirect URLs
- Remove unused imports and dead code
- Improve type safety
- Document server function response format convention
- Add extensible server logger with scopes
- Fix affiliate payout failed email template
Add `strict` prop to FeatureFlag component and useFeatureFlag hook that
respects actual flag state even for admins. This is useful for admin
panel where we want to hide Payment Link features behind the flag
regardless of admin privileges.

- Min Payout control hidden behind AFFILIATE_CUSTOM_PAYMENT_LINK flag
- Batch Settle button hidden behind flag
- Record Payout dialog hidden behind flag

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove 'pending' from stripeAccountStatus type (not in DB schema)
- Add updatePaymentMethodFn export alias for backward compatibility
- Add missing updateAffiliateCommissionRate import
- Fix refreshStripeStatusMutation call to use { data: undefined }
- Update determineStripeAccountStatus return type to StripeAccountStatusType

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update affiliate documentation to reflect:
- Commission rate is now configurable by admin (default 30%)
- Minimum payout is configurable and only applies to Payment Link affiliates
- Stripe Connect affiliates have no minimum threshold

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add timingSafeStringEqual for CSRF state validation in refresh route
- Remove unused imports (useSuspenseQuery, authenticatedMiddleware)
- Add PERF comment for future suspense query optimization
- Remove explicit Stripe API version to use SDK default

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- fix(feature-flags): Replace no-op stub with proper toggle function for
  VIDEO_SEGMENT_CONTENT_TABS flag that was causing "action is not a function" error

- fix(affiliate-dashboard): Replace hardcoded "$50.00" minimum payout with
  dynamic value from AFFILIATE_CONFIG using Intl.NumberFormat

- fix(stripe-callback): Defer cookie deletion until successful completion
  to allow OAuth retry on transient errors; only clear cookies on security
  violations or success

- fix(purchase): Extract magic numbers to named constants (CENTS_PER_DOLLAR,
  PERCENTAGE_DIVISOR) for clarity and maintainability

- fix(purchase): Add DefaultCatchBoundary error component to route

- perf(purchase): Move stripePromise to module level to avoid redundant
  loadStripe calls on each checkout attempt

- fix(purchase): Add missing semicolon and fix useCallback dependency array
@amoscicki amoscicki force-pushed the AM04/feat/affiliates branch from e5f00b3 to bb7821f Compare December 28, 2025 20:57
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.

1 participant