@striae-org/striae 5.4.2 → 5.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/app/components/actions/case-export/download-handlers.ts +1 -1
  2. package/app/components/actions/case-export/metadata-helpers.ts +2 -4
  3. package/app/components/actions/case-import/zip-processing.ts +3 -3
  4. package/app/components/mobile-warning/mobile-warning.module.css +80 -0
  5. package/app/components/mobile-warning/mobile-warning.tsx +108 -0
  6. package/app/components/navbar/case-import/utils/file-validation.ts +1 -1
  7. package/app/config-example/config.json +2 -2
  8. package/app/root.tsx +2 -0
  9. package/app/services/audit/audit-file-type.ts +0 -1
  10. package/app/services/audit/audit.service.ts +1 -1
  11. package/app/services/audit/builders/audit-event-builders-workflow.ts +2 -6
  12. package/app/services/audit/index.ts +0 -1
  13. package/app/types/audit.ts +1 -1
  14. package/app/utils/data/permissions.ts +17 -15
  15. package/app/utils/forensics/audit-export-signature.ts +4 -4
  16. package/app/utils/forensics/export-verification.ts +3 -11
  17. package/package.json +2 -2
  18. package/workers/audit-worker/package.json +1 -1
  19. package/workers/audit-worker/src/audit-worker.example.ts +1 -1
  20. package/workers/audit-worker/src/handlers/audit-routes.ts +1 -30
  21. package/workers/audit-worker/wrangler.jsonc.example +1 -1
  22. package/workers/data-worker/package.json +17 -17
  23. package/workers/data-worker/src/encryption-utils.ts +1 -1
  24. package/workers/data-worker/src/signing-payload-utils.ts +4 -4
  25. package/workers/data-worker/wrangler.jsonc.example +1 -1
  26. package/workers/image-worker/package.json +1 -1
  27. package/workers/image-worker/wrangler.jsonc.example +1 -1
  28. package/workers/pdf-worker/package.json +1 -1
  29. package/workers/pdf-worker/wrangler.jsonc.example +1 -1
  30. package/workers/user-worker/package.json +1 -1
  31. package/workers/user-worker/wrangler.jsonc.example +1 -1
  32. package/wrangler.toml.example +1 -1
  33. package/app/components/audit/viewer/use-audit-viewer-export.ts +0 -176
  34. package/app/services/audit/audit-export-csv.ts +0 -130
  35. package/app/services/audit/audit-export-report.ts +0 -205
  36. package/app/services/audit/audit-export.service.ts +0 -333
@@ -1,333 +0,0 @@
1
- import { type ValidationAuditEntry, type AuditTrail } from '~/types';
2
- import { calculateSHA256Secure, type AuditExportType } from '~/utils/forensics';
3
- import { AUDIT_CSV_ENTRY_HEADERS, entryToCSVRow } from './audit-export-csv';
4
- import { buildAuditReportContent } from './audit-export-report';
5
- import { type AuditExportContext, signAuditExport } from './audit-export-signing';
6
-
7
- /**
8
- * Audit Export Service
9
- * Handles exporting audit trails to various formats for compliance and forensic analysis
10
- */
11
- class AuditExportService {
12
- private static instance: AuditExportService;
13
-
14
- private constructor() {}
15
-
16
- public static getInstance(): AuditExportService {
17
- if (!AuditExportService.instance) {
18
- AuditExportService.instance = new AuditExportService();
19
- }
20
- return AuditExportService.instance;
21
- }
22
-
23
- /**
24
- * Export audit entries to CSV format
25
- */
26
- public async exportToCSV(
27
- entries: ValidationAuditEntry[],
28
- filename: string,
29
- context: AuditExportContext
30
- ): Promise<void> {
31
- const csvData = [
32
- AUDIT_CSV_ENTRY_HEADERS.join(','),
33
- ...entries.map(entry => entryToCSVRow(entry))
34
- ].join('\n');
35
-
36
- const generatedAt = new Date().toISOString();
37
- const hash = await calculateSHA256Secure(csvData);
38
- const signaturePayload = await signAuditExport(
39
- {
40
- exportFormat: 'csv',
41
- exportType: 'entries',
42
- generatedAt,
43
- totalEntries: entries.length,
44
- hash: hash.toUpperCase()
45
- },
46
- context
47
- );
48
-
49
- // Add hash metadata header
50
- const csvContent = [
51
- `# Striae Audit Export - Generated: ${generatedAt}`,
52
- `# Total Entries: ${entries.length}`,
53
- `# SHA-256 Hash: ${hash.toUpperCase()}`,
54
- `# Audit Signature Metadata: ${JSON.stringify(signaturePayload.signatureMetadata)}`,
55
- `# Audit Signature: ${JSON.stringify(signaturePayload.signature)}`,
56
- `# Verification: Recalculate SHA-256 of data rows only (excluding these comment lines)`,
57
- '',
58
- csvData
59
- ].join('\n');
60
-
61
- this.downloadFile(csvContent, filename, 'text/csv');
62
- }
63
-
64
- /**
65
- * Export audit trail to detailed CSV with summary
66
- */
67
- public async exportAuditTrailToCSV(
68
- auditTrail: AuditTrail,
69
- filename: string,
70
- context: AuditExportContext
71
- ): Promise<void> {
72
- const summaryHeaders = [
73
- 'Case Number',
74
- 'Workflow ID',
75
- 'Total Events',
76
- 'Successful Events',
77
- 'Failed Events',
78
- 'Warning Events',
79
- 'Compliance Status',
80
- 'Security Incidents',
81
- 'Start Time',
82
- 'End Time',
83
- 'Participating Users'
84
- ];
85
-
86
- const summaryRow = [
87
- auditTrail.caseNumber,
88
- auditTrail.workflowId,
89
- auditTrail.summary.totalEvents,
90
- auditTrail.summary.successfulEvents,
91
- auditTrail.summary.failedEvents,
92
- auditTrail.summary.warningEvents,
93
- auditTrail.summary.complianceStatus.toUpperCase(),
94
- auditTrail.summary.securityIncidents,
95
- auditTrail.summary.startTimestamp,
96
- auditTrail.summary.endTimestamp,
97
- auditTrail.summary.participatingUsers.join('; ')
98
- ].join(',');
99
-
100
- const csvData = [
101
- summaryHeaders.join(','),
102
- summaryRow,
103
- '',
104
- AUDIT_CSV_ENTRY_HEADERS.join(','),
105
- ...auditTrail.entries.map(entry => entryToCSVRow(entry))
106
- ].join('\n');
107
-
108
- const generatedAt = new Date().toISOString();
109
- const hash = await calculateSHA256Secure(csvData);
110
- const signaturePayload = await signAuditExport(
111
- {
112
- exportFormat: 'csv',
113
- exportType: 'trail',
114
- generatedAt,
115
- totalEntries: auditTrail.summary.totalEvents,
116
- hash: hash.toUpperCase()
117
- },
118
- context
119
- );
120
-
121
- const csvContent = [
122
- '# Striae Audit Trail Export - Generated: ' + generatedAt,
123
- `# Case: ${auditTrail.caseNumber} | Workflow: ${auditTrail.workflowId}`,
124
- `# Total Events: ${auditTrail.summary.totalEvents}`,
125
- `# SHA-256 Hash: ${hash.toUpperCase()}`,
126
- `# Audit Signature Metadata: ${JSON.stringify(signaturePayload.signatureMetadata)}`,
127
- `# Audit Signature: ${JSON.stringify(signaturePayload.signature)}`,
128
- '# Verification: Recalculate SHA-256 of data rows only (excluding these comment lines)',
129
- '',
130
- '# AUDIT TRAIL SUMMARY',
131
- csvData
132
- ].join('\n');
133
-
134
- this.downloadFile(csvContent, filename, 'text/csv');
135
- }
136
-
137
- /**
138
- * Generate filename with timestamp
139
- */
140
- public generateFilename(type: 'case' | 'user', identifier: string, format: 'csv' | 'json'): string {
141
- const timestamp = new Date().toISOString().slice(0, 19).replace(/[:.]/g, '-');
142
- const sanitizedId = identifier.replace(/[^a-zA-Z0-9-_]/g, '_');
143
- return `striae-audit-${type}-${sanitizedId}-${timestamp}.${format}`;
144
- }
145
-
146
- /**
147
- * Download file helper
148
- */
149
- private downloadFile(content: string, filename: string, mimeType: string): void {
150
- const blob = new Blob([content], { type: mimeType });
151
- const url = URL.createObjectURL(blob);
152
-
153
- const link = document.createElement('a');
154
- link.href = url;
155
- link.download = filename;
156
- link.style.display = 'none';
157
-
158
- document.body.appendChild(link);
159
- link.click();
160
- document.body.removeChild(link);
161
-
162
- // Clean up the URL object
163
- setTimeout(() => URL.revokeObjectURL(url), 100);
164
- }
165
-
166
- /**
167
- * Export audit entries to JSON format (for technical analysis)
168
- */
169
- public async exportToJSON(
170
- entries: ValidationAuditEntry[],
171
- filename: string,
172
- context: AuditExportContext
173
- ): Promise<void> {
174
- const generatedAt = new Date().toISOString();
175
-
176
- const exportData = {
177
- metadata: {
178
- exportTimestamp: generatedAt,
179
- exportVersion: '1.0',
180
- totalEntries: entries.length,
181
- application: 'Striae',
182
- exportType: 'entries' as AuditExportType,
183
- scopeType: context.scopeType,
184
- scopeIdentifier: context.scopeIdentifier
185
- },
186
- auditEntries: entries
187
- };
188
-
189
- const jsonContent = JSON.stringify(exportData, null, 2);
190
-
191
- // Calculate hash for integrity verification
192
- const hash = await calculateSHA256Secure(jsonContent);
193
- const signaturePayload = await signAuditExport(
194
- {
195
- exportFormat: 'json',
196
- exportType: exportData.metadata.exportType,
197
- generatedAt,
198
- totalEntries: entries.length,
199
- hash: hash.toUpperCase()
200
- },
201
- context
202
- );
203
-
204
- // Create final export with hash included
205
- const finalExportData = {
206
- metadata: {
207
- ...exportData.metadata,
208
- hash: hash.toUpperCase(),
209
- integrityNote: 'Verify hash and signature before trusting this export',
210
- signatureVersion: signaturePayload.signatureMetadata.signatureVersion,
211
- signature: signaturePayload.signature
212
- },
213
- auditEntries: entries
214
- };
215
-
216
- const finalJsonContent = JSON.stringify(finalExportData, null, 2);
217
- this.downloadFile(finalJsonContent, filename.replace('.csv', '.json'), 'application/json');
218
- }
219
-
220
- /**
221
- * Export full audit trail to JSON
222
- */
223
- public async exportAuditTrailToJSON(
224
- auditTrail: AuditTrail,
225
- filename: string,
226
- context: AuditExportContext
227
- ): Promise<void> {
228
- const generatedAt = new Date().toISOString();
229
-
230
- const exportData = {
231
- metadata: {
232
- exportTimestamp: generatedAt,
233
- exportVersion: '1.0',
234
- totalEntries: auditTrail.summary.totalEvents,
235
- application: 'Striae',
236
- exportType: 'trail' as AuditExportType,
237
- scopeType: context.scopeType,
238
- scopeIdentifier: context.scopeIdentifier
239
- },
240
- auditTrail
241
- };
242
-
243
- const jsonContent = JSON.stringify(exportData, null, 2);
244
-
245
- // Calculate hash for integrity verification
246
- const hash = await calculateSHA256Secure(jsonContent);
247
- const signaturePayload = await signAuditExport(
248
- {
249
- exportFormat: 'json',
250
- exportType: exportData.metadata.exportType,
251
- generatedAt,
252
- totalEntries: auditTrail.summary.totalEvents,
253
- hash: hash.toUpperCase()
254
- },
255
- context
256
- );
257
-
258
- // Create final export with hash included
259
- const finalExportData = {
260
- metadata: {
261
- ...exportData.metadata,
262
- hash: hash.toUpperCase(),
263
- integrityNote: 'Verify hash and signature before trusting this export',
264
- signatureVersion: signaturePayload.signatureMetadata.signatureVersion,
265
- signature: signaturePayload.signature
266
- },
267
- auditTrail
268
- };
269
-
270
- const finalJsonContent = JSON.stringify(finalExportData, null, 2);
271
- this.downloadFile(finalJsonContent, filename.replace('.csv', '.json'), 'application/json');
272
- }
273
-
274
- /**
275
- * Generate audit report summary text
276
- */
277
- public async generateReportSummary(auditTrail: AuditTrail, context: AuditExportContext): Promise<string> {
278
- const summary = auditTrail.summary;
279
- const generatedAt = new Date().toISOString();
280
-
281
- const reportContent = buildAuditReportContent(auditTrail, generatedAt);
282
-
283
- return this.appendSignedReportIntegrity(
284
- reportContent,
285
- context,
286
- summary.totalEvents,
287
- generatedAt
288
- );
289
- }
290
-
291
- /**
292
- * Append signed integrity metadata to a plain-text audit report.
293
- */
294
- public async appendSignedReportIntegrity(
295
- reportContent: string,
296
- context: AuditExportContext,
297
- totalEntries: number,
298
- generatedAt: string = new Date().toISOString()
299
- ): Promise<string> {
300
- const hash = await calculateSHA256Secure(reportContent);
301
- const signaturePayload = await signAuditExport(
302
- {
303
- exportFormat: 'txt',
304
- exportType: 'report',
305
- generatedAt,
306
- totalEntries,
307
- hash: hash.toUpperCase()
308
- },
309
- context
310
- );
311
-
312
- return reportContent + `
313
-
314
- ============================
315
- INTEGRITY VERIFICATION
316
- ============================
317
- Report Content SHA-256 Hash: ${hash.toUpperCase()}
318
- Audit Signature Metadata: ${JSON.stringify(signaturePayload.signatureMetadata)}
319
- Audit Signature: ${JSON.stringify(signaturePayload.signature)}
320
-
321
- Verification Instructions:
322
- 1. Copy the entire report content above the "INTEGRITY VERIFICATION" section
323
- 2. Calculate SHA256 hash of that content (excluding this verification section)
324
- 3. Validate audit signature metadata and signature with your signature verification workflow (for example OpenSSL or an internal verifier)
325
- 4. Confirm both hash and signature validation pass before relying on this report
326
-
327
- This report requires both hash and signature validation for tamper detection.
328
- Generated by Striae`;
329
- }
330
- }
331
-
332
- // Export singleton instance
333
- export const auditExportService = AuditExportService.getInstance();