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
110 lines
3.1 KiB
TypeScript
110 lines
3.1 KiB
TypeScript
/**
|
|
* Certificate of Authenticity API
|
|
* GET /api/transparency/certificate/[plantId] - Generate certificate for a plant
|
|
*
|
|
* Provides verifiable certificates of plant authenticity and provenance.
|
|
*/
|
|
|
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
import { getSignatureManager } from '../../../../lib/transparency';
|
|
|
|
export default async function handler(
|
|
req: NextApiRequest,
|
|
res: NextApiResponse
|
|
) {
|
|
if (req.method !== 'GET') {
|
|
return res.status(405).json({ error: 'Method not allowed' });
|
|
}
|
|
|
|
const { plantId, format = 'json' } = req.query;
|
|
|
|
if (!plantId || typeof plantId !== 'string') {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Missing plant ID'
|
|
});
|
|
}
|
|
|
|
try {
|
|
const signatureManager = getSignatureManager();
|
|
const certificate = await signatureManager.generateCertificate(plantId);
|
|
|
|
if (!certificate) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'Plant not found or certificate generation failed'
|
|
});
|
|
}
|
|
|
|
// Verify the certificate
|
|
const verification = signatureManager.verifyCertificate(certificate);
|
|
|
|
if (format === 'text') {
|
|
res.setHeader('Content-Type', 'text/plain');
|
|
return res.status(200).send(`
|
|
CERTIFICATE OF AUTHENTICITY
|
|
===========================
|
|
Certificate ID: ${certificate.id}
|
|
Generated: ${certificate.generatedAt}
|
|
|
|
PLANT INFORMATION
|
|
-----------------
|
|
Plant ID: ${certificate.plantId}
|
|
Name: ${certificate.plantName}
|
|
Variety: ${certificate.variety}
|
|
|
|
ORIGIN
|
|
------
|
|
Grower: ${certificate.origin.grower}
|
|
Location: ${certificate.origin.location}
|
|
Registered: ${certificate.origin.registeredAt}
|
|
|
|
LINEAGE
|
|
-------
|
|
Generation: ${certificate.lineage.generation}
|
|
Parent ID: ${certificate.lineage.parentId || 'None (Original)'}
|
|
Children: ${certificate.lineage.childCount}
|
|
|
|
SIGNATURES (${certificate.signatures.length})
|
|
--------------------------------------------
|
|
${certificate.signatures.map(s =>
|
|
`[${s.verified ? 'VERIFIED' : 'UNVERIFIED'}] ${s.type} by ${s.signer} at ${s.timestamp}`
|
|
).join('\n') || 'No signatures recorded'}
|
|
|
|
TRANSPORT HISTORY (${certificate.transportHistory.length})
|
|
---------------------------------------------------------
|
|
${certificate.transportHistory.map(t =>
|
|
`${t.date}: ${t.from} -> ${t.to} [${t.verified ? 'Verified' : 'Unverified'}]`
|
|
).join('\n') || 'No transport history recorded'}
|
|
|
|
CERTIFICATIONS
|
|
--------------
|
|
${certificate.certifications.join('\n') || 'No certifications'}
|
|
|
|
VERIFICATION STATUS
|
|
-------------------
|
|
Certificate Valid: ${verification.valid ? 'YES' : 'NO'}
|
|
${verification.errors.length > 0 ? `Errors:\n${verification.errors.map(e => ` - ${e}`).join('\n')}` : ''}
|
|
|
|
Certificate Hash: ${certificate.hash}
|
|
|
|
This certificate was generated by LocalGreenChain transparency system.
|
|
Verify at: /api/transparency/certificate/${certificate.plantId}
|
|
`.trim());
|
|
}
|
|
|
|
return res.status(200).json({
|
|
success: true,
|
|
data: {
|
|
certificate,
|
|
verification
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('[API] Certificate error:', error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to generate certificate'
|
|
});
|
|
}
|
|
}
|