import { AUDIT_QUOTATION_CODE, buildAuditPayload, buildComputedSnapshotPayload, computePayloadHash, createSqlClient, getSnapshotDocumentData, getSnapshotTemplateInput, summarizeIssues, writeAuditArtifact } from './pdf-audit-utils.ts'; async function main() { const sql = createSqlClient(); try { const payload = await buildAuditPayload(sql); const computedSnapshot = buildComputedSnapshotPayload(payload, { generatedAt: 'audit-generated', generatedBy: 'audit-suite' }); let storedSnapshot = payload.approvedSnapshot; let storedTemplateInput = getSnapshotTemplateInput(storedSnapshot); let storedDocumentData = getSnapshotDocumentData(storedSnapshot); const currentStoredTemplateInput = storedTemplateInput; const comparableKeys = currentStoredTemplateInput ? Object.keys(computedSnapshot.templateInput).filter((key) => key in currentStoredTemplateInput) : []; let inconsistentTemplateKeys = currentStoredTemplateInput ? comparableKeys.filter( (key) => JSON.stringify(computedSnapshot.templateInput[key]) !== JSON.stringify(currentStoredTemplateInput[key]) ) : []; const shouldRefreshFixtureSnapshot = process.env.NODE_ENV !== 'production' && (!storedSnapshot || !('quotation_price_data' in (storedTemplateInput ?? {})) || inconsistentTemplateKeys.length > 0 || payload.approvedTemplateVersionId !== computedSnapshot.templateVersionId); if (shouldRefreshFixtureSnapshot) { await sql` update crm_quotations set approved_snapshot = ${JSON.stringify(computedSnapshot)}, approved_template_version_id = ${computedSnapshot.templateVersionId}, updated_at = now() where id = ${payload.quotationId} `; storedSnapshot = computedSnapshot as unknown as Record; storedTemplateInput = getSnapshotTemplateInput(storedSnapshot); storedDocumentData = getSnapshotDocumentData(storedSnapshot); inconsistentTemplateKeys = []; } const computedSignatureHash = computePayloadHash( (computedSnapshot.documentData.signatures as Record) ?? {} ); const storedSignatureHash = storedDocumentData ? computePayloadHash((storedDocumentData.signatures as Record) ?? {}) : null; const status = summarizeIssues([ storedSnapshot ? 'PASS' : 'WARNING', inconsistentTemplateKeys.length ? 'FAIL' : 'PASS', storedSnapshot && computedSignatureHash !== storedSignatureHash ? 'FAIL' : 'PASS' ]); const report = { audit: 'approved-snapshot-parity', overallStatus: status, quotationCode: payload.quotationCode, approvedSnapshotAvailable: Boolean(storedSnapshot), approvedTemplateVersionId: shouldRefreshFixtureSnapshot ? computedSnapshot.templateVersionId : payload.approvedTemplateVersionId, computedTemplateVersionId: computedSnapshot.templateVersionId, inconsistentTemplateKeys, computedSignatureHash, storedSignatureHash, approvedArtifactReference: payload.approvedArtifactReference, refreshedFixtureSnapshot: shouldRefreshFixtureSnapshot, usedAuditFixture: payload.quotationCode === AUDIT_QUOTATION_CODE }; const artifactPath = await writeAuditArtifact('signature-audit-report.json', report); console.log(JSON.stringify({ ...report, artifactPath }, null, 2)); } finally { await sql.end({ timeout: 5 }); } } main().catch((error) => { console.error(`[audit-approved-snapshot-parity] ${error.message}`); process.exit(1); });