localgreenchain/pages/api/transparency/signatures.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

193 lines
5.5 KiB
TypeScript

/**
* Digital Signatures API
* GET /api/transparency/signatures - List signatures or verify one
* POST /api/transparency/signatures - Create a new signature
*
* Manage cryptographic signatures for verification.
*/
import type { NextApiRequest, NextApiResponse } from 'next';
import { getSignatureManager, SignatureType } from '../../../lib/transparency';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const signatureManager = getSignatureManager();
if (req.method === 'GET') {
try {
const { resourceType, resourceId, signatureId, action } = req.query;
// Verify a specific signature
if (signatureId && action === 'verify') {
const verification = signatureManager.verify(signatureId as string);
return res.status(200).json({
success: true,
data: verification
});
}
// Get signatures for a resource
if (resourceType && resourceId) {
const signatures = signatureManager.getSignaturesForResource(
resourceType as string,
resourceId as string
);
return res.status(200).json({
success: true,
data: {
signatures,
count: signatures.length
}
});
}
// Get stats
const stats = signatureManager.getStats();
return res.status(200).json({
success: true,
data: stats
});
} catch (error) {
console.error('[API] Signatures error:', error);
return res.status(500).json({
success: false,
error: 'Failed to process signatures request'
});
}
}
if (req.method === 'POST') {
try {
const { action } = req.body;
// Register a new identity
if (action === 'register_identity') {
const { name, type, publicKey, metadata } = req.body;
if (!name || !type || !publicKey) {
return res.status(400).json({
success: false,
error: 'Missing required fields: name, type, publicKey'
});
}
const identity = signatureManager.registerIdentity(name, type, publicKey, metadata);
return res.status(201).json({
success: true,
data: identity
});
}
// Generate a key pair
if (action === 'generate_keypair') {
const { algorithm = 'ECDSA' } = req.body;
const keyPair = signatureManager.generateKeyPair(algorithm);
return res.status(201).json({
success: true,
data: keyPair,
warning: 'Store your private key securely. It will not be stored on the server.'
});
}
// Create a signature
if (action === 'sign') {
const { type, resourceType, resourceId, data, privateKey, signerId, metadata } = req.body;
if (!type || !resourceType || !resourceId || !data || !privateKey || !signerId) {
return res.status(400).json({
success: false,
error: 'Missing required fields: type, resourceType, resourceId, data, privateKey, signerId'
});
}
const signature = signatureManager.sign(
type as SignatureType,
resourceType,
resourceId,
data,
privateKey,
signerId,
metadata
);
return res.status(201).json({
success: true,
data: {
id: signature.id,
type: signature.type,
resourceId: signature.resourceId,
timestamp: signature.timestamp,
// Don't return the signature itself for security
signaturePreview: signature.signature.substring(0, 20) + '...'
}
});
}
// Verify data directly
if (action === 'verify_data') {
const { data, signature, publicKey } = req.body;
if (!data || !signature || !publicKey) {
return res.status(400).json({
success: false,
error: 'Missing required fields: data, signature, publicKey'
});
}
const isValid = signatureManager.verifyData(data, signature, publicKey);
return res.status(200).json({
success: true,
data: { valid: isValid }
});
}
// Create transport handoff
if (action === 'transport_handoff') {
const { plantId, fromParty, toParty, location, privateKey } = req.body;
if (!plantId || !fromParty || !toParty || !location || !privateKey) {
return res.status(400).json({
success: false,
error: 'Missing required fields: plantId, fromParty, toParty, location, privateKey'
});
}
const signature = signatureManager.createTransportHandoff(
plantId,
fromParty,
toParty,
location,
privateKey
);
return res.status(201).json({
success: true,
data: {
signatureId: signature.id,
type: signature.type,
plantId,
fromParty,
toParty,
timestamp: signature.timestamp
}
});
}
return res.status(400).json({
success: false,
error: 'Invalid action. Supported: register_identity, generate_keypair, sign, verify_data, transport_handoff'
});
} catch (error) {
console.error('[API] Signature creation error:', error);
return res.status(500).json({
success: false,
error: 'Failed to create signature'
});
}
}
return res.status(405).json({ error: 'Method not allowed' });
}