@revealui/core 0.3.0 → 0.5.2
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.
- package/dist/client/admin/components/AdminDashboard.d.ts.map +1 -1
- package/dist/client/admin/components/AdminDashboard.js +20 -3
- package/dist/client/richtext/index.d.ts.map +1 -1
- package/dist/client/richtext/plugins/FloatingToolbarPlugin.js +1 -3
- package/dist/collections/operations/create.d.ts +2 -1
- package/dist/collections/operations/create.d.ts.map +1 -1
- package/dist/collections/operations/create.js +28 -1
- package/dist/database/type-adapter.d.ts.map +1 -1
- package/dist/features.d.ts +13 -3
- package/dist/features.d.ts.map +1 -1
- package/dist/features.js +17 -0
- package/dist/globals/GlobalOperations.d.ts.map +1 -1
- package/dist/globals/GlobalOperations.js +12 -2
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/license.d.ts +6 -0
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +14 -1
- package/dist/monitoring/alerts.d.ts +4 -4
- package/dist/monitoring/alerts.d.ts.map +1 -1
- package/dist/plugins/nested-docs.d.ts.map +1 -1
- package/dist/plugins/nested-docs.js +0 -1
- package/dist/queries/queryBuilder.d.ts.map +1 -1
- package/dist/queries/queryBuilder.js +4 -3
- package/dist/richtext/index.d.ts.map +1 -1
- package/dist/storage/vercel-blob.d.ts.map +1 -1
- package/dist/storage/vercel-blob.js +3 -0
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/core.d.ts +1 -1
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/extensions.d.ts.map +1 -1
- package/dist/types/frontend.d.ts.map +1 -1
- package/dist/types/legacy.d.ts.map +1 -1
- package/dist/types/query.d.ts.map +1 -1
- package/dist/types/runtime.d.ts +1 -0
- package/dist/types/runtime.d.ts.map +1 -1
- package/dist/utils/error-responses.d.ts.map +1 -1
- package/dist/utils/error-responses.js +2 -3
- package/package.json +24 -24
- package/dist/caching/app-cache.d.ts +0 -242
- package/dist/caching/app-cache.d.ts.map +0 -1
- package/dist/caching/app-cache.js +0 -438
- package/dist/caching/cdn-config.d.ts +0 -155
- package/dist/caching/cdn-config.d.ts.map +0 -1
- package/dist/caching/cdn-config.js +0 -415
- package/dist/caching/edge-cache.d.ts +0 -177
- package/dist/caching/edge-cache.d.ts.map +0 -1
- package/dist/caching/edge-cache.js +0 -414
- package/dist/caching/service-worker.d.ts +0 -157
- package/dist/caching/service-worker.d.ts.map +0 -1
- package/dist/caching/service-worker.js +0 -438
- package/dist/client/admin/utils/auth.d.ts +0 -23
- package/dist/client/admin/utils/auth.d.ts.map +0 -1
- package/dist/client/admin/utils/auth.js +0 -52
- package/dist/client/http/client.d.ts +0 -15
- package/dist/client/http/client.d.ts.map +0 -1
- package/dist/client/http/client.js +0 -49
- package/dist/client/http/fetchBanner.d.ts +0 -18
- package/dist/client/http/fetchBanner.d.ts.map +0 -1
- package/dist/client/http/fetchBanner.js +0 -44
- package/dist/client/http/fetchCard.d.ts +0 -18
- package/dist/client/http/fetchCard.d.ts.map +0 -1
- package/dist/client/http/fetchCard.js +0 -46
- package/dist/client/http/fetchEvents.d.ts +0 -18
- package/dist/client/http/fetchEvents.d.ts.map +0 -1
- package/dist/client/http/fetchEvents.js +0 -44
- package/dist/client/http/fetchHero.d.ts +0 -17
- package/dist/client/http/fetchHero.d.ts.map +0 -1
- package/dist/client/http/fetchHero.js +0 -55
- package/dist/client/http/fetchMainInfos.d.ts +0 -17
- package/dist/client/http/fetchMainInfos.d.ts.map +0 -1
- package/dist/client/http/fetchMainInfos.js +0 -44
- package/dist/client/http/fetchVideos.d.ts +0 -13
- package/dist/client/http/fetchVideos.d.ts.map +0 -1
- package/dist/client/http/fetchVideos.js +0 -36
- package/dist/client/http/index.d.ts +0 -19
- package/dist/client/http/index.d.ts.map +0 -1
- package/dist/client/http/index.js +0 -11
- package/dist/error-handling/circuit-breaker.d.ts +0 -262
- package/dist/error-handling/circuit-breaker.d.ts.map +0 -1
- package/dist/error-handling/circuit-breaker.js +0 -550
- package/dist/error-handling/retry.d.ts +0 -194
- package/dist/error-handling/retry.d.ts.map +0 -1
- package/dist/error-handling/retry.js +0 -455
- package/dist/errors/index.d.ts +0 -23
- package/dist/errors/index.d.ts.map +0 -1
- package/dist/errors/index.js +0 -40
- package/dist/generated/agents/index.d.ts +0 -8
- package/dist/generated/agents/index.d.ts.map +0 -1
- package/dist/generated/agents/index.js +0 -7
- package/dist/generated/components/index.d.ts +0 -8
- package/dist/generated/components/index.d.ts.map +0 -1
- package/dist/generated/components/index.js +0 -7
- package/dist/generated/functions/index.d.ts +0 -8
- package/dist/generated/functions/index.d.ts.map +0 -1
- package/dist/generated/functions/index.js +0 -7
- package/dist/generated/hooks/index.d.ts +0 -8
- package/dist/generated/hooks/index.d.ts.map +0 -1
- package/dist/generated/hooks/index.js +0 -7
- package/dist/generated/plans/index.d.ts +0 -8
- package/dist/generated/plans/index.d.ts.map +0 -1
- package/dist/generated/plans/index.js +0 -7
- package/dist/generated/prompts/index.d.ts +0 -8
- package/dist/generated/prompts/index.d.ts.map +0 -1
- package/dist/generated/prompts/index.js +0 -7
- package/dist/generated/tools/index.d.ts +0 -8
- package/dist/generated/tools/index.d.ts.map +0 -1
- package/dist/generated/tools/index.js +0 -7
- package/dist/generated/types/supabase.d.ts +0 -193
- package/dist/generated/types/supabase.d.ts.map +0 -1
- package/dist/generated/types/supabase.js +0 -5
- package/dist/optimization/asset-optimizer.d.ts +0 -206
- package/dist/optimization/asset-optimizer.d.ts.map +0 -1
- package/dist/optimization/asset-optimizer.js +0 -336
- package/dist/optimization/build-optimizer.d.ts +0 -202
- package/dist/optimization/build-optimizer.d.ts.map +0 -1
- package/dist/optimization/build-optimizer.js +0 -271
- package/dist/optimization/bundle-analyzer.d.ts +0 -98
- package/dist/optimization/bundle-analyzer.d.ts.map +0 -1
- package/dist/optimization/bundle-analyzer.js +0 -346
- package/dist/optimization/code-splitting.d.ts +0 -121
- package/dist/optimization/code-splitting.d.ts.map +0 -1
- package/dist/optimization/code-splitting.js +0 -261
- package/dist/plugin/index.d.ts +0 -12
- package/dist/plugin/index.d.ts.map +0 -1
- package/dist/plugin/index.js +0 -4
- package/dist/security/audit.d.ts +0 -188
- package/dist/security/audit.d.ts.map +0 -1
- package/dist/security/audit.js +0 -433
- package/dist/security/auth.d.ts +0 -110
- package/dist/security/auth.d.ts.map +0 -1
- package/dist/security/auth.js +0 -257
- package/dist/security/authorization.d.ts +0 -211
- package/dist/security/authorization.d.ts.map +0 -1
- package/dist/security/authorization.js +0 -492
- package/dist/security/encryption.d.ts +0 -226
- package/dist/security/encryption.d.ts.map +0 -1
- package/dist/security/encryption.js +0 -534
- package/dist/security/gdpr-storage.d.ts +0 -102
- package/dist/security/gdpr-storage.d.ts.map +0 -1
- package/dist/security/gdpr-storage.js +0 -65
- package/dist/security/gdpr.d.ts +0 -320
- package/dist/security/gdpr.d.ts.map +0 -1
- package/dist/security/gdpr.js +0 -531
- package/dist/security/headers.d.ts +0 -184
- package/dist/security/headers.d.ts.map +0 -1
- package/dist/security/headers.js +0 -420
- package/dist/utils/jwt-validation.d.ts +0 -14
- package/dist/utils/jwt-validation.d.ts.map +0 -1
- package/dist/utils/jwt-validation.js +0 -36
- package/dist/utils/request-headers.d.ts +0 -15
- package/dist/utils/request-headers.d.ts.map +0 -1
- package/dist/utils/request-headers.js +0 -31
package/dist/security/gdpr.js
DELETED
|
@@ -1,531 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GDPR Compliance Utilities
|
|
3
|
-
*
|
|
4
|
-
* Data privacy, consent management, data export, and right to be forgotten
|
|
5
|
-
*/
|
|
6
|
-
import { createHash, createHmac } from 'node:crypto';
|
|
7
|
-
import { logger } from '../observability/logger.js';
|
|
8
|
-
import { InMemoryBreachStorage } from './gdpr-storage.js';
|
|
9
|
-
/**
|
|
10
|
-
* Consent management system
|
|
11
|
-
*/
|
|
12
|
-
export class ConsentManager {
|
|
13
|
-
storage;
|
|
14
|
-
consentVersion = '1.0.0';
|
|
15
|
-
constructor(storage) {
|
|
16
|
-
this.storage = storage;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Grant consent
|
|
20
|
-
*/
|
|
21
|
-
async grantConsent(userId, type, source = 'explicit', expiresIn) {
|
|
22
|
-
const consent = {
|
|
23
|
-
id: crypto.randomUUID(),
|
|
24
|
-
userId,
|
|
25
|
-
type,
|
|
26
|
-
granted: true,
|
|
27
|
-
timestamp: new Date().toISOString(),
|
|
28
|
-
expiresAt: expiresIn ? new Date(Date.now() + expiresIn).toISOString() : undefined,
|
|
29
|
-
source,
|
|
30
|
-
version: this.consentVersion,
|
|
31
|
-
};
|
|
32
|
-
await this.storage.setConsent(userId, type, consent);
|
|
33
|
-
return consent;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Revoke consent
|
|
37
|
-
*/
|
|
38
|
-
async revokeConsent(userId, type) {
|
|
39
|
-
const existing = await this.storage.getConsent(userId, type);
|
|
40
|
-
if (existing) {
|
|
41
|
-
existing.granted = false;
|
|
42
|
-
existing.timestamp = new Date().toISOString();
|
|
43
|
-
await this.storage.setConsent(userId, type, existing);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Check if consent is granted
|
|
48
|
-
*/
|
|
49
|
-
async hasConsent(userId, type) {
|
|
50
|
-
const consent = await this.storage.getConsent(userId, type);
|
|
51
|
-
if (!consent?.granted) {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
// Check if expired
|
|
55
|
-
if (consent.expiresAt && new Date(consent.expiresAt) < new Date()) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Get all consents for user
|
|
62
|
-
*/
|
|
63
|
-
async getUserConsents(userId) {
|
|
64
|
-
return this.storage.getConsentsByUser(userId);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Update consent version
|
|
68
|
-
*/
|
|
69
|
-
setConsentVersion(version) {
|
|
70
|
-
this.consentVersion = version;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Check if consent needs renewal
|
|
74
|
-
*/
|
|
75
|
-
async needsRenewal(userId, type, maxAge) {
|
|
76
|
-
const consent = await this.storage.getConsent(userId, type);
|
|
77
|
-
if (!consent?.granted) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
const age = Date.now() - new Date(consent.timestamp).getTime();
|
|
81
|
-
return age >= maxAge;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Get consent statistics
|
|
85
|
-
*/
|
|
86
|
-
async getStatistics() {
|
|
87
|
-
const consents = await this.storage.getAllConsents();
|
|
88
|
-
const now = new Date();
|
|
89
|
-
const granted = consents.filter((c) => c.granted).length;
|
|
90
|
-
const revoked = consents.filter((c) => !c.granted).length;
|
|
91
|
-
const expired = consents.filter((c) => c.expiresAt && new Date(c.expiresAt) < now).length;
|
|
92
|
-
const byType = consents.reduce((acc, c) => {
|
|
93
|
-
acc[c.type] = (acc[c.type] || 0) + 1;
|
|
94
|
-
return acc;
|
|
95
|
-
}, {});
|
|
96
|
-
return {
|
|
97
|
-
total: consents.length,
|
|
98
|
-
granted,
|
|
99
|
-
revoked,
|
|
100
|
-
expired,
|
|
101
|
-
byType,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Escape a value for safe CSV inclusion.
|
|
107
|
-
* Prevents CSV injection by prefixing formula-triggering characters (=, +, -, @, \t, \r)
|
|
108
|
-
* with a single quote, and escapes embedded quotes/commas per RFC 4180.
|
|
109
|
-
*/
|
|
110
|
-
function escapeCsvField(value) {
|
|
111
|
-
// Prefix formula-triggering characters to prevent CSV injection in spreadsheet apps
|
|
112
|
-
let safe = /^[=+\-@\t\r]/.test(value) ? `'${value}` : value;
|
|
113
|
-
// RFC 4180: escape double quotes by doubling them
|
|
114
|
-
safe = safe.replace(/"/g, '""');
|
|
115
|
-
// Always quote the field to handle commas, newlines, and quotes
|
|
116
|
-
return `"${safe}"`;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Data export system
|
|
120
|
-
*/
|
|
121
|
-
export class DataExportSystem {
|
|
122
|
-
/**
|
|
123
|
-
* Export user data
|
|
124
|
-
*/
|
|
125
|
-
async exportUserData(userId, getUserData, format = 'json') {
|
|
126
|
-
const data = await getUserData(userId);
|
|
127
|
-
const exportData = {
|
|
128
|
-
userId,
|
|
129
|
-
exportedAt: new Date().toISOString(),
|
|
130
|
-
data: {
|
|
131
|
-
profile: data.profile,
|
|
132
|
-
activities: data.activities,
|
|
133
|
-
consents: data.consents,
|
|
134
|
-
dataProcessing: [],
|
|
135
|
-
},
|
|
136
|
-
format,
|
|
137
|
-
};
|
|
138
|
-
return exportData;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Format export as JSON
|
|
142
|
-
*/
|
|
143
|
-
formatAsJSON(exportData) {
|
|
144
|
-
return JSON.stringify(exportData, null, 2);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Format export as CSV
|
|
148
|
-
*/
|
|
149
|
-
formatAsCSV(exportData) {
|
|
150
|
-
const lines = [];
|
|
151
|
-
// Profile data
|
|
152
|
-
lines.push('Type,Key,Value');
|
|
153
|
-
Object.entries(exportData.data.profile).forEach(([key, value]) => {
|
|
154
|
-
lines.push(`Profile,${escapeCsvField(key)},${escapeCsvField(String(value))}`);
|
|
155
|
-
});
|
|
156
|
-
// Activities
|
|
157
|
-
exportData.data.activities.forEach((activity, index) => {
|
|
158
|
-
Object.entries(activity).forEach(([key, value]) => {
|
|
159
|
-
lines.push(`Activity ${index + 1},${escapeCsvField(key)},${escapeCsvField(String(value))}`);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
return lines.join('\n');
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Create download link
|
|
166
|
-
*/
|
|
167
|
-
createDownloadLink(content, _filename, mimeType) {
|
|
168
|
-
const blob = new Blob([content], { type: mimeType });
|
|
169
|
-
return URL.createObjectURL(blob);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Data deletion system (Right to be Forgotten)
|
|
174
|
-
*/
|
|
175
|
-
export class DataDeletionSystem {
|
|
176
|
-
storage;
|
|
177
|
-
constructor(storage) {
|
|
178
|
-
this.storage = storage;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Request data deletion
|
|
182
|
-
*/
|
|
183
|
-
async requestDeletion(userId, dataCategories, reason) {
|
|
184
|
-
const request = {
|
|
185
|
-
id: crypto.randomUUID(),
|
|
186
|
-
userId,
|
|
187
|
-
requestedAt: new Date().toISOString(),
|
|
188
|
-
status: 'pending',
|
|
189
|
-
dataCategories,
|
|
190
|
-
reason,
|
|
191
|
-
};
|
|
192
|
-
await this.storage.setDeletionRequest(request);
|
|
193
|
-
return request;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Process deletion request
|
|
197
|
-
*/
|
|
198
|
-
async processDeletion(requestId, deleteData) {
|
|
199
|
-
const request = await this.storage.getDeletionRequest(requestId);
|
|
200
|
-
if (!request) {
|
|
201
|
-
throw new Error('Deletion request not found');
|
|
202
|
-
}
|
|
203
|
-
request.status = 'processing';
|
|
204
|
-
await this.storage.setDeletionRequest(request);
|
|
205
|
-
try {
|
|
206
|
-
const result = await deleteData(request.userId, request.dataCategories);
|
|
207
|
-
request.status = 'completed';
|
|
208
|
-
request.processedAt = new Date().toISOString();
|
|
209
|
-
request.deletedData = result.deleted;
|
|
210
|
-
request.retainedData = result.retained;
|
|
211
|
-
await this.storage.setDeletionRequest(request);
|
|
212
|
-
}
|
|
213
|
-
catch (error) {
|
|
214
|
-
request.status = 'failed';
|
|
215
|
-
await this.storage.setDeletionRequest(request);
|
|
216
|
-
throw error;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Get deletion request
|
|
221
|
-
*/
|
|
222
|
-
async getRequest(requestId) {
|
|
223
|
-
return this.storage.getDeletionRequest(requestId);
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Get user deletion requests
|
|
227
|
-
*/
|
|
228
|
-
async getUserRequests(userId) {
|
|
229
|
-
return this.storage.getDeletionRequestsByUser(userId);
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Check if data can be deleted
|
|
233
|
-
*/
|
|
234
|
-
canDelete(_dataCategory, legalBasis) {
|
|
235
|
-
// Data with legal obligation or vital interest cannot be deleted
|
|
236
|
-
if (legalBasis === 'legal_obligation' || legalBasis === 'vital_interest') {
|
|
237
|
-
return false;
|
|
238
|
-
}
|
|
239
|
-
return true;
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Calculate retention period
|
|
243
|
-
*/
|
|
244
|
-
calculateRetentionEnd(createdAt, retentionPeriod) {
|
|
245
|
-
return new Date(createdAt.getTime() + retentionPeriod * 24 * 60 * 60 * 1000);
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Check if data should be deleted (retention period expired)
|
|
249
|
-
*/
|
|
250
|
-
shouldDelete(createdAt, retentionPeriod) {
|
|
251
|
-
const retentionEnd = this.calculateRetentionEnd(createdAt, retentionPeriod);
|
|
252
|
-
return new Date() > retentionEnd;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Data anonymization utilities
|
|
257
|
-
*/
|
|
258
|
-
/**
|
|
259
|
-
* Hash value (irreversible) using SHA-256
|
|
260
|
-
*/
|
|
261
|
-
function hashValue(value) {
|
|
262
|
-
const digest = createHash('sha256').update(value).digest('hex');
|
|
263
|
-
return `hash_${digest}`;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Anonymize user data
|
|
267
|
-
*/
|
|
268
|
-
function anonymizeUser(user) {
|
|
269
|
-
return {
|
|
270
|
-
...user,
|
|
271
|
-
email: hashValue(user.email),
|
|
272
|
-
name: 'Anonymous User',
|
|
273
|
-
phone: undefined,
|
|
274
|
-
address: undefined,
|
|
275
|
-
ip: undefined,
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Pseudonymize data (one-way, key-dependent)
|
|
280
|
-
*
|
|
281
|
-
* Uses HMAC-SHA256 — cryptographically bound to the key, resistant to
|
|
282
|
-
* length-extension attacks and GPU brute-force (unlike plain SHA-256).
|
|
283
|
-
*/
|
|
284
|
-
function pseudonymize(value, key) {
|
|
285
|
-
const hmac = createHmac('sha256', key).update(value).digest('hex');
|
|
286
|
-
return `pseudo_${hmac.substring(0, 16)}`;
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Anonymize dataset
|
|
290
|
-
*/
|
|
291
|
-
function anonymizeDataset(data, sensitiveFields) {
|
|
292
|
-
return data.map((item) => {
|
|
293
|
-
const anonymized = { ...item };
|
|
294
|
-
sensitiveFields.forEach((field) => {
|
|
295
|
-
if (field in anonymized && typeof anonymized[field] === 'string') {
|
|
296
|
-
anonymized[field] = hashValue(anonymized[field]);
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
return anonymized;
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* K-anonymity check
|
|
304
|
-
*/
|
|
305
|
-
function checkKAnonymity(data, quasiIdentifiers, k) {
|
|
306
|
-
// Group by quasi-identifiers
|
|
307
|
-
const groups = new Map();
|
|
308
|
-
data.forEach((item) => {
|
|
309
|
-
const key = quasiIdentifiers.map((field) => String(item[field])).join('|');
|
|
310
|
-
groups.set(key, (groups.get(key) || 0) + 1);
|
|
311
|
-
});
|
|
312
|
-
// Check if all groups have at least k members
|
|
313
|
-
return Array.from(groups.values()).every((count) => count >= k);
|
|
314
|
-
}
|
|
315
|
-
export const DataAnonymization = {
|
|
316
|
-
anonymizeUser,
|
|
317
|
-
pseudonymize,
|
|
318
|
-
hashValue,
|
|
319
|
-
anonymizeDataset,
|
|
320
|
-
checkKAnonymity,
|
|
321
|
-
};
|
|
322
|
-
/**
|
|
323
|
-
* Privacy policy manager
|
|
324
|
-
*/
|
|
325
|
-
export class PrivacyPolicyManager {
|
|
326
|
-
policies = new Map();
|
|
327
|
-
currentVersion = '1.0.0';
|
|
328
|
-
/**
|
|
329
|
-
* Add policy version
|
|
330
|
-
*/
|
|
331
|
-
addPolicy(version, content, effectiveDate) {
|
|
332
|
-
this.policies.set(version, { version, content, effectiveDate });
|
|
333
|
-
this.currentVersion = version;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Get current policy
|
|
337
|
-
*/
|
|
338
|
-
getCurrentPolicy() {
|
|
339
|
-
return this.policies.get(this.currentVersion);
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Get policy by version
|
|
343
|
-
*/
|
|
344
|
-
getPolicy(version) {
|
|
345
|
-
return this.policies.get(version);
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Check if user accepted current policy
|
|
349
|
-
*/
|
|
350
|
-
hasAcceptedCurrent(userAcceptedVersion) {
|
|
351
|
-
return userAcceptedVersion === this.currentVersion;
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Get all versions
|
|
355
|
-
*/
|
|
356
|
-
getAllVersions() {
|
|
357
|
-
return Array.from(this.policies.keys());
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
export class CookieConsentManager {
|
|
361
|
-
config = {
|
|
362
|
-
necessary: true,
|
|
363
|
-
functional: false,
|
|
364
|
-
analytics: false,
|
|
365
|
-
marketing: false,
|
|
366
|
-
};
|
|
367
|
-
/**
|
|
368
|
-
* Set consent configuration
|
|
369
|
-
*/
|
|
370
|
-
setConsent(config) {
|
|
371
|
-
this.config = { ...this.config, ...config };
|
|
372
|
-
this.saveToStorage();
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Get consent configuration
|
|
376
|
-
*/
|
|
377
|
-
getConsent() {
|
|
378
|
-
return { ...this.config };
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Check if specific consent is granted
|
|
382
|
-
*/
|
|
383
|
-
hasConsent(type) {
|
|
384
|
-
return this.config[type];
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Save to storage
|
|
388
|
-
*/
|
|
389
|
-
saveToStorage() {
|
|
390
|
-
if (typeof localStorage !== 'undefined') {
|
|
391
|
-
localStorage.setItem('cookie-consent', JSON.stringify(this.config));
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
/**
|
|
395
|
-
* Load from storage
|
|
396
|
-
*/
|
|
397
|
-
loadFromStorage() {
|
|
398
|
-
if (typeof localStorage !== 'undefined') {
|
|
399
|
-
const stored = localStorage.getItem('cookie-consent');
|
|
400
|
-
if (stored) {
|
|
401
|
-
try {
|
|
402
|
-
const parsed = JSON.parse(stored);
|
|
403
|
-
// Validate shape before assigning — only accept known boolean fields
|
|
404
|
-
// to prevent malicious scripts from injecting arbitrary config.
|
|
405
|
-
if (typeof parsed === 'object' && parsed !== null) {
|
|
406
|
-
this.config = {
|
|
407
|
-
necessary: true, // always required
|
|
408
|
-
analytics: typeof parsed.analytics === 'boolean' ? parsed.analytics : false,
|
|
409
|
-
marketing: typeof parsed.marketing === 'boolean' ? parsed.marketing : false,
|
|
410
|
-
functional: typeof parsed.functional === 'boolean' ? parsed.functional : true,
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
catch {
|
|
415
|
-
// Ignore parse errors
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* Clear consent
|
|
422
|
-
*/
|
|
423
|
-
clearConsent() {
|
|
424
|
-
this.config = {
|
|
425
|
-
necessary: true,
|
|
426
|
-
functional: false,
|
|
427
|
-
analytics: false,
|
|
428
|
-
marketing: false,
|
|
429
|
-
};
|
|
430
|
-
if (typeof localStorage !== 'undefined') {
|
|
431
|
-
localStorage.removeItem('cookie-consent');
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
export class DataBreachManager {
|
|
436
|
-
storage;
|
|
437
|
-
constructor(storage) {
|
|
438
|
-
if (storage) {
|
|
439
|
-
this.storage = storage;
|
|
440
|
-
}
|
|
441
|
-
else {
|
|
442
|
-
logger.warn('DataBreachManager: using in-memory storage — breach records will be lost on restart. ' +
|
|
443
|
-
'For production GDPR compliance, pass a database-backed BreachStorage.');
|
|
444
|
-
this.storage = new InMemoryBreachStorage();
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Report data breach
|
|
449
|
-
*/
|
|
450
|
-
async reportBreach(breach) {
|
|
451
|
-
const fullBreach = {
|
|
452
|
-
...breach,
|
|
453
|
-
id: crypto.randomUUID(),
|
|
454
|
-
detectedAt: new Date().toISOString(),
|
|
455
|
-
status: 'detected',
|
|
456
|
-
};
|
|
457
|
-
await this.storage.setBreach(fullBreach);
|
|
458
|
-
// Auto-notify if critical
|
|
459
|
-
if (fullBreach.severity === 'critical') {
|
|
460
|
-
await this.notifyAuthorities(fullBreach);
|
|
461
|
-
}
|
|
462
|
-
return fullBreach;
|
|
463
|
-
}
|
|
464
|
-
/**
|
|
465
|
-
* Notify authorities (required within 72 hours under GDPR)
|
|
466
|
-
*/
|
|
467
|
-
async notifyAuthorities(breach) {
|
|
468
|
-
await this.storage.updateBreach(breach.id, {
|
|
469
|
-
reportedAt: new Date().toISOString(),
|
|
470
|
-
status: 'notified',
|
|
471
|
-
});
|
|
472
|
-
// In production, integrate with data protection authority API
|
|
473
|
-
logger.info('Breach reported to authorities', { breachId: breach.id });
|
|
474
|
-
}
|
|
475
|
-
/**
|
|
476
|
-
* Notify affected users
|
|
477
|
-
*/
|
|
478
|
-
async notifyAffectedUsers(breachId, notifyFn) {
|
|
479
|
-
const breach = await this.storage.getBreach(breachId);
|
|
480
|
-
if (!breach) {
|
|
481
|
-
throw new Error('Breach not found');
|
|
482
|
-
}
|
|
483
|
-
for (const userId of breach.affectedUsers) {
|
|
484
|
-
await notifyFn(userId, breach);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
/**
|
|
488
|
-
* Check if breach notification is required
|
|
489
|
-
*/
|
|
490
|
-
requiresNotification(breach) {
|
|
491
|
-
// Notification required for high risk breaches
|
|
492
|
-
return (breach.severity === 'high' ||
|
|
493
|
-
breach.severity === 'critical' ||
|
|
494
|
-
breach.dataCategories.includes('sensitive') ||
|
|
495
|
-
breach.dataCategories.includes('financial'));
|
|
496
|
-
}
|
|
497
|
-
/**
|
|
498
|
-
* Get breach
|
|
499
|
-
*/
|
|
500
|
-
async getBreach(id) {
|
|
501
|
-
return this.storage.getBreach(id);
|
|
502
|
-
}
|
|
503
|
-
/**
|
|
504
|
-
* Get all breaches
|
|
505
|
-
*/
|
|
506
|
-
async getAllBreaches() {
|
|
507
|
-
return this.storage.getAllBreaches();
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* Factory functions for GDPR subsystems.
|
|
512
|
-
*
|
|
513
|
-
* `ConsentManager` and `DataDeletionSystem` require a `GDPRStorage` implementation.
|
|
514
|
-
* Use `InMemoryGDPRStorage` only in tests — production MUST use a database-backed store.
|
|
515
|
-
*
|
|
516
|
-
* `DataExportSystem`, `PrivacyPolicyManager`, `CookieConsentManager`, and
|
|
517
|
-
* `DataBreachManager` are stateless or client-side only, so singletons are safe.
|
|
518
|
-
*/
|
|
519
|
-
export function createConsentManager(storage) {
|
|
520
|
-
return new ConsentManager(storage);
|
|
521
|
-
}
|
|
522
|
-
export function createDataDeletionSystem(storage) {
|
|
523
|
-
return new DataDeletionSystem(storage);
|
|
524
|
-
}
|
|
525
|
-
export const dataExportSystem = new DataExportSystem();
|
|
526
|
-
export const privacyPolicyManager = new PrivacyPolicyManager();
|
|
527
|
-
export const cookieConsentManager = new CookieConsentManager();
|
|
528
|
-
export function createDataBreachManager(storage) {
|
|
529
|
-
return new DataBreachManager(storage);
|
|
530
|
-
}
|
|
531
|
-
export const dataBreachManager = new DataBreachManager();
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security Headers and CORS Configuration
|
|
3
|
-
*
|
|
4
|
-
* HTTP security headers and CORS policy management
|
|
5
|
-
*/
|
|
6
|
-
export interface SecurityHeadersConfig {
|
|
7
|
-
contentSecurityPolicy?: string | ContentSecurityPolicyConfig;
|
|
8
|
-
strictTransportSecurity?: boolean | HSTSConfig;
|
|
9
|
-
xFrameOptions?: 'DENY' | 'SAMEORIGIN' | string;
|
|
10
|
-
xContentTypeOptions?: boolean;
|
|
11
|
-
referrerPolicy?: ReferrerPolicyValue;
|
|
12
|
-
permissionsPolicy?: string | PermissionsPolicyConfig;
|
|
13
|
-
crossOriginEmbedderPolicy?: 'require-corp' | 'credentialless';
|
|
14
|
-
crossOriginOpenerPolicy?: 'same-origin' | 'same-origin-allow-popups' | 'unsafe-none';
|
|
15
|
-
crossOriginResourcePolicy?: 'same-origin' | 'same-site' | 'cross-origin';
|
|
16
|
-
}
|
|
17
|
-
export interface ContentSecurityPolicyConfig {
|
|
18
|
-
defaultSrc?: string[];
|
|
19
|
-
scriptSrc?: string[];
|
|
20
|
-
styleSrc?: string[];
|
|
21
|
-
imgSrc?: string[];
|
|
22
|
-
fontSrc?: string[];
|
|
23
|
-
connectSrc?: string[];
|
|
24
|
-
frameSrc?: string[];
|
|
25
|
-
objectSrc?: string[];
|
|
26
|
-
mediaSrc?: string[];
|
|
27
|
-
workerSrc?: string[];
|
|
28
|
-
childSrc?: string[];
|
|
29
|
-
formAction?: string[];
|
|
30
|
-
frameAncestors?: string[];
|
|
31
|
-
baseUri?: string[];
|
|
32
|
-
manifestSrc?: string[];
|
|
33
|
-
upgradeInsecureRequests?: boolean;
|
|
34
|
-
blockAllMixedContent?: boolean;
|
|
35
|
-
reportUri?: string;
|
|
36
|
-
reportTo?: string;
|
|
37
|
-
}
|
|
38
|
-
export interface HSTSConfig {
|
|
39
|
-
maxAge: number;
|
|
40
|
-
includeSubDomains?: boolean;
|
|
41
|
-
preload?: boolean;
|
|
42
|
-
}
|
|
43
|
-
export type ReferrerPolicyValue = 'no-referrer' | 'no-referrer-when-downgrade' | 'origin' | 'origin-when-cross-origin' | 'same-origin' | 'strict-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url';
|
|
44
|
-
export interface PermissionsPolicyConfig {
|
|
45
|
-
accelerometer?: string[];
|
|
46
|
-
ambientLightSensor?: string[];
|
|
47
|
-
autoplay?: string[];
|
|
48
|
-
battery?: string[];
|
|
49
|
-
camera?: string[];
|
|
50
|
-
displayCapture?: string[];
|
|
51
|
-
documentDomain?: string[];
|
|
52
|
-
encryptedMedia?: string[];
|
|
53
|
-
fullscreen?: string[];
|
|
54
|
-
geolocation?: string[];
|
|
55
|
-
gyroscope?: string[];
|
|
56
|
-
magnetometer?: string[];
|
|
57
|
-
microphone?: string[];
|
|
58
|
-
midi?: string[];
|
|
59
|
-
payment?: string[];
|
|
60
|
-
pictureInPicture?: string[];
|
|
61
|
-
publicKeyCredentials?: string[];
|
|
62
|
-
screenWakeLock?: string[];
|
|
63
|
-
syncXhr?: string[];
|
|
64
|
-
usb?: string[];
|
|
65
|
-
webShare?: string[];
|
|
66
|
-
xrSpatialTracking?: string[];
|
|
67
|
-
}
|
|
68
|
-
export interface CORSConfig {
|
|
69
|
-
origin?: string | string[] | ((origin: string) => boolean);
|
|
70
|
-
methods?: string[];
|
|
71
|
-
allowedHeaders?: string[];
|
|
72
|
-
exposedHeaders?: string[];
|
|
73
|
-
credentials?: boolean;
|
|
74
|
-
maxAge?: number;
|
|
75
|
-
preflightContinue?: boolean;
|
|
76
|
-
optionsSuccessStatus?: number;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Security headers manager
|
|
80
|
-
*/
|
|
81
|
-
export declare class SecurityHeaders {
|
|
82
|
-
private config;
|
|
83
|
-
constructor(config?: SecurityHeadersConfig);
|
|
84
|
-
/**
|
|
85
|
-
* Get all security headers
|
|
86
|
-
*/
|
|
87
|
-
getHeaders(): Record<string, string>;
|
|
88
|
-
/**
|
|
89
|
-
* Build Content Security Policy header
|
|
90
|
-
*/
|
|
91
|
-
private buildCSP;
|
|
92
|
-
/**
|
|
93
|
-
* Build HSTS header
|
|
94
|
-
*/
|
|
95
|
-
private buildHSTS;
|
|
96
|
-
/**
|
|
97
|
-
* Build Permissions-Policy header
|
|
98
|
-
*/
|
|
99
|
-
private buildPermissionsPolicy;
|
|
100
|
-
/**
|
|
101
|
-
* Apply headers to response
|
|
102
|
-
*/
|
|
103
|
-
applyHeaders(response: Response): Response;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* CORS manager
|
|
107
|
-
*/
|
|
108
|
-
export declare class CORSManager {
|
|
109
|
-
private config;
|
|
110
|
-
constructor(config?: CORSConfig);
|
|
111
|
-
/**
|
|
112
|
-
* Check if origin is allowed
|
|
113
|
-
*/
|
|
114
|
-
isOriginAllowed(origin: string): boolean;
|
|
115
|
-
/**
|
|
116
|
-
* Get CORS headers
|
|
117
|
-
*/
|
|
118
|
-
getCORSHeaders(origin: string): Record<string, string>;
|
|
119
|
-
/**
|
|
120
|
-
* Get preflight headers
|
|
121
|
-
*/
|
|
122
|
-
getPreflightHeaders(origin: string): Record<string, string>;
|
|
123
|
-
/**
|
|
124
|
-
* Handle CORS request
|
|
125
|
-
*/
|
|
126
|
-
handleRequest(request: Request): Response | null;
|
|
127
|
-
/**
|
|
128
|
-
* Handle preflight request
|
|
129
|
-
*/
|
|
130
|
-
handlePreflight(_request: Request, origin: string): Response;
|
|
131
|
-
/**
|
|
132
|
-
* Apply CORS headers to response
|
|
133
|
-
*/
|
|
134
|
-
applyHeaders(response: Response, origin: string): Response;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Common security header presets
|
|
138
|
-
*/
|
|
139
|
-
export declare const SecurityPresets: {
|
|
140
|
-
/**
|
|
141
|
-
* Strict security (recommended for production)
|
|
142
|
-
*/
|
|
143
|
-
strict: () => SecurityHeadersConfig;
|
|
144
|
-
/**
|
|
145
|
-
* Moderate security (balanced)
|
|
146
|
-
*/
|
|
147
|
-
moderate: () => SecurityHeadersConfig;
|
|
148
|
-
/**
|
|
149
|
-
* Development (permissive)
|
|
150
|
-
*/
|
|
151
|
-
development: () => SecurityHeadersConfig;
|
|
152
|
-
};
|
|
153
|
-
/**
|
|
154
|
-
* Common CORS presets
|
|
155
|
-
*/
|
|
156
|
-
export declare const CORSPresets: {
|
|
157
|
-
/**
|
|
158
|
-
* Strict CORS (same origin only)
|
|
159
|
-
*/
|
|
160
|
-
strict: () => CORSConfig;
|
|
161
|
-
/**
|
|
162
|
-
* Moderate CORS (specific origins)
|
|
163
|
-
*/
|
|
164
|
-
moderate: (allowedOrigins: string[]) => CORSConfig;
|
|
165
|
-
/**
|
|
166
|
-
* Permissive CORS (all origins) — development only.
|
|
167
|
-
* Logs a warning if used when NODE_ENV === 'production'.
|
|
168
|
-
*/
|
|
169
|
-
permissive: () => CORSConfig;
|
|
170
|
-
/**
|
|
171
|
-
* API CORS (public read-only APIs) — credentials disabled.
|
|
172
|
-
* Logs a warning if used when NODE_ENV === 'production'.
|
|
173
|
-
*/
|
|
174
|
-
api: () => CORSConfig;
|
|
175
|
-
};
|
|
176
|
-
/**
|
|
177
|
-
* Security middleware creator
|
|
178
|
-
*/
|
|
179
|
-
export declare function createSecurityMiddleware(securityConfig?: SecurityHeadersConfig, corsConfig?: CORSConfig): (request: Request, next: () => Promise<Response>) => Promise<Response>;
|
|
180
|
-
/**
|
|
181
|
-
* Rate limiting headers
|
|
182
|
-
*/
|
|
183
|
-
export declare function setRateLimitHeaders(response: Response, limit: number, remaining: number, reset: number): void;
|
|
184
|
-
//# sourceMappingURL=headers.d.ts.map
|