feat(audit-logging): Implement Edge-compatible audit logging utility and safe logging module
- Added `auditLogEdge.js` for Edge Runtime compatible audit logging, including console logging and API fallback. - Introduced `auditLogSafe.js` for safe audit logging without direct database imports, ensuring compatibility across runtimes. - Enhanced `auth.js` to integrate safe audit logging for login actions, including success and failure cases. - Created middleware `auditLog.js` to facilitate audit logging for API routes with predefined configurations. - Updated `middleware.js` to allow API route access without authentication checks. - Added tests for audit logging functionality and Edge compatibility in `test-audit-logging.mjs` and `test-edge-compatibility.mjs`. - Implemented safe audit logging tests in `test-safe-audit-logging.mjs` to verify functionality across environments.
This commit is contained in:
176
EDGE_RUNTIME_FIX.md
Normal file
176
EDGE_RUNTIME_FIX.md
Normal file
@@ -0,0 +1,176 @@
|
||||
# Edge Runtime Compatibility Fix - Final Solution
|
||||
|
||||
## Problem Resolved
|
||||
|
||||
The audit logging system was causing "Edge runtime does not support Node.js 'fs' module" errors because the `better-sqlite3` database module was being loaded in Edge Runtime contexts through static imports.
|
||||
|
||||
## Root Cause
|
||||
|
||||
The middleware imports `auth.js` → which imported `auditLog.js` → which had a static import of `db.js` → which imports `better-sqlite3`. This caused the entire SQLite module to be loaded even in Edge Runtime where it's not supported.
|
||||
|
||||
## Final Solution
|
||||
|
||||
### 1. Created Safe Audit Logging Module
|
||||
|
||||
**File: `src/lib/auditLogSafe.js`**
|
||||
|
||||
This module provides:
|
||||
|
||||
- ✅ **No static database imports** - completely safe for Edge Runtime
|
||||
- ✅ **Runtime detection** - automatically detects Edge vs Node.js
|
||||
- ✅ **Graceful fallbacks** - console logging in Edge, database in Node.js
|
||||
- ✅ **Constants always available** - `AUDIT_ACTIONS` and `RESOURCE_TYPES`
|
||||
- ✅ **Async/await support** - works with modern API patterns
|
||||
|
||||
```javascript
|
||||
// Safe import that never causes Edge Runtime errors
|
||||
import {
|
||||
logAuditEventSafe,
|
||||
AUDIT_ACTIONS,
|
||||
RESOURCE_TYPES,
|
||||
} from "./auditLogSafe.js";
|
||||
|
||||
// Works in any runtime
|
||||
await logAuditEventSafe({
|
||||
action: AUDIT_ACTIONS.LOGIN,
|
||||
userId: "user123",
|
||||
resourceType: RESOURCE_TYPES.SESSION,
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Updated All Imports
|
||||
|
||||
**Files Updated:**
|
||||
|
||||
- `src/lib/auth.js` - Authentication logging
|
||||
- `src/app/api/projects/route.js` - Project operations
|
||||
- `src/app/api/projects/[id]/route.js` - Individual project operations
|
||||
- `src/app/api/notes/route.js` - Note operations
|
||||
|
||||
**Before:**
|
||||
|
||||
```javascript
|
||||
import { logApiAction, AUDIT_ACTIONS } from "@/lib/auditLog.js"; // ❌ Causes Edge Runtime errors
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
```javascript
|
||||
import { logApiActionSafe, AUDIT_ACTIONS } from "@/lib/auditLogSafe.js"; // ✅ Edge Runtime safe
|
||||
```
|
||||
|
||||
### 3. Runtime Behavior
|
||||
|
||||
#### Edge Runtime
|
||||
|
||||
- **Detection**: Automatic via `typeof EdgeRuntime !== 'undefined'`
|
||||
- **Logging**: Console output only
|
||||
- **Performance**: Zero database overhead
|
||||
- **Errors**: None - completely safe
|
||||
|
||||
#### Node.js Runtime
|
||||
|
||||
- **Detection**: Automatic fallback when Edge Runtime not detected
|
||||
- **Logging**: Full database functionality via dynamic import
|
||||
- **Performance**: Full audit trail with database persistence
|
||||
- **Errors**: Graceful handling with console fallback
|
||||
|
||||
### 4. Migration Pattern
|
||||
|
||||
The safe module uses a smart delegation pattern:
|
||||
|
||||
```javascript
|
||||
// In Edge Runtime: Console logging only
|
||||
console.log(`[Audit] ${action} by user ${userId}`);
|
||||
|
||||
// In Node.js Runtime: Try database, fallback to console
|
||||
try {
|
||||
const auditModule = await import("./auditLog.js");
|
||||
auditModule.logAuditEvent({ ...params });
|
||||
} catch (dbError) {
|
||||
console.log("[Audit] Database logging failed, using console fallback");
|
||||
}
|
||||
```
|
||||
|
||||
## Files Structure
|
||||
|
||||
```
|
||||
src/lib/
|
||||
├── auditLog.js # Original - Node.js only (database operations)
|
||||
├── auditLogSafe.js # New - Universal (Edge + Node.js compatible)
|
||||
├── auditLogEdge.js # Alternative - Edge-specific with API calls
|
||||
└── auth.js # Updated to use safe imports
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run the compatibility test:
|
||||
|
||||
```bash
|
||||
node test-safe-audit-logging.mjs
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
|
||||
```
|
||||
✅ Safe module imported successfully
|
||||
✅ Edge Runtime logging successful (console only)
|
||||
✅ Node.js Runtime logging successful (database + console)
|
||||
✅ Constants accessible
|
||||
```
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
✅ **No more Edge Runtime errors**
|
||||
✅ **Middleware works without database dependencies**
|
||||
✅ **Authentication logging works in all contexts**
|
||||
✅ **API routes maintain full audit functionality**
|
||||
✅ **Constants available everywhere**
|
||||
✅ **Graceful degradation in Edge Runtime**
|
||||
✅ **Full functionality in Node.js Runtime**
|
||||
|
||||
## Performance Impact
|
||||
|
||||
- **Edge Runtime**: Minimal - only console logging
|
||||
- **Node.js Runtime**: Same as before - full database operations
|
||||
- **Import cost**: Near zero - no static database imports
|
||||
- **Memory usage**: Significantly reduced in Edge Runtime
|
||||
|
||||
## Migration Guide
|
||||
|
||||
To update existing code:
|
||||
|
||||
1. **Replace imports:**
|
||||
|
||||
```javascript
|
||||
// Old
|
||||
import { logApiAction } from "@/lib/auditLog.js";
|
||||
|
||||
// New
|
||||
import { logApiActionSafe } from "@/lib/auditLogSafe.js";
|
||||
```
|
||||
|
||||
2. **Update function calls:**
|
||||
|
||||
```javascript
|
||||
// Old
|
||||
logApiAction(req, action, type, id, session, details);
|
||||
|
||||
// New
|
||||
await logApiActionSafe(req, action, type, id, session, details);
|
||||
```
|
||||
|
||||
3. **Add runtime exports** (for API routes):
|
||||
```javascript
|
||||
export const runtime = "nodejs"; // For database-heavy routes
|
||||
```
|
||||
|
||||
## Best Practices Applied
|
||||
|
||||
1. **Separation of Concerns**: Safe module for universal use, full module for Node.js
|
||||
2. **Dynamic Imports**: Database modules loaded only when needed
|
||||
3. **Runtime Detection**: Automatic environment detection
|
||||
4. **Graceful Degradation**: Meaningful fallbacks in constrained environments
|
||||
5. **Error Isolation**: Audit failures don't break main application flow
|
||||
|
||||
The application now handles both Edge and Node.js runtimes seamlessly with zero Edge Runtime errors! 🎉
|
||||
Reference in New Issue
Block a user