Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@devkiran
Copy link
Collaborator

@devkiran devkiran commented Jul 4, 2025

Summary by CodeRabbit

  • New Features

    • Introduced export functionality for audit logs as CSV files, accessible to enterprise plan users.
    • Added new dashboard components for managing and exporting audit logs, SAML SSO, and SCIM directory sync.
    • Enhanced security settings page with modular components for SAML, SCIM, and audit logs management.
  • Improvements

    • Added audit logging across partner, commission, discount, reward, and payout actions for improved traceability.
    • Enabled audit log viewing and export with date range selection and user feedback.
    • Updated date range picker to support disabling based on permissions.
  • Bug Fixes

    • Improved permission and plan checks for audit log export and security features.
  • Chores

    • Added new schemas and endpoints to support audit log storage and querying.
    • Updated plan capabilities to reflect audit log export availability for enterprise plans.

devkiran added 9 commits June 28, 2025 16:35
- Introduced new `record-audit-log.ts` to handle recording of audit logs.
- Created `schemas.ts` for defining audit log schemas using Zod.
- Added `dub_audit_logs.datasource` for Tinybird integration.
- Updated `create-id.ts` to include "audit_" prefix for generated IDs.
@vercel
Copy link
Contributor

vercel bot commented Jul 4, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
dub ✅ Ready (Inspect) Visit Preview Jul 4, 2025 7:30pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 4, 2025

Warning

Rate limit exceeded

@steven-tey has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 11 minutes and 1 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between ffaf2b5 and c362a05.

📒 Files selected for processing (1)
  • apps/web/lib/api/audit-logs/record-audit-log.ts (1 hunks)

Walkthrough

This update introduces a comprehensive audit logging system across the application. It adds new backend APIs, data schemas, and UI components to record, fetch, and export audit logs. Audit log recording is integrated into numerous partner and commission actions, with corresponding Tinybird data pipelines and datasources. The workspace security dashboard is refactored to modularize SAML, SCIM, and audit log export functionality.

Changes

Files / Paths Change Summary
.../api/audit-logs/export/route.ts Adds POST API endpoint for exporting audit logs as CSV with workspace and permission checks.
.../api/commissions/[commissionId]/route.ts Refactors PATCH handler to include session context and audit logging on commission updates.
.../api/cron/payouts/confirm/confirm-payouts.ts Adds background audit log recording for each payout confirmed.
.../app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/page-client.tsx Refactors to render modular SAML, SCIM, and AuditLogs components; removes inline logic for SAML/SCIM sections.
.../settings/security/saml.tsx
.../settings/security/scim.tsx
.../settings/security/audit-logs.tsx
New React components for SAML SSO, SCIM sync, and audit log export management in workspace security dashboard.
.../lib/api/audit-logs/get-audit-logs.ts
.../lib/api/audit-logs/record-audit-log.ts
.../lib/api/audit-logs/schemas.ts
New modules for audit log fetching, ingestion, and schema validation using Tinybird and Zod.
.../lib/api/create-id.ts Adds "audit_" to allowed ID prefixes.
.../lib/api/programs/get-program-enrollment-or-throw.ts Updates function to optionally include partner data in enrollment queries.
.../lib/plan-capabilities.ts Adds canExportAuditLogs flag for enterprise plan check.
.../ui/shared/simple-date-range-picker.tsx Adds optional disabled prop to date range picker.
.../lib/actions/partners/.ts
.../lib/partners/
.ts
Integrates audit log recording into partner, commission, reward, discount, payout, and program actions.
packages/tinybird/datasources/dub_audit_logs.datasource Introduces Tinybird datasource schema for audit logs with TTL and indexing.
packages/tinybird/pipes/get_audit_logs.pipe Adds Tinybird pipe to query audit logs with filters and ordering.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WebApp
    participant API
    participant Tinybird

    User->>WebApp: Clicks "Export Audit Logs"
    WebApp->>API: POST /api/audit-logs/export {start, end}
    API->>Tinybird: Fetch audit logs (get_audit_logs.pipe)
    Tinybird-->>API: Returns audit log data
    API-->>WebApp: Returns CSV file
    WebApp-->>User: Triggers CSV download
Loading
sequenceDiagram
    participant User
    participant WebApp
    participant API
    participant Tinybird

    User->>WebApp: Performs partner/commission action
    WebApp->>API: Action request (e.g., approve, ban, update)
    API->>Tinybird: recordAuditLog (ingest audit log)
    Tinybird-->>API: Ingestion confirmation
    API-->>WebApp: Action response
Loading

Suggested reviewers

  • steven-tey

Poem

🐇
Audit logs now hop and bound,
Through every action, safe and sound.
Export as CSV, with dates you pick,
SAML and SCIM in modules click.
Rabbits log each partner’s tale—
Enterprise plans now set the trail!
📝✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@devkiran devkiran marked this pull request as ready for review July 4, 2025 13:21
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (8)
apps/web/app/(ee)/api/audit-logs/export/route.ts (2)

22-27: Remove redundant validation.

The schema already validates that start and end are strings, so this additional check is unnecessary since auditLogExportQuerySchema.parse() would have already thrown an error for missing fields.

-    if (!start || !end) {
-      throw new DubApiError({
-        code: "bad_request",
-        message: "Must provide start and end dates.",
-      });
-    }

52-52: Add filename to Content-Disposition header.

The CSV export should include a descriptive filename for better user experience.

-        "Content-Disposition": `attachment;`,
+        "Content-Disposition": `attachment; filename="audit-logs-${start}-${end}.csv"`,
apps/web/lib/api/audit-logs/record-audit-log.ts (1)

12-40: Consider data consistency improvements.

The transformation function is well-structured but has some considerations:

  1. Location extraction inconsistency: The function tries ipAddress(data.req) first, then falls back to getIP(), but the logic might be inconsistent.

  2. Empty string defaults: Some fields default to empty strings instead of null, which might not match the Tinybird schema expectations.

Consider this improvement for better data consistency:

-    location: location || "",
-    user_agent: userAgent || "",
+    location: location || null,
+    user_agent: userAgent || null,

And ensure the Tinybird schema handles nulls appropriately.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/audit-log.tsx (2)

23-25: Improve the workspace ID validation.

The current check if (!workspaceId) return; silently fails without user feedback. Consider providing user feedback or using a more robust validation approach.

Apply this diff to provide better user feedback:

-if (!workspaceId) {
-  return;
-}
+if (!workspaceId) {
+  toast.error("Workspace not found");
+  return;
+}

60-62: Improve error handling specificity.

The error handling could be more specific about the error type and provide better user feedback.

Apply this diff to improve error handling:

 } catch (error) {
-  toast.error(error);
+  toast.error(error instanceof Error ? error.message : "Failed to export audit logs");
 } finally {
apps/web/lib/api/audit-logs/get-audit-logs.ts (2)

45-46: Document the date formatting logic.

The date formatting logic that replaces "T" with space and removes "Z" appears to be specific to Tinybird's expected format. Consider adding a comment to explain this transformation.

Apply this diff to improve documentation:

+    // Convert ISO date to Tinybird format: "YYYY-MM-DD HH:mm:ss"
     start: start.toISOString().replace("T", " ").replace("Z", ""),
     end: end.toISOString().replace("T", " ").replace("Z", ""),

45-46: Consider extracting date formatting to a utility function.

The date formatting logic could be reused elsewhere. Consider extracting it to a utility function for better maintainability.

Create a utility function:

const formatDateForTinybird = (date: Date): string => {
  return date.toISOString().replace("T", " ").replace("Z", "");
};

Then use it in the function:

-    start: start.toISOString().replace("T", " ").replace("Z", ""),
-    end: end.toISOString().replace("T", " ").replace("Z", ""),
+    start: formatDateForTinybird(start),
+    end: formatDateForTinybird(end),
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/saml.tsx (1)

94-126: Consider extracting popover menu logic.

The popover implementation is correct but could be extracted into a separate component for better reusability, especially if similar action menus are used elsewhere in the security settings.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a9811a and 0dbaf64.

📒 Files selected for processing (42)
  • apps/web/app/(ee)/api/audit-logs/export/route.ts (1 hunks)
  • apps/web/app/(ee)/api/commissions/[commissionId]/route.ts (2 hunks)
  • apps/web/app/(ee)/api/cron/payouts/confirm/confirm-payouts.ts (3 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/audit-log.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/page-client.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/saml.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/scim.tsx (1 hunks)
  • apps/web/lib/actions/partners/approve-partners-bulk.ts (2 hunks)
  • apps/web/lib/actions/partners/archive-partner.ts (3 hunks)
  • apps/web/lib/actions/partners/ban-partner.ts (4 hunks)
  • apps/web/lib/actions/partners/create-clawback.ts (2 hunks)
  • apps/web/lib/actions/partners/create-commission.ts (4 hunks)
  • apps/web/lib/actions/partners/create-discount.ts (3 hunks)
  • apps/web/lib/actions/partners/create-program.ts (2 hunks)
  • apps/web/lib/actions/partners/create-reward.ts (2 hunks)
  • apps/web/lib/actions/partners/delete-discount.ts (4 hunks)
  • apps/web/lib/actions/partners/delete-program-invite.ts (3 hunks)
  • apps/web/lib/actions/partners/delete-reward.ts (3 hunks)
  • apps/web/lib/actions/partners/invite-partner.ts (3 hunks)
  • apps/web/lib/actions/partners/mark-commission-duplicate.ts (3 hunks)
  • apps/web/lib/actions/partners/mark-commission-fraud-or-canceled.ts (3 hunks)
  • apps/web/lib/actions/partners/mark-payout-paid.ts (4 hunks)
  • apps/web/lib/actions/partners/reject-partner.ts (3 hunks)
  • apps/web/lib/actions/partners/reject-partners-bulk.ts (3 hunks)
  • apps/web/lib/actions/partners/resend-program-invite.ts (4 hunks)
  • apps/web/lib/actions/partners/unban-partner.ts (3 hunks)
  • apps/web/lib/actions/partners/update-auto-approve-partners.ts (2 hunks)
  • apps/web/lib/actions/partners/update-discount.ts (3 hunks)
  • apps/web/lib/actions/partners/update-program.ts (4 hunks)
  • apps/web/lib/actions/partners/update-reward.ts (3 hunks)
  • apps/web/lib/api/audit-logs/get-audit-logs.ts (1 hunks)
  • apps/web/lib/api/audit-logs/record-audit-log.ts (1 hunks)
  • apps/web/lib/api/audit-logs/schemas.ts (1 hunks)
  • apps/web/lib/api/create-id.ts (1 hunks)
  • apps/web/lib/api/programs/get-program-enrollment-or-throw.ts (2 hunks)
  • apps/web/lib/partners/approve-partner-enrollment.ts (3 hunks)
  • apps/web/lib/partners/bulk-approve-partners.ts (4 hunks)
  • apps/web/lib/partners/create-partner-commission.ts (4 hunks)
  • apps/web/lib/plan-capabilities.ts (1 hunks)
  • apps/web/ui/shared/simple-date-range-picker.tsx (2 hunks)
  • packages/tinybird/datasources/dub_audit_logs.datasource (1 hunks)
  • packages/tinybird/pipes/audit_logs.pipe (1 hunks)
🧰 Additional context used
🧠 Learnings (18)
apps/web/lib/actions/partners/approve-partners-bulk.ts (2)
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
Learnt from: devkiran
PR: dubinc/dub#2510
File: apps/web/lib/actions/partners/onboard-program.ts:16-19
Timestamp: 2025-06-10T19:16:23.445Z
Learning: Business rule: Each workspace may have at most one program; attempting to create more must be blocked in code.
apps/web/lib/actions/partners/create-clawback.ts (1)
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
apps/web/lib/actions/partners/delete-program-invite.ts (1)
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
apps/web/lib/actions/partners/reject-partners-bulk.ts (2)
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
apps/web/lib/actions/partners/create-discount.ts (1)
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
apps/web/lib/actions/partners/create-program.ts (1)
Learnt from: devkiran
PR: dubinc/dub#2510
File: apps/web/lib/actions/partners/onboard-program.ts:16-19
Timestamp: 2025-06-10T19:16:23.445Z
Learning: Business rule: Each workspace may have at most one program; attempting to create more must be blocked in code.
apps/web/lib/actions/partners/mark-commission-duplicate.ts (1)
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
apps/web/lib/actions/partners/reject-partner.ts (1)
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
apps/web/lib/partners/approve-partner-enrollment.ts (1)
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
apps/web/app/(ee)/api/cron/payouts/confirm/confirm-payouts.ts (2)
Learnt from: steven-tey
PR: dubinc/dub#0
File: :0-0
Timestamp: 2025-06-25T21:20:59.837Z
Learning: In the Dub codebase, payout limit validation uses a two-stage pattern: server actions perform quick sanity checks (payoutsUsage > payoutsLimit) for immediate user feedback, while the cron job (/cron/payouts) performs authoritative validation (payoutsUsage + payoutAmount > payoutsLimit) with actual calculated amounts before processing. This design provides fast user feedback while ensuring accurate limit enforcement at transaction time.
Learnt from: steven-tey
PR: dubinc/dub#0
File: :0-0
Timestamp: 2025-06-19T01:46:45.723Z
Learning: PayPal webhook verification in the Dub codebase is handled at the route level in `apps/web/app/(ee)/api/paypal/webhook/route.ts` using the `verifySignature` function. Individual webhook handlers like `payoutsItemFailed` don't need to re-verify signatures since they're only called after successful verification.
apps/web/lib/actions/partners/update-program.ts (2)
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
Learnt from: devkiran
PR: dubinc/dub#2510
File: apps/web/lib/actions/partners/onboard-program.ts:16-19
Timestamp: 2025-06-10T19:16:23.445Z
Learning: Business rule: Each workspace may have at most one program; attempting to create more must be blocked in code.
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/audit-log.tsx (1)
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
apps/web/lib/api/programs/get-program-enrollment-or-throw.ts (1)
Learnt from: devkiran
PR: dubinc/dub#2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
apps/web/lib/actions/partners/unban-partner.ts (1)
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
apps/web/lib/partners/bulk-approve-partners.ts (1)
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/page-client.tsx (1)
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
apps/web/lib/actions/partners/ban-partner.ts (1)
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/saml.tsx (1)
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
🧬 Code Graph Analysis (18)
apps/web/lib/actions/partners/delete-program-invite.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/delete-reward.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/resend-program-invite.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/create-discount.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/delete-discount.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/create-program.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/partners/approve-partner-enrollment.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/app/(ee)/api/cron/payouts/confirm/confirm-payouts.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/api/audit-logs/record-audit-log.ts (3)
apps/web/lib/api/audit-logs/schemas.ts (2)
  • recordAuditLogInputSchema (170-185)
  • auditLogSchemaTB (10-24)
apps/web/lib/api/create-id.ts (1)
  • createId (55-64)
packages/utils/src/functions/log.ts (1)
  • log (9-45)
apps/web/lib/actions/partners/update-program.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/mark-commission-fraud-or-canceled.ts (2)
apps/web/lib/api/partners/sync-total-commissions.ts (1)
  • syncTotalCommissions (4-35)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/archive-partner.ts (3)
apps/web/lib/actions/safe-action.ts (1)
  • authActionClient (33-82)
apps/web/lib/zod/schemas/partners.ts (1)
  • archivePartnerSchema (574-577)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/mark-payout-paid.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/partners/create-partner-commission.ts (5)
apps/web/lib/types.ts (1)
  • RewardProps (472-472)
packages/prisma/client.ts (1)
  • CommissionType (5-5)
apps/web/lib/auth/utils.ts (1)
  • Session (6-16)
apps/web/lib/api/partners/sync-total-commissions.ts (1)
  • syncTotalCommissions (4-35)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/update-discount.ts (1)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/unban-partner.ts (4)
apps/web/lib/api/programs/get-default-program-id-or-throw.ts (1)
  • getDefaultProgramIdOrThrow (4-17)
apps/web/lib/api/programs/get-program-enrollment-or-throw.ts (1)
  • getProgramEnrollmentOrThrow (6-85)
apps/web/lib/api/links/cache.ts (1)
  • linkCache (102-102)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/lib/actions/partners/ban-partner.ts (6)
apps/web/lib/api/programs/get-default-program-id-or-throw.ts (1)
  • getDefaultProgramIdOrThrow (4-17)
apps/web/lib/api/programs/get-program-enrollment-or-throw.ts (1)
  • getProgramEnrollmentOrThrow (6-85)
packages/email/src/index.ts (1)
  • sendEmail (6-29)
packages/email/src/templates/partner-banned.tsx (1)
  • PartnerBanned (17-84)
apps/web/lib/zod/schemas/partners.ts (1)
  • BAN_PARTNER_REASONS (38-45)
apps/web/lib/api/audit-logs/record-audit-log.ts (1)
  • recordAuditLog (42-62)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/saml.tsx (2)
packages/ui/src/icons/nucleo/lock.tsx (1)
  • Lock (3-48)
packages/ui/src/tooltip.tsx (1)
  • TooltipContent (90-128)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (61)
apps/web/lib/actions/partners/approve-partners-bulk.ts (1)

49-49: LGTM! User context properly passed for audit logging.

The change from userId: user.id to user correctly passes the entire user object to support audit logging functionality in the bulkApprovePartners function.

apps/web/ui/shared/simple-date-range-picker.tsx (1)

8-8: LGTM! Proper disabled prop implementation.

The disabled prop is correctly added with proper TypeScript typing and forwarded to the underlying DateRangePicker component. This supports the audit log export feature gating.

Also applies to: 13-13, 74-74

apps/web/lib/api/create-id.ts (1)

29-29: LGTM! Audit prefix properly added.

The "audit_" prefix is correctly added to support audit log ID generation, following the established naming pattern.

apps/web/lib/plan-capabilities.ts (1)

13-13: LGTM! Enterprise-only audit log export capability correctly implemented.

The canExportAuditLogs flag properly restricts audit log export functionality to enterprise plans only, following the established pattern for other capability flags.

apps/web/lib/actions/partners/create-commission.ts (2)

22-22: LGTM! User context properly extracted for audit logging.

The user is correctly extracted from the context to support audit logging in commission creation.


63-65: LGTM! Consistent audit logging parameters across all commission types.

The user and workspaceId parameters are consistently added to all three commission creation calls (custom, lead, and sale), ensuring proper audit logging coverage across all commission types.

Also applies to: 184-186, 220-222

apps/web/lib/actions/partners/create-clawback.ts (1)

12-12: LGTM! Clean integration of audit logging context.

The extraction of user from context and passing it to createPartnerCommission along with workspaceId follows the established pattern for enabling audit logging in partner actions.

Also applies to: 29-30

apps/web/lib/actions/partners/delete-program-invite.ts (1)

3-3: LGTM! Comprehensive audit logging implementation.

The audit log integration is well-implemented with proper error isolation using Promise.allSettled and includes all necessary context (workspace, program, actor, target with metadata). The action type "partner.invite_deleted" is descriptive and follows the established naming convention.

Also applies to: 19-19, 60-73

packages/tinybird/datasources/dub_audit_logs.datasource (1)

1-19: LGTM! Well-designed audit log schema.

The datasource schema demonstrates excellent design choices:

  • LowCardinality for action and actor_type fields optimizes storage for frequently repeated values
  • Partitioning by toYYYYMM(timestamp) provides efficient time-based data management
  • Sorting key workspace_id, program_id, timestamp enables fast queries by workspace and program
  • 1-year TTL is appropriate for audit log retention policies
  • JSON path extraction allows flexible data ingestion
apps/web/lib/actions/partners/create-reward.ts (1)

3-3: LGTM! Proper audit logging implementation.

The audit log integration follows the established pattern correctly:

  • Uses waitUntil appropriately for the async audit log operation
  • Includes comprehensive audit context (workspace, program, actor, target with metadata)
  • Action type "reward.created" is descriptive and consistent with naming conventions

Also applies to: 11-11, 17-17, 114-131

apps/web/lib/actions/partners/create-program.ts (1)

1-1: LGTM! Clean integration into existing async operations.

The audit log recording is properly integrated into the existing Promise.allSettled call, maintaining consistency with other post-creation operations. The audit log structure appropriately captures the program creation event with comprehensive metadata.

Also applies to: 200-213

apps/web/lib/actions/partners/delete-reward.ts (1)

3-3: LGTM - Audit logging implementation follows best practices.

The audit logging implementation is well-structured:

  • Uses asynchronous logging with waitUntil to avoid blocking the main action
  • Captures relevant metadata from the fetched reward before deletion
  • Follows consistent pattern with other audit logging implementations

Also applies to: 8-8, 20-20, 66-83

apps/web/lib/actions/partners/reject-partner.ts (1)

3-3: LGTM - Proper inclusion of partner data for audit logging.

The changes correctly:

  • Include the partner relation in the query to access partner metadata for audit logging
  • Follow the established async audit logging pattern with waitUntil
  • Use appropriate action type and descriptive message

Also applies to: 7-7, 14-14, 26-28, 44-61

apps/web/lib/actions/partners/update-reward.ts (1)

3-3: LGTM - Audit logging correctly captures reward update.

The implementation properly:

  • Uses the updatedReward from the Prisma update operation for metadata
  • Places audit logging after all business logic completion
  • Follows the established async pattern with waitUntil

Also applies to: 12-12, 18-18, 85-102

apps/web/app/(ee)/api/cron/payouts/confirm/confirm-payouts.ts (1)

273-307: LGTM - Good practice to refetch payouts before audit logging.

The refetch to confirm payouts are in "processing" state before logging is a good practice that ensures data consistency for the audit trail.

apps/web/lib/actions/partners/reject-partners-bulk.ts (1)

3-3: LGTM - Proper bulk audit logging implementation.

The implementation correctly:

  • Includes the partner relation in the query for audit log metadata
  • Maps over program enrollments to create individual audit log entries for each rejection
  • Uses the established async audit logging pattern with waitUntil
  • Maintains consistency with the single partner rejection action

Also applies to: 8-8, 15-15, 30-30, 49-68

apps/web/lib/actions/partners/invite-partner.ts (2)

96-96: Good practice: Capturing the enrolled partner result.

Properly capturing the enrolledPartner result for use in the audit log metadata ensures consistent tracking of partner enrollment actions.


110-142: Excellent implementation of concurrent async operations.

The use of Promise.allSettled to run email sending and audit logging concurrently is a good pattern that ensures neither operation blocks the other, while maintaining proper error isolation.

packages/tinybird/pipes/audit_logs.pipe (1)

5-26: Well-structured audit log query with proper filtering.

The query structure effectively retrieves audit log data with conditional filtering support for date ranges, workspace, and program scope. The descending timestamp ordering ensures most recent logs appear first.

apps/web/lib/actions/partners/mark-payout-paid.ts (2)

19-19: Proper context extraction for audit logging.

Adding user to the context extraction enables proper actor tracking in the audit log.


50-67: Consistent audit logging implementation.

The audit log recording follows the established pattern of using waitUntil for async execution without blocking the main action flow. The payout metadata is properly captured in the audit log.

apps/web/lib/partners/approve-partner-enrollment.ts (2)

122-130: Appropriate user fetching for audit logging.

Using findUniqueOrThrow ensures the actor information is available for audit logging, properly handling cases where the user might not exist.


169-182: Well-integrated audit logging with existing operations.

The audit log recording is properly integrated into the existing Promise.allSettled alongside email and webhook operations, maintaining consistent async execution patterns.

apps/web/lib/actions/partners/create-discount.ts (2)

17-17: Proper context extraction for audit logging.

Adding user to the context extraction enables proper actor tracking in the audit log.


100-129: Consistent concurrent operation pattern.

The implementation properly uses Promise.allSettled to execute cache invalidation and audit logging concurrently, following the established pattern seen in other audit logging integrations.

apps/web/lib/actions/partners/resend-program-invite.ts (1)

52-89: LGTM! Good use of Promise.allSettled for resilient concurrent operations.

The switch from Promise.all to Promise.allSettled ensures all operations are attempted even if one fails, which is appropriate for this use case. The audit log entry is comprehensive with proper metadata including workspace, program, action type, and target information.

apps/web/lib/actions/partners/delete-discount.ts (1)

102-129: LGTM! Proper audit logging implementation.

The audit log correctly captures the discount data before deletion and uses Promise.allSettled to ensure both the cache invalidation and audit logging are attempted even if one fails.

apps/web/lib/actions/partners/update-program.ts (1)

134-147: LGTM! Clean integration of audit logging.

The audit log properly captures the updated program state and is well-integrated into the existing async operations pattern. Using the updatedProgram data for the audit log metadata is appropriate for tracking the final state after the update.

apps/web/lib/actions/partners/mark-commission-duplicate.ts (1)

77-99: LGTM! Consistent audit logging pattern.

The audit log correctly captures the commission data before any modifications and uses Promise.allSettled to ensure both the commission sync and audit logging are attempted even if one fails. The implementation follows the established pattern across the codebase.

apps/web/lib/actions/partners/mark-commission-fraud-or-canceled.ts (3)

3-3: LGTM: Clean audit log import added.

The import follows the established pattern used across other files in this PR.


21-21: LGTM: User extracted from context for audit logging.

This change aligns with the audit logging requirements to capture the acting user information.


116-141: LGTM: Excellent concurrent execution pattern with audit logging.

The implementation correctly:

  • Uses Promise.allSettled for concurrent execution of commission sync and audit logging
  • Conditionally sets action type based on status (commission.marked_fraud vs commission.canceled)
  • Includes comprehensive audit metadata (commission ID, actor, targets with full commission data)
  • Maintains error isolation between operations
apps/web/lib/actions/partners/update-auto-approve-partners.ts (4)

3-3: LGTM: Necessary imports added for audit logging.

The imports follow the established pattern used across other files in this PR.

Also applies to: 6-6


18-18: LGTM: User extracted from context for audit logging.

This change aligns with the audit logging requirements to capture the acting user information.


23-31: LGTM: Program object returned for better API response.

Returning the updated program object provides better response data for API consumers.


32-47: LGTM: Well-structured audit logging implementation.

The audit log implementation correctly:

  • Uses conditional action types (auto_approve_partner.enabled vs auto_approve_partner.disabled)
  • Provides clear, user-friendly descriptions
  • Includes necessary context (workspace, program, actor)
  • Executes asynchronously to avoid blocking the main flow
apps/web/lib/actions/partners/archive-partner.ts (4)

3-3: LGTM: Necessary imports added for audit logging.

The imports follow the established pattern used across other files in this PR.

Also applies to: 8-8


15-15: LGTM: User extracted from context for audit logging.

This change aligns with the audit logging requirements to capture the acting user information.


25-39: LGTM: Enhanced query to support audit logging.

The query modification correctly:

  • Includes partner data needed for audit log metadata
  • Returns the status for conditional audit log action
  • Maintains the original toggle logic

41-59: LGTM: Proper audit logging with conditional actions.

The audit log implementation correctly:

  • Uses conditional action types (partner.archived vs partner.approved)
  • Includes partner metadata in targets for comprehensive audit trail
  • Executes asynchronously to avoid blocking the main flow
  • Follows the established pattern
apps/web/lib/partners/bulk-approve-partners.ts (4)

9-9: LGTM: Necessary imports added for audit logging and type definitions.

The imports follow the established pattern and provide necessary type definitions for the signature change.

Also applies to: 12-12


22-22: LGTM: Function signature enhanced with full user object.

The change from userId: string to user: Session["user"] provides richer context for audit logging. This breaking change should be coordinated with all callers.

Also applies to: 27-27


66-66: LGTM: Consistent use of user.id for partner link generation.

The change maintains compatibility with the existing generatePartnerLink function while using the new user object structure.


121-136: LGTM: Efficient bulk audit logging implementation.

The audit log implementation correctly:

  • Records individual audit logs for each approved partner
  • Uses array input to recordAuditLog for efficient batch processing
  • Includes comprehensive partner metadata in targets
  • Follows the established pattern with descriptive action type
apps/web/lib/api/audit-logs/record-audit-log.ts (4)

1-8: LGTM: Well-structured imports for audit logging infrastructure.

The imports cover all necessary utilities for data transformation, validation, and ingestion.


10-10: LGTM: Clean type definition from schema.

Using z.infer ensures type safety and consistency with the validation schema.


42-62: LGTM: Robust error handling with logging.

The function correctly:

  • Handles both single and array inputs
  • Includes comprehensive error logging
  • Uses Slack notifications for error alerts
  • Avoids throwing errors to prevent breaking main flows

64-68: LGTM: Proper Tinybird endpoint configuration.

The configuration correctly specifies the datasource, event schema, and wait parameter for reliable ingestion.

apps/web/lib/partners/create-partner-commission.ts (2)

18-52: Function signature update looks good.

The addition of optional workspaceId and user parameters maintains backward compatibility while enabling audit logging functionality. The parameter types are correctly defined.


191-222: Audit logging implementation is well-structured.

The conditional audit logging based on user and workspaceId availability is appropriate. The isClawback logic correctly identifies negative earnings, and the use of Promise.allSettled ensures both operations execute independently without blocking each other.

apps/web/lib/actions/partners/unban-partner.ts (2)

28-28: Good addition of includePartner parameter.

Adding includePartner: true is necessary to fetch partner metadata for the audit log, ensuring the audit entry has complete information about the partner being unbanned.


90-108: Audit logging implementation follows established pattern.

The audit logging implementation is consistent with other partner actions in the codebase. Using Promise.allSettled ensures both cache invalidation and audit logging are attempted independently.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/page-client.tsx (1)

1-15: Excellent refactor for better maintainability.

The modularization of the security settings page into separate SAML, SCIM, and AuditLog components greatly improves code organization and maintainability. This follows React best practices for component composition.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/scim.tsx (1)

13-167: Well-structured component with proper feature gating.

The component follows React best practices with proper state management, conditional rendering, and accessibility considerations. The enterprise plan gating for SCIM configuration is correctly implemented.

apps/web/lib/actions/partners/update-discount.ts (1)

123-150: Consistent audit logging implementation.

The audit logging implementation follows the established pattern throughout the codebase. The use of Promise.allSettled appropriately handles both cache invalidation and audit logging as independent operations.

apps/web/lib/api/programs/get-program-enrollment-or-throw.ts (1)

10-10: LGTM! Clean implementation following existing patterns.

The addition of the includePartner parameter follows the same pattern as includeRewards, maintaining consistency in the codebase. This change efficiently supports the audit logging requirements by allowing partner data to be fetched in a single query.

Also applies to: 15-15, 29-32

apps/web/lib/actions/partners/ban-partner.ts (1)

3-3: LGTM! Well-implemented audit logging with good practices.

The audit logging implementation demonstrates several good practices:

  • Optimizes database queries by using includePartner: true instead of separate partner fetch
  • Uses Promise.allSettled for concurrent operations to prevent blocking
  • Includes comprehensive metadata in audit logs (actor, targets, action type)
  • Maintains existing error handling and transaction logic

The change integrates seamlessly with the existing ban functionality while adding the required audit trail.

Also applies to: 22-22, 30-30, 84-84, 104-137

apps/web/app/(ee)/api/commissions/[commissionId]/route.ts (1)

2-2: LGTM! Well-integrated audit logging implementation.

The audit logging implementation is well-integrated and follows established patterns:

  • Properly adds session context to access user information for audit logs
  • Uses Promise.allSettled for concurrent operations to prevent blocking
  • Includes comprehensive audit metadata with actor and updated commission data
  • Maintains existing error handling and transaction logic

The changes seamlessly add audit trail functionality without disrupting the existing commission update flow.

Also applies to: 19-20, 155-179

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/saml.tsx (1)

128-143: LGTM - Proper enterprise plan gating implementation.

The button correctly implements plan-based feature gating with appropriate tooltip for non-enterprise users, following the pattern established in the codebase.

apps/web/lib/api/audit-logs/schemas.ts (2)

10-24: LGTM - Well-structured Tinybird schema.

The schema correctly uses snake_case naming convention for database storage and includes all necessary fields for audit log tracking.


184-184: No changes needed: Request is available in the browser and Next.js runtimes
The global Request constructor is provided in all target environments—browsers, Node.js 18+ (used by Next.js), and the Next.js Edge runtime. The z.instanceof(Request).nullish() check will work as expected.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/audit-logs.tsx (2)

17-19: Remove unnecessary workspaceId check.

Based on the retrieved learning, components that use workspace data are wrapped in WorkspaceAuth which ensures workspaceId is always available, making this guard clause unnecessary.

-  const exportAuditLogs = async () => {
-    if (!workspaceId) {
-      return;
-    }
-
+  const exportAuditLogs = async () => {

115-120: Handle undefined slug gracefully.

The upgrade button logic assumes slug might be undefined but doesn't handle the case where it could be an empty string or other falsy values consistently.

             onClick={() =>
               window.open(
-                slug ? `/${slug}/upgrade` : "https://dub.co/enterprise",
+                slug && slug.trim() ? `/${slug}/upgrade` : "https://dub.co/enterprise",
                 "_blank",
               )
             }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9169ffe and 4f6d9b8.

📒 Files selected for processing (2)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/audit-logs.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/page-client.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/page-client.tsx (1)
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
🧬 Code Graph Analysis (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/audit-logs.tsx (3)
apps/web/lib/plan-capabilities.ts (1)
  • getPlanCapabilities (4-15)
apps/web/ui/shared/simple-date-range-picker.tsx (1)
  • SimpleDateRangePicker (4-77)
packages/ui/src/tooltip.tsx (1)
  • TooltipContent (90-128)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (5)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/page-client.tsx (2)

3-5: LGTM: Clean refactoring with proper component separation.

The extraction of SAML, SCIM, and AuditLogs components into separate modules improves maintainability and follows good separation of concerns principles.


10-12: LGTM: Simple and clean component composition.

The component now serves as a clean container for the three security feature components.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/audit-logs.tsx (3)

72-77: LGTM: Proper date picker integration with plan gating.

The date picker is correctly disabled when the user doesn't have export permissions, maintaining a consistent UI experience.


83-96: LGTM: Excellent plan-based gating with informative tooltip.

The export button properly implements plan restrictions with a clear tooltip that guides users to the enterprise plan upgrade.


100-123: LGTM: Clear upgrade prompt for non-enterprise users.

The footer section provides a clear call-to-action for users who need to upgrade to access audit log export functionality.

@steven-tey
Copy link
Collaborator

@CodeRabbit final review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 4, 2025

Tip

For best results, initiate chat on the files or code changes.

@steven-tey This is an excellent implementation of a comprehensive audit logging system! Here's my final review:

🎯 Overall Assessment: Outstanding

This PR delivers a production-ready audit logging system with exceptional attention to detail and consistency.

Key Strengths

1. Robust Architecture

  • Tinybird Integration: Smart choice for analytics-focused audit data with built-in TTL (1 year retention)
  • Async Processing: Consistent use of waitUntil ensures audit logging doesn't block critical operations
  • Scalable Design: Separate datasource and pipes for efficient querying and storage

2. Comprehensive Coverage

  • 38+ Actions Instrumented: Every critical partner, commission, and payout operation now has audit trails
  • Rich Context: Captures actor details, timestamps, IP addresses, user agents, and detailed metadata
  • Consistent Patterns: Uniform implementation across all actions using recordAuditLog

3. Security & Access Control

  • Enterprise Gating: Audit log export properly restricted to enterprise plans
  • Permission Checks: Workspace authentication and proper authorization
  • Data Validation: Strong Zod schemas for input/output validation

4. Developer Experience

  • Type Safety: Comprehensive TypeScript definitions throughout
  • Error Handling: Graceful fallbacks when audit logging fails
  • Modular Design: Clean separation of concerns with dedicated audit modules

5. User Experience

  • Intuitive UI: Well-integrated audit log management in security settings
  • Export Functionality: CSV export with proper file handling and user feedback
  • Plan Awareness: Clear upgrade prompts for non-enterprise users

🔍 Technical Highlights

// Excellent pattern used throughout:
waitUntil(
  recordAuditLog({
    workspaceId: workspace.id,
    programId: program.id,
    action: "partner.approved",
    actor: { id: user.id, name: user.name },
    targets: [{ id: partner.id, type: "partner", metadata: partner }]
  })
);

📊 Impact

This implementation provides:

  • Complete Accountability: Full audit trail for all partner operations
  • Compliance Ready: Enterprise-grade logging for regulatory requirements
  • Operational Insights: Rich data for analytics and monitoring
  • Security Enhancement: Detailed activity tracking for security analysis

🚀 Ready for Production

The implementation demonstrates:

  • Consistent coding patterns
  • Proper error handling
  • Performance considerations (async logging)
  • User-friendly interface
  • Enterprise-grade features

Recommendation: This PR is ready to merge. Excellent work on delivering a comprehensive, well-architected audit logging system! 🎉

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac0f681 and 441231e.

📒 Files selected for processing (4)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/audit-logs.tsx (1 hunks)
  • apps/web/lib/api/audit-logs/get-audit-logs.ts (1 hunks)
  • apps/web/lib/api/audit-logs/record-audit-log.ts (1 hunks)
  • packages/tinybird/pipes/get_audit_logs.pipe (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/web/lib/api/audit-logs/record-audit-log.ts
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/settings/security/audit-logs.tsx
  • apps/web/lib/api/audit-logs/get-audit-logs.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (3)
packages/tinybird/pipes/get_audit_logs.pipe (3)

1-3: LGTM - Standard Tinybird pipe syntax.

The NODE endpoint declaration and SQL query structure follow Tinybird conventions correctly.


4-17: Comprehensive field selection looks good.

The SELECT clause appropriately captures all essential audit log fields including actor information, timestamps, targets, and metadata for complete audit trail visibility.


24-25: Security: Proper parameterization implemented.

Good use of Tinybird's String() function for parameter sanitization to prevent SQL injection in the workspace and program ID filters.

@steven-tey steven-tey merged commit ec9aac5 into main Jul 4, 2025
8 checks passed
@steven-tey steven-tey deleted the partner-audit-logs branch July 4, 2025 19:46
This was referenced Oct 2, 2025
@coderabbitai coderabbitai bot mentioned this pull request Nov 14, 2025
This was referenced Nov 24, 2025
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.

3 participants