- Add Legal Office of the Master seal (SVG design with Maltese Cross, scales of justice, legal scroll) - Create legal-office-manifest-template.json for Legal Office credentials - Update SEAL_MAPPING.md and DESIGN_GUIDE.md with Legal Office seal documentation - Complete Azure CDN infrastructure deployment: - Resource group, storage account, and container created - 17 PNG seal files uploaded to Azure Blob Storage - All manifest templates updated with Azure URLs - Configuration files generated (azure-cdn-config.env) - Add comprehensive Azure CDN setup scripts and documentation - Fix manifest URL generation to prevent double slashes - Verify all seals accessible via HTTPS
97 lines
4.0 KiB
JavaScript
97 lines
4.0 KiB
JavaScript
/**
|
|
* Credential lifecycle management operations
|
|
*/
|
|
import { query } from './client';
|
|
// Note: CredentialTemplate operations are now in credential-templates.ts
|
|
// This file focuses on lifecycle operations (status history, revocation, audit)
|
|
// Credential Status History operations
|
|
export async function addCredentialStatusHistory(history) {
|
|
const result = await query(`INSERT INTO credential_status_history (credential_id, status, reason, changed_by, metadata)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
RETURNING *`, [
|
|
history.credential_id,
|
|
history.status,
|
|
history.reason || null,
|
|
history.changed_by || null,
|
|
history.metadata ? JSON.stringify(history.metadata) : null,
|
|
]);
|
|
return result.rows[0];
|
|
}
|
|
export async function getCredentialStatusHistory(credentialId) {
|
|
const result = await query(`SELECT * FROM credential_status_history
|
|
WHERE credential_id = $1
|
|
ORDER BY changed_at DESC`, [credentialId]);
|
|
return result.rows;
|
|
}
|
|
// Credential Revocation operations
|
|
export async function revokeCredential(revocation) {
|
|
// First, update the credential as revoked
|
|
await query(`UPDATE verifiable_credentials
|
|
SET revoked = TRUE, updated_at = NOW()
|
|
WHERE credential_id = $1`, [revocation.credential_id]);
|
|
// Get the next revocation list index
|
|
const indexResult = await query(`SELECT MAX(revocation_list_index) as max_index
|
|
FROM credential_revocation_registry
|
|
WHERE issuer_did = $1`, [revocation.issuer_did]);
|
|
const nextIndex = (indexResult.rows[0]?.max_index ?? -1) + 1;
|
|
// Add to revocation registry
|
|
const result = await query(`INSERT INTO credential_revocation_registry
|
|
(credential_id, issuer_did, revocation_reason, revoked_by, revocation_list_index)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
RETURNING *`, [
|
|
revocation.credential_id,
|
|
revocation.issuer_did,
|
|
revocation.revocation_reason || null,
|
|
revocation.revoked_by || null,
|
|
nextIndex,
|
|
]);
|
|
return result.rows[0];
|
|
}
|
|
export async function isCredentialRevoked(credentialId) {
|
|
const result = await query(`SELECT revoked FROM verifiable_credentials WHERE credential_id = $1`, [credentialId]);
|
|
return result.rows[0]?.revoked ?? false;
|
|
}
|
|
export async function getRevocationRegistry(issuerDid, limit = 100, offset = 0) {
|
|
const result = await query(`SELECT * FROM credential_revocation_registry
|
|
WHERE issuer_did = $1
|
|
ORDER BY revocation_list_index DESC
|
|
LIMIT $2 OFFSET $3`, [issuerDid, limit, offset]);
|
|
return result.rows;
|
|
}
|
|
// Credential Audit Log operations
|
|
export async function logCredentialAction(audit) {
|
|
const result = await query(`INSERT INTO credential_issuance_audit
|
|
(credential_id, issuer_did, subject_did, credential_type, action, performed_by, metadata, ip_address, user_agent)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
RETURNING *`, [
|
|
audit.credential_id,
|
|
audit.issuer_did,
|
|
audit.subject_did,
|
|
audit.credential_type,
|
|
audit.action,
|
|
audit.performed_by || null,
|
|
audit.metadata ? JSON.stringify(audit.metadata) : null,
|
|
audit.ip_address || null,
|
|
audit.user_agent || null,
|
|
]);
|
|
return result.rows[0];
|
|
}
|
|
export async function getCredentialAuditLog(credentialId, limit = 100) {
|
|
const result = await query(`SELECT * FROM credential_issuance_audit
|
|
WHERE credential_id = $1
|
|
ORDER BY performed_at DESC
|
|
LIMIT $2`, [credentialId, limit]);
|
|
return result.rows;
|
|
}
|
|
export async function getExpiringCredentials(daysAhead, limit = 100) {
|
|
const result = await query(`SELECT credential_id, expiration_date, subject_did, issuer_did, credential_type, credential_subject
|
|
FROM verifiable_credentials
|
|
WHERE expiration_date IS NOT NULL
|
|
AND expiration_date > NOW()
|
|
AND expiration_date < NOW() + INTERVAL '${daysAhead} days'
|
|
AND revoked = FALSE
|
|
ORDER BY expiration_date ASC
|
|
LIMIT $1`, [limit]);
|
|
return result.rows;
|
|
}
|
|
//# sourceMappingURL=credential-lifecycle.js.map
|