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
193 lines
5.5 KiB
TypeScript
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' });
|
|
}
|