Skip to content

Merge test to main - #307

Merged
sweetmantech merged 1 commit into
mainfrom
test
Mar 17, 2026
Merged

Merge test to main#307
sweetmantech merged 1 commit into
mainfrom
test

Conversation

@sweetmantech

@sweetmantechsweetmantech commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Merge test branch into main after admin privy endpoint changes.

Summary by CodeRabbit

Release Notes

  • New Features
    • Added admin API endpoint to retrieve Privy login statistics filtered by time period (daily, weekly, monthly, or all-time)
    • Endpoint includes metrics for total users, new accounts, and active accounts
    • Requires admin authentication and supports CORS

* feat: add GET /api/admins/privy endpoint
Returns Privy login statistics (total count + login table) filtered
by daily/weekly/monthly time period. Requires admin authentication.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor: return full Privy user objects instead of filtered fields
The API was discarding most of the Privy user data (linked_accounts,
mfa_methods, is_guest, etc.) and only returning 3 fields. Now returns
the complete, unmodified user objects from the Privy Management API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove unsupported order param from Privy API call
The Privy GET /v1/users endpoint does not support the "order" parameter.
The code assumed desc ordering and stopped paginating on the first user
older than the cutoff, which meant it returned 0 results when the default
order is oldest-first. Now paginates through all users, filters by cutoff,
and sorts by created_at descending.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: normalize Privy created_at timestamp units before filtering
Privy docs say created_at is in milliseconds but examples show seconds
(10 digits). The code was comparing seconds against a millisecond cutoff,
causing incorrect filtering. Now auto-detects the unit (>1e12 = ms,
otherwise seconds) and normalizes to ms for comparison.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add total_new and total_active counts to privy endpoint
- total_new: accounts created within the period (created_at)
- total_active: accounts active within the period (latest_verified_at)
- fetchPrivyLogins now includes users matching either criteria
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: extract SRP files from fetchPrivyLogins
- toMs.ts: normalize Privy timestamps to milliseconds
- fetchPrivyUsersPage.ts: single-page Privy API fetch
- countNewAccounts.ts: count accounts created within period
- countActiveAccounts.ts: count accounts active within period
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: read latest_verified_at from linked_accounts, not top-level
latest_verified_at is nested inside each linked_accounts[] entry,
not at the top level of the Privy user object. Extracted
getLatestVerifiedAt to find the most recent verification across
all linked accounts for a user.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: address PR review comments
- Validate PRIVY_APP_ID/PRIVY_PROJECT_SECRET before use
- Add 10s timeout to Privy API fetch via AbortController
- Guard created_at with runtime type check before comparison
- Use Privy SDK types (User, LinkedAccount) instead of Record<string, unknown>
- Extract PERIOD_DAYS to shared periodDays.ts (DRY)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add total_privy_users to response for debugging discrepancies
Added total count of all Privy users to help identify if the API is
missing users compared to the Privy dashboard. Also applied PR review
fixes: credential validation, fetch timeout, runtime type guards,
SDK types, and DRY PERIOD_DAYS.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: import User type from @privy-io/node main entry
The package only exports from '.' and './viem', not from
'./resources/users'. Changed all imports to use '@privy-io/node'.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add 'all' period and make it the default
Default period is now 'all' (all time) instead of 'daily'.
Supported values: all, daily, weekly, monthly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use 'in' operator instead of type cast for latest_verified_at
All LinkedAccount union members have latest_verified_at, so use
'in' check for type-safe property access without casting.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: filter linked_accounts to email type only
- Response only includes email linked accounts, not wallets
- getLatestVerifiedAt only considers email account verification
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use midnight UTC calendar day boundaries to match Privy dashboard
Privy dashboard uses calendar day boundaries (e.g. weekly = last 7 days
from start of today), not rolling N*24 hours. Also reverted
getLatestVerifiedAt to check all linked accounts (not just email) since
the dashboard counts activity across all account types. Email filtering
remains only in the response payload.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove email-only filter and widen monthly cutoff
- Return full Privy user objects including wallet data (KISS)
- Widen cutoff from days-1 to days to capture borderline monthly users
- Active counts already use all linked accounts for latest_verified_at
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: revert cutoff to days-1 to restore weekly accuracy
The wider cutoff (days) broke weekly by including Mar 10 accounts.
The monthly off-by-one (5 vs 6 active) appears to be a Privy dashboard
internal metric that tracks session events beyond what the user list
API exposes via latest_verified_at.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: DRY period type and schema into privyLoginsPeriod.ts
Single source of truth for the Zod schema and PrivyLoginsPeriod type,
used by both fetchPrivyLogins and validateGetPrivyLoginsQuery.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: import PrivyLoginsPeriod from source, not re-exported
All files now import PrivyLoginsPeriod directly from
privyLoginsPeriod.ts instead of via fetchPrivyLogins.ts re-export.
Fixes build error where the type wasn't available in fetchPrivyLogins.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: remove stray blank line between imports
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Recoup Agent <agent@recoupable.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercelBot commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

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

ProjectDeploymentActionsUpdated (UTC)
recoup-apiBuildingBuildingPreviewMar 17, 2026 5:35pm

Request Review

@coderabbitai

coderabbitaiBot commented Mar 17, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4ea7abc2-e94b-41ce-b033-53e2188a3075

📥 Commits

Reviewing files that changed from the base of the PR and between 0b5421f and e3e7983.

⛔ Files ignored due to path filters (2)
  • lib/admins/privy/__tests__/getPrivyLoginsHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/admins/privy/__tests__/validateGetPrivyLoginsQuery.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
📒 Files selected for processing (12)
  • app/api/admins/privy/route.ts
  • lib/admins/privy/countActiveAccounts.ts
  • lib/admins/privy/countNewAccounts.ts
  • lib/admins/privy/fetchPrivyLogins.ts
  • lib/admins/privy/fetchPrivyUsersPage.ts
  • lib/admins/privy/getCutoffMs.ts
  • lib/admins/privy/getLatestVerifiedAt.ts
  • lib/admins/privy/getPrivyLoginsHandler.ts
  • lib/admins/privy/periodDays.ts
  • lib/admins/privy/privyLoginsPeriod.ts
  • lib/admins/privy/toMs.ts
  • lib/admins/privy/validateGetPrivyLoginsQuery.ts

📝 Walkthrough

Walkthrough

Introduces a new admin API endpoint for Privy login statistics at /api/admins/privy, along with supporting utilities to fetch Privy users via pagination, filter by time periods (daily, weekly, monthly, or all-time), validate admin authorization, and count active and new accounts.

Changes

Cohort / File(s)Summary
API Route Handler
app/api/admins/privy/route.ts
Exposes GET and OPTIONS handlers for the admin Privy endpoint; GET delegates to getPrivyLoginsHandler and OPTIONS responds with CORS headers and 204 status.
Data Fetching & Pagination
lib/admins/privy/fetchPrivyUsersPage.ts, lib/admins/privy/fetchPrivyLogins.ts
Implements paginated Privy API calls with Basic auth, 10-second timeout enforcement, and user aggregation; filters users by created_at and latest_verified_at timestamps based on the requested period.
Account Counting Logic
lib/admins/privy/countNewAccounts.ts, lib/admins/privy/countActiveAccounts.ts
Counts new accounts (by created_at) and active accounts (by latest verified timestamp) within a specified period cutoff.
Request Handling & Validation
lib/admins/privy/getPrivyLoginsHandler.ts, lib/admins/privy/validateGetPrivyLoginsQuery.ts
Main handler orchestrates data fetching and counting; validation function enforces admin auth and parses/validates period query parameter with Zod schema.
Timestamp & Period Utilities
lib/admins/privy/toMs.ts, lib/admins/privy/getCutoffMs.ts, lib/admins/privy/periodDays.ts, lib/admins/privy/getLatestVerifiedAt.ts
Converts timestamps between seconds/milliseconds, computes UTC midnight cutoffs aligned with Privy dashboard behavior, maps periods to day counts, and extracts latest verified timestamps from user linked accounts.
Types & Schemas
lib/admins/privy/privyLoginsPeriod.ts
Defines Zod-validated PrivyLoginsPeriod enum ("all", "daily", "weekly", "monthly") with inferred TypeScript type for runtime and compile-time validation.

Sequence Diagram

sequenceDiagram
actor Client
participant Route as API Route<br/>(GET/OPTIONS)
participant Handler as getPrivyLoginsHandler
participant Validator as Validation
participant Fetcher as fetchPrivyLogins
participant Privy as Privy API
participant Counter as Counting Logic
participant Response as JSON Response
Client->>Route: GET /api/admins/privy?period=weekly
Route->>Handler: invoke with request
Handler->>Validator: validateGetPrivyLoginsQuery()
Validator->>Response: return 401 if unauthorized
Validator->>Handler: return { period: "weekly" }
Handler->>Fetcher: fetchPrivyLogins("weekly")
loop Pagination
Fetcher->>Privy: fetchPrivyUsersPage(cursor)
Privy->>Fetcher: { data: User[], next_cursor? }
Fetcher->>Fetcher: filter & aggregate by cutoff
end
Fetcher->>Handler: { users, totalPrivyUsers }
Handler->>Counter: countNewAccounts(users, period)
Counter->>Handler: total_new count
Handler->>Counter: countActiveAccounts(users, period)
Counter->>Handler: total_active count
Handler->>Response: { status, total, total_new,<br/>total_active, total_privy_users, logins }
Response->>Client: 200 JSON + CORS headers
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • feat: add GET /api/admins/privy endpoint #306: Directly related; adds identical admin Privy endpoint and all supporting utilities (getPrivyLoginsHandler, fetchPrivyLogins, validation, account counting, timestamp helpers) to the same directory structure.

Poem

📊 A Privy glimpse through admin's eyes,
Logins tallied by time's disguise—
Periods parsed, accounts now known,
Active seeds and newborns shown! 🌱✨

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for freeto 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

@sweetmantech