localgreenchain/pages/api/transparency/audit.ts
Claude 0fcc2763fe
Add comprehensive transparency system for LocalGreenChain
This commit introduces a complete transparency infrastructure including:

Core Transparency Modules:
- AuditLog: Immutable, cryptographically-linked audit trail for all actions
- EventStream: Real-time SSE streaming and webhook support
- TransparencyDashboard: Aggregated metrics and system health monitoring
- DigitalSignatures: Cryptographic verification for handoffs and certificates

API Endpoints:
- /api/transparency/dashboard - Full platform metrics
- /api/transparency/audit - Query and log audit entries
- /api/transparency/events - SSE stream and event history
- /api/transparency/webhooks - Webhook management
- /api/transparency/signatures - Digital signature operations
- /api/transparency/certificate/[plantId] - Plant authenticity certificates
- /api/transparency/export - Multi-format data export
- /api/transparency/report - Compliance reporting
- /api/transparency/health - System health checks

Features:
- Immutable audit logging with chain integrity verification
- Real-time event streaming via Server-Sent Events
- Webhook support with HMAC signature verification
- Digital signatures for transport handoffs and ownership transfers
- Certificate of Authenticity generation for plants
- Multi-format data export (JSON, CSV, summary)
- Public transparency portal at /transparency
- System health monitoring for all components

Documentation:
- Comprehensive TRANSPARENCY.md guide with API examples
2025-11-23 03:29:56 +00:00

128 lines
3.6 KiB
TypeScript

/**
* Audit Log API
* GET /api/transparency/audit - Query audit entries
* POST /api/transparency/audit - Log a custom audit entry
*
* Provides access to the immutable audit trail.
*/
import type { NextApiRequest, NextApiResponse } from 'next';
import { getAuditLog, AuditQuery, AuditAction, AuditCategory, AuditSeverity } from '../../../lib/transparency';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const auditLog = getAuditLog();
if (req.method === 'GET') {
try {
const {
startDate,
endDate,
actions,
categories,
severities,
actorId,
actorType,
resourceType,
resourceId,
correlationId,
search,
limit = '100',
offset = '0',
format = 'json'
} = req.query;
const query: AuditQuery = {
startDate: startDate as string,
endDate: endDate as string,
actions: actions ? (actions as string).split(',') as AuditAction[] : undefined,
categories: categories ? (categories as string).split(',') as AuditCategory[] : undefined,
severities: severities ? (severities as string).split(',') as AuditSeverity[] : undefined,
actorId: actorId as string,
actorType: actorType as any,
resourceType: resourceType as string,
resourceId: resourceId as string,
correlationId: correlationId as string,
searchTerm: search as string,
limit: parseInt(limit as string, 10),
offset: parseInt(offset as string, 10)
};
// Handle different formats
if (format === 'csv') {
const csv = auditLog.export('csv', query);
res.setHeader('Content-Type', 'text/csv');
res.setHeader('Content-Disposition', 'attachment; filename=audit-log.csv');
return res.status(200).send(csv);
}
if (format === 'summary') {
const summary = auditLog.export('summary', query);
res.setHeader('Content-Type', 'text/plain');
return res.status(200).send(summary);
}
const result = auditLog.query(query);
return res.status(200).json({
success: true,
data: {
entries: result.entries,
total: result.total,
limit: query.limit,
offset: query.offset
}
});
} catch (error) {
console.error('[API] Audit query error:', error);
return res.status(500).json({
success: false,
error: 'Failed to query audit log'
});
}
}
if (req.method === 'POST') {
try {
const { action, category, description, severity, actor, resource, metadata } = req.body;
if (!action || !category || !description) {
return res.status(400).json({
success: false,
error: 'Missing required fields: action, category, description'
});
}
const entry = auditLog.log(
action as AuditAction,
category as AuditCategory,
description,
{
severity: severity as AuditSeverity,
actor: {
...actor,
ip: req.headers['x-forwarded-for'] as string || req.socket.remoteAddress,
userAgent: req.headers['user-agent']
},
resource,
metadata
}
);
return res.status(201).json({
success: true,
data: entry
});
} catch (error) {
console.error('[API] Audit log error:', error);
return res.status(500).json({
success: false,
error: 'Failed to create audit entry'
});
}
}
return res.status(405).json({ error: 'Method not allowed' });
}