--- a/prd.json +++ b/prd.json @@ -1,70 +1,147 @@ { "project": "AdminPanel", - "branchName": "ralph/user-invite-flow", - "description": "User Invite Flow - Allow admins to invite new users via email", + "branchName": "ralph/admin-audit-log-export", + "description": "Admin Audit Log Export - Enable compliance team to search, filter, and export audit logs from the admin panel for SOC 2 Type II certification", "userStories": [ { "id": "US-001", - "title": "Add invitations table to database", - "description": "As a developer, I need to store pending invitations in the database.", + "title": "Ensure audit_events table schema has required columns", + "description": "As a developer, I need the audit_events table to have the right shape for querying and export.", "acceptanceCriteria": [ - "Create invitations table with columns: id, email, role, invited_by, token, expires_at, accepted_at, created_at", - "Add unique index on token column", - "Add index on email column", + "audit_events table has column actor_email (string, indexed)", + "audit_events table has column action_type (enum: create, update, delete, login, export)", + "audit_events table has column resource_type (string)", + "audit_events table has column resource_id (string)", + "audit_events table has column metadata (jsonb, nullable)", + "audit_events table has column created_at (timestamp with timezone, indexed, default now)", "Generate and run migration successfully", "Typecheck passes" ], "priority": 1, - "passes": true, - "notes": "Migration 0047 created and applied." + "passes": false, + "notes": "" }, { "id": "US-002", - "title": "Create invitation server actions", - "description": "As a developer, I need server actions to create and validate invitations.", + "title": "Build audit log query service with filtering and pagination", + "description": "As a developer, I need a server-side service to query audit events with filters, pagination, and sorting.", "acceptanceCriteria": [ - "createInvitation action accepts email and role, generates secure token, sets 72h expiry", - "validateInvitation action looks up token and checks expiry", - "acceptInvitation action marks invitation as accepted and creates user account", - "Duplicate email within 24h returns error instead of creating new invitation", + "Service supports filtering by date range, actor_email, action_type, and resource_type", + "Cursor-based pagination returns 50 results per page", + "Results sorted by created_at descending", + "getAuditEventCount function returns total matching events for a given filter set", + "Date range filter rejects ranges exceeding 90 days", + "All filter values are sanitized against injection", "Typecheck passes", "Tests pass" ], "priority": 2, - "passes": true, - "notes": "All three actions implemented and tested." + "passes": false, + "notes": "" }, { "id": "US-003", - "title": "Build invite user form in admin panel", - "description": "As an admin, I want to invite a new user by entering their email and selecting a role.", + "title": "Add role-based access control for audit log page", + "description": "As a developer, I need to restrict audit log access to admin and auditor roles only.", "acceptanceCriteria": [ - "Form with email input and role dropdown (admin, editor, viewer)", - "Submit calls createInvitation server action", - "Success toast shows 'Invitation sent to {email}'", - "Validation error shown for invalid email format", + "Only users with admin or auditor role can access the audit log page", + "Unauthorized access returns 403 response", + "Unauthorized access attempts are logged as audit events", "Typecheck passes", - "Verify in browser using dev-browser skill" + "Tests pass" ], "priority": 3, - "passes": true, - "notes": "Form working, toast notifications confirmed." + "passes": false, + "notes": "" }, { "id": "US-004", - "title": "Add pending invitations list to admin users page", - "description": "As an admin, I want to see all pending invitations alongside existing users.", + "title": "Build audit log viewer table with pagination", + "description": "As an admin, I want to see audit events in a table with pagination so I can review activity.", "acceptanceCriteria": [ - "Pending invitations section shows below user list", - "Each row shows email, role, invited by, sent date, and expiry status", - "Expired invitations shown with 'Expired' badge", - "Resend button available for expired invitations", + "Table displays columns: timestamp, actor email, action type, resource type, resource ID", + "All timestamps displayed in the user's local timezone", + "Previous/next pagination controls with page indicator", + "Loading skeleton shown while data is fetching", + "Empty state displayed when no events exist", + "Table is navigable via keyboard with proper ARIA labels", + "Page loads initial data in under 2 seconds", "Typecheck passes", "Verify in browser using dev-browser skill" ], "priority": 4, "passes": false, "notes": "" + }, + { + "id": "US-005", + "title": "Add filter bar to audit log viewer", + "description": "As an admin, I want to filter audit events by action type, resource type, actor email, and date range.", + "acceptanceCriteria": [ + "Filter bar has dropdown for action_type (create, update, delete, login, export)", + "Filter bar has dropdown for resource_type", + "Filter bar has text input for actor_email", + "Filter bar has date range picker", + "Selecting filters updates the table results", + "Empty state shown when no events match current filters", + "Typecheck passes", + "Verify in browser using dev-browser skill" + ], + "priority": 5, + "passes": false, + "notes": "" + }, + { + "id": "US-006", + "title": "Add row expansion to show metadata details", + "description": "As an admin, I want to click a row to see the full metadata JSON for that audit event.", + "acceptanceCriteria": [ + "Clicking a table row expands it to show metadata JSON in a formatted view", + "Clicking an expanded row collapses it", + "Metadata displays IP address, user agent, and changed fields when present", + "Null metadata shows appropriate empty message", + "Typecheck passes", + "Verify in browser using dev-browser skill" + ], + "priority": 6, + "passes": false, + "notes": "" + }, + { + "id": "US-007", + "title": "Build server-side CSV export endpoint", + "description": "As a developer, I need a server endpoint that generates and streams audit log CSV files.", + "acceptanceCriteria": [ + "Endpoint generates CSV with columns: Timestamp, Actor, Action, Resource Type, Resource ID, Metadata (JSON stringified)", + "Export respects the same filters as the viewer (date range, actor, action type, resource type)", + "CSV streamed as download response with proper Content-Disposition header", + "Maximum export capped at 10,000 rows", + "Endpoint rate-limited to 5 exports per admin per hour", + "Export action is itself logged as an audit event with action_type export", + "Export of 10k rows completes in under 10 seconds", + "Typecheck passes", + "Tests pass" + ], + "priority": 7, + "passes": false, + "notes": "" + }, + { + "id": "US-008", + "title": "Add CSV export button and notifications to audit log viewer", + "description": "As an admin, I want to export the currently filtered audit logs as a CSV file from the UI.", + "acceptanceCriteria": [ + "Export CSV button in toolbar, disabled when there are no results", + "Clicking export triggers server-side CSV generation and download", + "Warning shown if filtered set exceeds 10,000 rows", + "Toast notification shown when export starts", + "Toast notification shown when download is ready", + "Typecheck passes", + "Verify in browser using dev-browser skill" + ], + "priority": 8, + "passes": false, + "notes": "" } ] }