Skip to content

feat(web): Add pagination and time range filtering to audit endpoint#949

Merged
msukkari merged 4 commits intomainfrom
msukkari/audit-pagination-SOU-584
Feb 27, 2026
Merged

feat(web): Add pagination and time range filtering to audit endpoint#949
msukkari merged 4 commits intomainfrom
msukkari/audit-pagination-SOU-584

Conversation

@msukkari
Copy link
Contributor

@msukkari msukkari commented Feb 27, 2026

Summary

The audit GET endpoint now supports pagination and time range filtering in UTC. Query parameters include page, perPage (default 50, max 100), since, and until (ISO 8601 datetimes). The response includes X-Total-Count header and RFC 5988 Link header for pagination, matching the commits API pattern.

Fixes #SOU-584

Summary by CodeRabbit

  • New Features

    • Added pagination (page, perPage) to the audit endpoint.
    • Added UTC time-range filtering (since, until) to audit queries.
    • Responses include total-count header and pagination Link headers for navigation.
    • Standardized JSON response format and Content-Type header.
  • Bug Fixes / Improvements

    • Added request validation and clearer error responses for invalid query parameters.

The audit API now supports pagination with page and perPage query parameters (max 100 items), and time range filtering with since and until parameters in UTC. Returns X-Total-Count header and RFC 5988 Link header for pagination, matching the commits API pattern.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@github-actions

This comment has been minimized.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

Walkthrough

Adds request-aware validation, UTC time-range filtering, and pagination to the audit GET endpoint; returns paginated results with X-Total-Count and Link headers and propagates validation/service errors as structured responses.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Documented addition of pagination and UTC time range filtering for the audit GET endpoint.
Audit Route Handler
packages/web/src/app/api/(server)/ee/audit/route.ts
Converted GET handler to accept NextRequest, validate page, perPage, since, until via zod, compute skip/take, call service with dates, return JSON with X-Total-Count and Link headers, and surface validation/service errors.
Audit Service / Actions
packages/web/src/ee/features/audit/actions.ts
Added FetchAuditRecordsParams (skip, take, since?, until?), changed fetchAuditRecords to accept params, build dynamic date-filtered where clause, fetch records and total count in parallel, apply ordering and pagination, and return { auditRecords, totalCount } or structured ServiceError.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant RouteHandler as Audit GET Route
    participant Validator as Zod Validator
    participant Service as fetchAuditRecords
    participant Database as DB

    Client->>RouteHandler: GET /api/ee/audit?page=1&perPage=10&since=...&until=...
    RouteHandler->>Validator: parse & validate query params
    Validator-->>RouteHandler: validated params or error

    alt validation error
        RouteHandler-->>Client: 400 { ServiceError }
    else valid
        RouteHandler->>RouteHandler: compute skip=(page-1)*perPage
        RouteHandler->>Service: fetchAuditRecords({skip, take, since, until})
        Service->>Database: COUNT WHERE timestamp BETWEEN since and until?
        Service->>Database: SELECT ... ORDER BY timestamp DESC, id DESC LIMIT take OFFSET skip
        Database-->>Service: { totalCount, auditRecords }
        Service-->>RouteHandler: { auditRecords, totalCount }
        RouteHandler->>RouteHandler: set X-Total-Count & Link headers
        RouteHandler-->>Client: 200 { auditRecords } + headers
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: pagination and time range filtering were added to the audit endpoint, matching the primary objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch msukkari/audit-pagination-SOU-584

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.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/web/src/app/api/`(server)/ee/audit/route.ts:
- Around line 14-19: The query schema auditQueryParamsSchema validates since and
until independently so inverted ranges slip through; update
auditQueryParamsSchema to add a cross-field validation (e.g., use .superRefine
or .refine) that checks if both since and until are present and ensures new
Date(since) <= new Date(until), and in the route return a 400 when the schema
rejects the input; apply the same cross-field refinement to the other identical
schema instance handling the same params (the one around lines 45-53) so both
endpoints consistently reject inverted time ranges.

In `@packages/web/src/ee/features/audit/actions.ts`:
- Around line 52-54: The query's orderBy currently sorts only by timestamp which
is non-deterministic for pagination; update the orderBy object (the one
containing timestamp: 'desc') to include a unique tiebreaker field (e.g., id or
uuid) as a second sort key using the same direction as timestamp (e.g., {
timestamp: 'desc', id: 'desc' }) and ensure any cursor/seek logic (pagination
cursors or where/skip logic in the surrounding function handling the query) is
updated to include and compare that same tiebreaker to make page boundaries
deterministic.
- Around line 35-58: The handler fetchAuditRecords is using the global Prisma
client (prisma.audit / prisma.count) but must use the auth-scoped client
provided by withAuthV2; update the withAuthV2 callback signature to destructure
the scoped prisma (e.g. async ({ user, org, role, prisma }) => ...) and replace
all usages of the imported/global prisma inside fetchAuditRecords with that
scoped prisma (prisma.findMany/prisma.count on the audit model), making any
necessary type adjustments so the scoped client is used consistently for queries
and counts.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e0e737 and c40542d.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • packages/web/src/app/api/(server)/ee/audit/route.ts
  • packages/web/src/ee/features/audit/actions.ts

…agination

Reject requests where 'since' >= 'until' with a 400 error, and add 'id' as a
tiebreaker to the orderBy clause so paginated results are deterministic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/web/src/app/api/(server)/ee/audit/route.ts (1)

1-1: ⚠️ Potential issue | 🟡 Minor

Remove 'use server' directive from API route.

The 'use server' directive is for Server Actions, not API route handlers. API routes in the app/api/ directory are already server-side by default and don't need this directive.

Proposed fix
-'use server';
-
 import { fetchAuditRecords } from "@/ee/features/audit/actions";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/web/src/app/api/`(server)/ee/audit/route.ts at line 1, Remove the
`'use server'` directive from the top of the API route file (the literal "'use
server'" string in route.ts); API routes under app/api are server-side by
default and must not include Server Action directives—delete that line and
ensure the route handler functions remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/web/src/app/api/`(server)/ee/audit/route.ts:
- Line 1: Remove the `'use server'` directive from the top of the API route file
(the literal "'use server'" string in route.ts); API routes under app/api are
server-side by default and must not include Server Action directives—delete that
line and ensure the route handler functions remain unchanged.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c40542d and 8de3068.

📒 Files selected for processing (2)
  • packages/web/src/app/api/(server)/ee/audit/route.ts
  • packages/web/src/ee/features/audit/actions.ts

@msukkari msukkari merged commit e369199 into main Feb 27, 2026
9 checks passed
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