@revealui/core 0.2.1 → 0.3.0
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/api/compression.d.ts.map +1 -1
- package/dist/api/payload-optimization.d.ts.map +1 -1
- package/dist/api/rate-limit.d.ts +29 -28
- package/dist/api/rate-limit.d.ts.map +1 -1
- package/dist/api/rate-limit.js +63 -3
- package/dist/api/response-cache.d.ts.map +1 -1
- package/dist/api/response-cache.js +1 -1
- package/dist/api/rest.d.ts.map +1 -1
- package/dist/api/rest.js +3 -2
- package/dist/auth/access.d.ts.map +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/cache/query-cache.d.ts +12 -10
- package/dist/cache/query-cache.d.ts.map +1 -1
- package/dist/cache/query-cache.js +38 -42
- package/dist/caching/app-cache.d.ts +5 -0
- package/dist/caching/app-cache.d.ts.map +1 -1
- package/dist/caching/app-cache.js +9 -1
- package/dist/caching/cdn-config.d.ts.map +1 -1
- package/dist/caching/cdn-config.js +4 -0
- package/dist/caching/edge-cache.d.ts +1 -1
- package/dist/caching/edge-cache.d.ts.map +1 -1
- package/dist/caching/edge-cache.js +36 -7
- package/dist/caching/index.d.ts +6 -0
- package/dist/caching/index.d.ts.map +1 -0
- package/dist/caching/index.js +5 -0
- package/dist/caching/service-worker.d.ts +6 -3
- package/dist/caching/service-worker.d.ts.map +1 -1
- package/dist/caching/service-worker.js +3 -2
- package/dist/client/admin/RichText.d.ts +1 -1
- package/dist/client/admin/RichText.d.ts.map +1 -1
- package/dist/client/admin/components/AdminDashboard.d.ts.map +1 -1
- package/dist/client/admin/components/AdminDashboard.js +178 -205
- package/dist/client/admin/components/CollectionList.d.ts.map +1 -1
- package/dist/client/admin/components/DocumentForm.d.ts.map +1 -1
- package/dist/client/admin/components/DocumentForm.js +130 -6
- package/dist/client/admin/components/GlobalForm.d.ts.map +1 -1
- package/dist/client/admin/context/ServerFunctionContext.d.ts +8 -0
- package/dist/client/admin/context/ServerFunctionContext.d.ts.map +1 -0
- package/dist/client/admin/context/ServerFunctionContext.js +15 -0
- package/dist/client/admin/i18n/en.d.ts.map +1 -1
- package/dist/client/admin/index.d.ts +1 -0
- package/dist/client/admin/index.d.ts.map +1 -1
- package/dist/client/admin/index.js +1 -0
- package/dist/client/admin/layout.d.ts +1 -1
- package/dist/client/admin/layout.d.ts.map +1 -1
- package/dist/client/admin/layout.js +3 -2
- package/dist/client/admin/page.d.ts.map +1 -1
- package/dist/client/admin/utils/apiClient.d.ts.map +1 -1
- package/dist/client/admin/utils/apiClient.js +0 -4
- package/dist/client/admin/utils/index.d.ts +0 -1
- package/dist/client/admin/utils/index.d.ts.map +1 -1
- package/dist/client/admin/utils/index.js +0 -1
- package/dist/client/admin/utils/serializeConfig.d.ts.map +1 -1
- package/dist/client/hooks.d.ts.map +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/richtext/RichTextEditor.d.ts.map +1 -1
- package/dist/client/richtext/components/ImageNodeComponent.d.ts.map +1 -1
- package/dist/client/richtext/components/ImageNodeComponent.js +0 -1
- package/dist/client/richtext/components/ImageUploadButton.d.ts +2 -0
- package/dist/client/richtext/components/ImageUploadButton.d.ts.map +1 -1
- package/dist/client/richtext/components/ImageUploadButton.js +30 -15
- package/dist/client/richtext/index.d.ts.map +1 -1
- package/dist/client/richtext/nodes/DecoratorBlockNode.d.ts.map +1 -1
- package/dist/client/richtext/nodes/ImageNode.d.ts.map +1 -1
- package/dist/client/richtext/plugins/CollaborationPlugin.d.ts.map +1 -1
- package/dist/client/richtext/plugins/CursorsOverlayPlugin.d.ts.map +1 -1
- package/dist/client/richtext/plugins/FloatingToolbarPlugin.d.ts.map +1 -1
- package/dist/client/richtext/plugins/ImagePlugin.d.ts.map +1 -1
- package/dist/client/richtext/plugins/ToolbarPlugin.d.ts.map +1 -1
- package/dist/client/ui/index.d.ts.map +1 -1
- package/dist/client/ui/index.js +1 -1
- package/dist/collections/CollectionOperations.d.ts +7 -7
- package/dist/collections/CollectionOperations.d.ts.map +1 -1
- package/dist/collections/CollectionOperations.js +15 -1
- package/dist/collections/hooks.d.ts.map +1 -1
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/collections/operations/create.d.ts +2 -4
- package/dist/collections/operations/create.d.ts.map +1 -1
- package/dist/collections/operations/create.js +7 -5
- package/dist/collections/operations/createMany.d.ts +12 -0
- package/dist/collections/operations/createMany.d.ts.map +1 -0
- package/dist/collections/operations/createMany.js +43 -0
- package/dist/collections/operations/delete.d.ts +1 -1
- package/dist/collections/operations/delete.d.ts.map +1 -1
- package/dist/collections/operations/delete.js +31 -2
- package/dist/collections/operations/deleteMany.d.ts +11 -0
- package/dist/collections/operations/deleteMany.d.ts.map +1 -0
- package/dist/collections/operations/deleteMany.js +50 -0
- package/dist/collections/operations/fieldHooks.d.ts +2 -2
- package/dist/collections/operations/fieldHooks.d.ts.map +1 -1
- package/dist/collections/operations/fieldHooks.js +4 -4
- package/dist/collections/operations/find.d.ts +2 -4
- package/dist/collections/operations/find.d.ts.map +1 -1
- package/dist/collections/operations/find.js +115 -8
- package/dist/collections/operations/findById.d.ts +3 -4
- package/dist/collections/operations/findById.d.ts.map +1 -1
- package/dist/collections/operations/findById.js +53 -1
- package/dist/collections/operations/sqlAdapter.d.ts +23 -0
- package/dist/collections/operations/sqlAdapter.d.ts.map +1 -0
- package/dist/collections/operations/sqlAdapter.js +76 -0
- package/dist/collections/operations/update.d.ts +3 -5
- package/dist/collections/operations/update.d.ts.map +1 -1
- package/dist/collections/operations/update.js +103 -11
- package/dist/collections/operations/updateMany.d.ts +11 -0
- package/dist/collections/operations/updateMany.d.ts.map +1 -0
- package/dist/collections/operations/updateMany.js +52 -0
- package/dist/collections/registry.d.ts +12 -0
- package/dist/collections/registry.d.ts.map +1 -0
- package/dist/collections/registry.js +38 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/runtime.d.ts.map +1 -1
- package/dist/config/utils.d.ts +0 -10
- package/dist/config/utils.d.ts.map +1 -1
- package/dist/config/utils.js +0 -13
- package/dist/database/index.d.ts +3 -0
- package/dist/database/index.d.ts.map +1 -1
- package/dist/database/index.js +1 -5
- package/dist/database/safe-parse.d.ts.map +1 -1
- package/dist/database/ssl-config.d.ts.map +1 -1
- package/dist/database/type-adapter.d.ts.map +1 -1
- package/dist/database/universal-postgres.d.ts.map +1 -1
- package/dist/database/universal-postgres.js +6 -1
- package/dist/dataloader.d.ts.map +1 -1
- package/dist/error-handling/circuit-breaker.d.ts +1 -1
- package/dist/error-handling/circuit-breaker.d.ts.map +1 -1
- package/dist/error-handling/circuit-breaker.js +11 -3
- package/dist/error-handling/error-boundary.d.ts.map +1 -1
- package/dist/error-handling/error-reporter.d.ts +1 -1
- package/dist/error-handling/error-reporter.d.ts.map +1 -1
- package/dist/error-handling/error-reporter.js +19 -5
- package/dist/error-handling/fallback-components.d.ts.map +1 -1
- package/dist/error-handling/fallback-components.js +1 -1
- package/dist/error-handling/index.d.ts +2 -4
- package/dist/error-handling/index.d.ts.map +1 -1
- package/dist/error-handling/index.js +1 -4
- package/dist/error-handling/retry.d.ts.map +1 -1
- package/dist/error-handling/retry.js +13 -8
- package/dist/factories/builders.d.ts.map +1 -1
- package/dist/factories/index.d.ts.map +1 -1
- package/dist/features.d.ts +0 -4
- package/dist/features.d.ts.map +1 -1
- package/dist/features.js +0 -2
- package/dist/fieldTraversal.d.ts.map +1 -1
- package/dist/fields/config/types.d.ts.map +1 -1
- package/dist/fields/getDefaultValue.d.ts.map +1 -1
- package/dist/fields/getFieldPaths.d.ts.map +1 -1
- package/dist/fields/hooks/afterRead/index.d.ts.map +1 -1
- package/dist/fields/hooks/afterRead/promise.d.ts.map +1 -1
- package/dist/fields/hooks/afterRead/traverseFields.d.ts.map +1 -1
- package/dist/generated/types/cms.d.ts.map +1 -1
- package/dist/generated/types/cms.js +0 -1
- package/dist/generated/types/neon.d.ts.map +1 -1
- package/dist/generated/types/neon.js +4 -2
- package/dist/globals/GlobalOperations.d.ts.map +1 -1
- package/dist/globals/GlobalOperations.js +4 -2
- package/dist/globals/index.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/instance/RevealUIInstance.d.ts.map +1 -1
- package/dist/instance/RevealUIInstance.js +6 -19
- package/dist/instance/index.d.ts.map +1 -1
- package/dist/instance/logger.d.ts.map +1 -1
- package/dist/instance/methods/create.d.ts.map +1 -1
- package/dist/instance/methods/create.js +0 -3
- package/dist/instance/methods/delete.d.ts.map +1 -1
- package/dist/instance/methods/delete.js +1 -4
- package/dist/instance/methods/find.d.ts.map +1 -1
- package/dist/instance/methods/find.js +0 -3
- package/dist/instance/methods/findById.d.ts.map +1 -1
- package/dist/instance/methods/findById.js +0 -3
- package/dist/instance/methods/hooks.d.ts.map +1 -1
- package/dist/instance/methods/update.d.ts.map +1 -1
- package/dist/instance/methods/update.js +0 -3
- package/dist/jobs/index.d.ts +16 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +14 -0
- package/dist/jobs/queue.d.ts +57 -0
- package/dist/jobs/queue.d.ts.map +1 -0
- package/dist/jobs/queue.js +134 -0
- package/dist/license-encryption.d.ts +21 -0
- package/dist/license-encryption.d.ts.map +1 -0
- package/dist/license-encryption.js +74 -0
- package/dist/license.d.ts +20 -3
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +73 -6
- package/dist/monitoring/alerts.d.ts.map +1 -1
- package/dist/monitoring/cleanup-manager.d.ts.map +1 -1
- package/dist/monitoring/health-monitor.d.ts.map +1 -1
- package/dist/monitoring/index.d.ts.map +1 -1
- package/dist/monitoring/process-registry.d.ts.map +1 -1
- package/dist/monitoring/query-monitor.d.ts.map +1 -1
- package/dist/monitoring/types.d.ts.map +1 -1
- package/dist/monitoring/zombie-detector.d.ts.map +1 -1
- package/dist/monitoring/zombie-detector.js +5 -0
- package/dist/nextjs/index.d.ts.map +1 -1
- package/dist/nextjs/utilities.d.ts.map +1 -1
- package/dist/nextjs/withRevealUI.d.ts.map +1 -1
- package/dist/observability/alerts.d.ts.map +1 -1
- package/dist/observability/alerts.js +1 -2
- package/dist/observability/health-check.d.ts +0 -4
- package/dist/observability/health-check.d.ts.map +1 -1
- package/dist/observability/health-check.js +0 -36
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/logger.d.ts.map +1 -1
- package/dist/observability/logger.js +1 -1
- package/dist/observability/metrics.d.ts.map +1 -1
- package/dist/observability/tracing.d.ts.map +1 -1
- package/dist/observability/tracing.js +0 -1
- package/dist/optimization/asset-optimizer.d.ts +6 -2
- package/dist/optimization/asset-optimizer.d.ts.map +1 -1
- package/dist/optimization/asset-optimizer.js +31 -7
- package/dist/optimization/bundle-analyzer.d.ts +1 -1
- package/dist/optimization/bundle-analyzer.d.ts.map +1 -1
- package/dist/optimization/bundle-analyzer.js +29 -5
- package/dist/optimization/code-splitting.d.ts +0 -10
- package/dist/optimization/code-splitting.d.ts.map +1 -1
- package/dist/optimization/code-splitting.js +0 -16
- package/dist/plugins/form-builder.d.ts.map +1 -1
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/nested-docs.d.ts +4 -0
- package/dist/plugins/nested-docs.d.ts.map +1 -1
- package/dist/plugins/nested-docs.js +50 -5
- package/dist/plugins/redirects.d.ts.map +1 -1
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/queryBuilder.d.ts.map +1 -1
- package/dist/queries/queryBuilder.js +9 -2
- package/dist/relationships/analyzer.d.ts.map +1 -1
- package/dist/relationships/analyzer.js +8 -0
- package/dist/relationships/index.d.ts.map +1 -1
- package/dist/relationships/populate-core.d.ts +57 -0
- package/dist/relationships/populate-core.d.ts.map +1 -0
- package/dist/relationships/populate-core.js +116 -0
- package/dist/relationships/populate-helpers.d.ts +5 -51
- package/dist/relationships/populate-helpers.d.ts.map +1 -1
- package/dist/relationships/populate-helpers.js +4 -109
- package/dist/relationships/population.d.ts +1 -9
- package/dist/relationships/population.d.ts.map +1 -1
- package/dist/relationships/population.js +8 -3
- package/dist/revealui.d.ts.map +1 -1
- package/dist/richtext/exports/client/rcc.d.ts.map +1 -1
- package/dist/richtext/exports/client/rcc.js +1 -1
- package/dist/richtext/exports/server/rsc.d.ts +17 -0
- package/dist/richtext/exports/server/rsc.d.ts.map +1 -1
- package/dist/richtext/exports/server/rsc.js +61 -5
- package/dist/richtext/index.d.ts.map +1 -1
- package/dist/richtext/lexical.d.ts.map +1 -1
- package/dist/security/audit.d.ts +1 -1
- package/dist/security/audit.d.ts.map +1 -1
- package/dist/security/audit.js +4 -2
- package/dist/security/auth.d.ts +29 -160
- package/dist/security/auth.d.ts.map +1 -1
- package/dist/security/auth.js +148 -367
- package/dist/security/authorization.d.ts +7 -31
- package/dist/security/authorization.d.ts.map +1 -1
- package/dist/security/authorization.js +72 -14
- package/dist/security/encryption.d.ts +56 -44
- package/dist/security/encryption.d.ts.map +1 -1
- package/dist/security/encryption.js +113 -96
- package/dist/security/gdpr-storage.d.ts +102 -0
- package/dist/security/gdpr-storage.d.ts.map +1 -0
- package/dist/security/gdpr-storage.js +65 -0
- package/dist/security/gdpr.d.ts +57 -37
- package/dist/security/gdpr.d.ts.map +1 -1
- package/dist/security/gdpr.js +155 -89
- package/dist/security/headers.d.ts +4 -2
- package/dist/security/headers.d.ts.map +1 -1
- package/dist/security/headers.js +35 -17
- package/dist/security/index.d.ts +3 -16
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +3 -16
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/renderPage.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +2 -4
- package/dist/storage/vercel-blob.d.ts.map +1 -1
- package/dist/translations/index.d.ts.map +1 -1
- package/dist/types/access.d.ts.map +1 -1
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/cms.d.ts.map +1 -1
- package/dist/types/config.d.ts.map +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/generated.d.ts.map +1 -1
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/interfaces/app.d.ts.map +1 -1
- package/dist/types/jobs.d.ts.map +1 -1
- package/dist/types/legacy.d.ts.map +1 -1
- package/dist/types/plugins.d.ts.map +1 -1
- package/dist/types/query.d.ts.map +1 -1
- package/dist/types/request.d.ts.map +1 -1
- package/dist/types/richtext.d.ts.map +1 -1
- package/dist/types/runtime.d.ts +59 -1
- package/dist/types/runtime.d.ts.map +1 -1
- package/dist/types/schema.d.ts.map +1 -1
- package/dist/types/user.d.ts.map +1 -1
- package/dist/utils/access-conversion.d.ts.map +1 -1
- package/dist/utils/api-wrapper.d.ts.map +1 -1
- package/dist/utils/api-wrapper.js +1 -1
- package/dist/utils/block-conversion.d.ts.map +1 -1
- package/dist/utils/cache.d.ts.map +1 -1
- package/dist/utils/deep-clone.js +0 -1
- package/dist/utils/error-responses.d.ts.map +1 -1
- package/dist/utils/errors.d.ts +36 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +103 -0
- package/dist/utils/field-conversion.d.ts +1 -1
- package/dist/utils/field-conversion.d.ts.map +1 -1
- package/dist/utils/flattenResult.d.ts.map +1 -1
- package/dist/utils/flattenResult.js +0 -1
- package/dist/utils/getBlockSelect.d.ts.map +1 -1
- package/dist/utils/getSelectMode.d.ts.map +1 -1
- package/dist/utils/isValidID.d.ts.map +1 -1
- package/dist/utils/json-parsing.d.ts.map +1 -1
- package/dist/utils/logger-client.d.ts.map +1 -1
- package/dist/utils/logger-server.d.ts.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/request-context.d.ts.map +1 -1
- package/dist/utils/stripUnselectedFields.d.ts.map +1 -1
- package/dist/utils/type-guards.d.ts.map +1 -1
- package/package.json +39 -7
package/dist/security/gdpr.js
CHANGED
|
@@ -3,14 +3,18 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Data privacy, consent management, data export, and right to be forgotten
|
|
5
5
|
*/
|
|
6
|
-
import { createHash } from 'node:crypto';
|
|
6
|
+
import { createHash, createHmac } from 'node:crypto';
|
|
7
7
|
import { logger } from '../observability/logger.js';
|
|
8
|
+
import { InMemoryBreachStorage } from './gdpr-storage.js';
|
|
8
9
|
/**
|
|
9
10
|
* Consent management system
|
|
10
11
|
*/
|
|
11
12
|
export class ConsentManager {
|
|
12
|
-
|
|
13
|
+
storage;
|
|
13
14
|
consentVersion = '1.0.0';
|
|
15
|
+
constructor(storage) {
|
|
16
|
+
this.storage = storage;
|
|
17
|
+
}
|
|
14
18
|
/**
|
|
15
19
|
* Grant consent
|
|
16
20
|
*/
|
|
@@ -25,25 +29,25 @@ export class ConsentManager {
|
|
|
25
29
|
source,
|
|
26
30
|
version: this.consentVersion,
|
|
27
31
|
};
|
|
28
|
-
this.
|
|
32
|
+
await this.storage.setConsent(userId, type, consent);
|
|
29
33
|
return consent;
|
|
30
34
|
}
|
|
31
35
|
/**
|
|
32
36
|
* Revoke consent
|
|
33
37
|
*/
|
|
34
38
|
async revokeConsent(userId, type) {
|
|
35
|
-
const
|
|
36
|
-
const existing = this.consents.get(key);
|
|
39
|
+
const existing = await this.storage.getConsent(userId, type);
|
|
37
40
|
if (existing) {
|
|
38
41
|
existing.granted = false;
|
|
39
42
|
existing.timestamp = new Date().toISOString();
|
|
43
|
+
await this.storage.setConsent(userId, type, existing);
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
/**
|
|
43
47
|
* Check if consent is granted
|
|
44
48
|
*/
|
|
45
|
-
hasConsent(userId, type) {
|
|
46
|
-
const consent = this.
|
|
49
|
+
async hasConsent(userId, type) {
|
|
50
|
+
const consent = await this.storage.getConsent(userId, type);
|
|
47
51
|
if (!consent?.granted) {
|
|
48
52
|
return false;
|
|
49
53
|
}
|
|
@@ -56,8 +60,8 @@ export class ConsentManager {
|
|
|
56
60
|
/**
|
|
57
61
|
* Get all consents for user
|
|
58
62
|
*/
|
|
59
|
-
getUserConsents(userId) {
|
|
60
|
-
return
|
|
63
|
+
async getUserConsents(userId) {
|
|
64
|
+
return this.storage.getConsentsByUser(userId);
|
|
61
65
|
}
|
|
62
66
|
/**
|
|
63
67
|
* Update consent version
|
|
@@ -68,8 +72,8 @@ export class ConsentManager {
|
|
|
68
72
|
/**
|
|
69
73
|
* Check if consent needs renewal
|
|
70
74
|
*/
|
|
71
|
-
needsRenewal(userId, type, maxAge) {
|
|
72
|
-
const consent = this.
|
|
75
|
+
async needsRenewal(userId, type, maxAge) {
|
|
76
|
+
const consent = await this.storage.getConsent(userId, type);
|
|
73
77
|
if (!consent?.granted) {
|
|
74
78
|
return true;
|
|
75
79
|
}
|
|
@@ -79,8 +83,8 @@ export class ConsentManager {
|
|
|
79
83
|
/**
|
|
80
84
|
* Get consent statistics
|
|
81
85
|
*/
|
|
82
|
-
getStatistics() {
|
|
83
|
-
const consents =
|
|
86
|
+
async getStatistics() {
|
|
87
|
+
const consents = await this.storage.getAllConsents();
|
|
84
88
|
const now = new Date();
|
|
85
89
|
const granted = consents.filter((c) => c.granted).length;
|
|
86
90
|
const revoked = consents.filter((c) => !c.granted).length;
|
|
@@ -98,6 +102,19 @@ export class ConsentManager {
|
|
|
98
102
|
};
|
|
99
103
|
}
|
|
100
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
|
+
}
|
|
101
118
|
/**
|
|
102
119
|
* Data export system
|
|
103
120
|
*/
|
|
@@ -134,12 +151,12 @@ export class DataExportSystem {
|
|
|
134
151
|
// Profile data
|
|
135
152
|
lines.push('Type,Key,Value');
|
|
136
153
|
Object.entries(exportData.data.profile).forEach(([key, value]) => {
|
|
137
|
-
lines.push(`Profile,${key}
|
|
154
|
+
lines.push(`Profile,${escapeCsvField(key)},${escapeCsvField(String(value))}`);
|
|
138
155
|
});
|
|
139
156
|
// Activities
|
|
140
157
|
exportData.data.activities.forEach((activity, index) => {
|
|
141
158
|
Object.entries(activity).forEach(([key, value]) => {
|
|
142
|
-
lines.push(`Activity ${index + 1},${key}
|
|
159
|
+
lines.push(`Activity ${index + 1},${escapeCsvField(key)},${escapeCsvField(String(value))}`);
|
|
143
160
|
});
|
|
144
161
|
});
|
|
145
162
|
return lines.join('\n');
|
|
@@ -156,7 +173,10 @@ export class DataExportSystem {
|
|
|
156
173
|
* Data deletion system (Right to be Forgotten)
|
|
157
174
|
*/
|
|
158
175
|
export class DataDeletionSystem {
|
|
159
|
-
|
|
176
|
+
storage;
|
|
177
|
+
constructor(storage) {
|
|
178
|
+
this.storage = storage;
|
|
179
|
+
}
|
|
160
180
|
/**
|
|
161
181
|
* Request data deletion
|
|
162
182
|
*/
|
|
@@ -169,41 +189,44 @@ export class DataDeletionSystem {
|
|
|
169
189
|
dataCategories,
|
|
170
190
|
reason,
|
|
171
191
|
};
|
|
172
|
-
this.
|
|
192
|
+
await this.storage.setDeletionRequest(request);
|
|
173
193
|
return request;
|
|
174
194
|
}
|
|
175
195
|
/**
|
|
176
196
|
* Process deletion request
|
|
177
197
|
*/
|
|
178
198
|
async processDeletion(requestId, deleteData) {
|
|
179
|
-
const request = this.
|
|
199
|
+
const request = await this.storage.getDeletionRequest(requestId);
|
|
180
200
|
if (!request) {
|
|
181
201
|
throw new Error('Deletion request not found');
|
|
182
202
|
}
|
|
183
203
|
request.status = 'processing';
|
|
204
|
+
await this.storage.setDeletionRequest(request);
|
|
184
205
|
try {
|
|
185
206
|
const result = await deleteData(request.userId, request.dataCategories);
|
|
186
207
|
request.status = 'completed';
|
|
187
208
|
request.processedAt = new Date().toISOString();
|
|
188
209
|
request.deletedData = result.deleted;
|
|
189
210
|
request.retainedData = result.retained;
|
|
211
|
+
await this.storage.setDeletionRequest(request);
|
|
190
212
|
}
|
|
191
213
|
catch (error) {
|
|
192
214
|
request.status = 'failed';
|
|
215
|
+
await this.storage.setDeletionRequest(request);
|
|
193
216
|
throw error;
|
|
194
217
|
}
|
|
195
218
|
}
|
|
196
219
|
/**
|
|
197
220
|
* Get deletion request
|
|
198
221
|
*/
|
|
199
|
-
getRequest(requestId) {
|
|
200
|
-
return this.
|
|
222
|
+
async getRequest(requestId) {
|
|
223
|
+
return this.storage.getDeletionRequest(requestId);
|
|
201
224
|
}
|
|
202
225
|
/**
|
|
203
226
|
* Get user deletion requests
|
|
204
227
|
*/
|
|
205
|
-
getUserRequests(userId) {
|
|
206
|
-
return
|
|
228
|
+
async getUserRequests(userId) {
|
|
229
|
+
return this.storage.getDeletionRequestsByUser(userId);
|
|
207
230
|
}
|
|
208
231
|
/**
|
|
209
232
|
* Check if data can be deleted
|
|
@@ -232,62 +255,70 @@ export class DataDeletionSystem {
|
|
|
232
255
|
/**
|
|
233
256
|
* Data anonymization utilities
|
|
234
257
|
*/
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* K-anonymity check
|
|
279
|
-
*/
|
|
280
|
-
static checkKAnonymity(data, quasiIdentifiers, k) {
|
|
281
|
-
// Group by quasi-identifiers
|
|
282
|
-
const groups = new Map();
|
|
283
|
-
data.forEach((item) => {
|
|
284
|
-
const key = quasiIdentifiers.map((field) => String(item[field])).join('|');
|
|
285
|
-
groups.set(key, (groups.get(key) || 0) + 1);
|
|
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
|
+
}
|
|
286
298
|
});
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
299
|
+
return anonymized;
|
|
300
|
+
});
|
|
290
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
|
+
};
|
|
291
322
|
/**
|
|
292
323
|
* Privacy policy manager
|
|
293
324
|
*/
|
|
@@ -368,7 +399,17 @@ export class CookieConsentManager {
|
|
|
368
399
|
const stored = localStorage.getItem('cookie-consent');
|
|
369
400
|
if (stored) {
|
|
370
401
|
try {
|
|
371
|
-
|
|
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
|
+
}
|
|
372
413
|
}
|
|
373
414
|
catch {
|
|
374
415
|
// Ignore parse errors
|
|
@@ -392,7 +433,17 @@ export class CookieConsentManager {
|
|
|
392
433
|
}
|
|
393
434
|
}
|
|
394
435
|
export class DataBreachManager {
|
|
395
|
-
|
|
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
|
+
}
|
|
396
447
|
/**
|
|
397
448
|
* Report data breach
|
|
398
449
|
*/
|
|
@@ -403,7 +454,7 @@ export class DataBreachManager {
|
|
|
403
454
|
detectedAt: new Date().toISOString(),
|
|
404
455
|
status: 'detected',
|
|
405
456
|
};
|
|
406
|
-
this.
|
|
457
|
+
await this.storage.setBreach(fullBreach);
|
|
407
458
|
// Auto-notify if critical
|
|
408
459
|
if (fullBreach.severity === 'critical') {
|
|
409
460
|
await this.notifyAuthorities(fullBreach);
|
|
@@ -414,8 +465,10 @@ export class DataBreachManager {
|
|
|
414
465
|
* Notify authorities (required within 72 hours under GDPR)
|
|
415
466
|
*/
|
|
416
467
|
async notifyAuthorities(breach) {
|
|
417
|
-
breach.
|
|
418
|
-
|
|
468
|
+
await this.storage.updateBreach(breach.id, {
|
|
469
|
+
reportedAt: new Date().toISOString(),
|
|
470
|
+
status: 'notified',
|
|
471
|
+
});
|
|
419
472
|
// In production, integrate with data protection authority API
|
|
420
473
|
logger.info('Breach reported to authorities', { breachId: breach.id });
|
|
421
474
|
}
|
|
@@ -423,7 +476,7 @@ export class DataBreachManager {
|
|
|
423
476
|
* Notify affected users
|
|
424
477
|
*/
|
|
425
478
|
async notifyAffectedUsers(breachId, notifyFn) {
|
|
426
|
-
const breach = this.
|
|
479
|
+
const breach = await this.storage.getBreach(breachId);
|
|
427
480
|
if (!breach) {
|
|
428
481
|
throw new Error('Breach not found');
|
|
429
482
|
}
|
|
@@ -444,22 +497,35 @@ export class DataBreachManager {
|
|
|
444
497
|
/**
|
|
445
498
|
* Get breach
|
|
446
499
|
*/
|
|
447
|
-
getBreach(id) {
|
|
448
|
-
return this.
|
|
500
|
+
async getBreach(id) {
|
|
501
|
+
return this.storage.getBreach(id);
|
|
449
502
|
}
|
|
450
503
|
/**
|
|
451
504
|
* Get all breaches
|
|
452
505
|
*/
|
|
453
|
-
getAllBreaches() {
|
|
454
|
-
return
|
|
506
|
+
async getAllBreaches() {
|
|
507
|
+
return this.storage.getAllBreaches();
|
|
455
508
|
}
|
|
456
509
|
}
|
|
457
510
|
/**
|
|
458
|
-
*
|
|
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.
|
|
459
518
|
*/
|
|
460
|
-
export
|
|
519
|
+
export function createConsentManager(storage) {
|
|
520
|
+
return new ConsentManager(storage);
|
|
521
|
+
}
|
|
522
|
+
export function createDataDeletionSystem(storage) {
|
|
523
|
+
return new DataDeletionSystem(storage);
|
|
524
|
+
}
|
|
461
525
|
export const dataExportSystem = new DataExportSystem();
|
|
462
|
-
export const dataDeletionSystem = new DataDeletionSystem();
|
|
463
526
|
export const privacyPolicyManager = new PrivacyPolicyManager();
|
|
464
527
|
export const cookieConsentManager = new CookieConsentManager();
|
|
528
|
+
export function createDataBreachManager(storage) {
|
|
529
|
+
return new DataBreachManager(storage);
|
|
530
|
+
}
|
|
465
531
|
export const dataBreachManager = new DataBreachManager();
|
|
@@ -163,11 +163,13 @@ export declare const CORSPresets: {
|
|
|
163
163
|
*/
|
|
164
164
|
moderate: (allowedOrigins: string[]) => CORSConfig;
|
|
165
165
|
/**
|
|
166
|
-
* Permissive CORS (all origins)
|
|
166
|
+
* Permissive CORS (all origins) — development only.
|
|
167
|
+
* Logs a warning if used when NODE_ENV === 'production'.
|
|
167
168
|
*/
|
|
168
169
|
permissive: () => CORSConfig;
|
|
169
170
|
/**
|
|
170
|
-
* API CORS (
|
|
171
|
+
* API CORS (public read-only APIs) — credentials disabled.
|
|
172
|
+
* Logs a warning if used when NODE_ENV === 'production'.
|
|
171
173
|
*/
|
|
172
174
|
api: () => CORSConfig;
|
|
173
175
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/security/headers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/security/headers.ts"],"names":[],"mappings":"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"}
|
package/dist/security/headers.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* HTTP security headers and CORS policy management
|
|
5
5
|
*/
|
|
6
|
+
import { defaultLogger } from '../instance/logger.js';
|
|
6
7
|
/**
|
|
7
8
|
* Security headers manager
|
|
8
9
|
*/
|
|
@@ -192,6 +193,11 @@ export class CORSManager {
|
|
|
192
193
|
if (this.isOriginAllowed(origin)) {
|
|
193
194
|
headers['Access-Control-Allow-Origin'] = this.config.origin === '*' ? '*' : origin;
|
|
194
195
|
}
|
|
196
|
+
// Vary: Origin — required when Access-Control-Allow-Origin is not '*' so caches
|
|
197
|
+
// don't serve a response allowed for origin A to origin B.
|
|
198
|
+
if (this.config.origin !== '*') {
|
|
199
|
+
headers.Vary = 'Origin';
|
|
200
|
+
}
|
|
195
201
|
// Access-Control-Allow-Credentials — incompatible with origin: '*' per Fetch spec
|
|
196
202
|
if (this.config.credentials && this.config.origin !== '*') {
|
|
197
203
|
headers['Access-Control-Allow-Credentials'] = 'true';
|
|
@@ -345,26 +351,38 @@ export const CORSPresets = {
|
|
|
345
351
|
maxAge: 86400,
|
|
346
352
|
}),
|
|
347
353
|
/**
|
|
348
|
-
* Permissive CORS (all origins)
|
|
354
|
+
* Permissive CORS (all origins) — development only.
|
|
355
|
+
* Logs a warning if used when NODE_ENV === 'production'.
|
|
349
356
|
*/
|
|
350
|
-
permissive: () =>
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
+
permissive: () => {
|
|
358
|
+
if (process.env.NODE_ENV === 'production') {
|
|
359
|
+
defaultLogger.warn('[SecurityPresets] CORS permissive preset used in production — this allows all origins. Use moderate() with explicit origins instead.');
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
origin: '*',
|
|
363
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
|
364
|
+
allowedHeaders: ['*'],
|
|
365
|
+
credentials: false,
|
|
366
|
+
maxAge: 86400,
|
|
367
|
+
};
|
|
368
|
+
},
|
|
357
369
|
/**
|
|
358
|
-
* API CORS (
|
|
370
|
+
* API CORS (public read-only APIs) — credentials disabled.
|
|
371
|
+
* Logs a warning if used when NODE_ENV === 'production'.
|
|
359
372
|
*/
|
|
360
|
-
api: () =>
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
373
|
+
api: () => {
|
|
374
|
+
if (process.env.NODE_ENV === 'production') {
|
|
375
|
+
defaultLogger.warn('[SecurityPresets] CORS api preset uses origin:"*". For production, pass explicit origins to moderate() instead.');
|
|
376
|
+
}
|
|
377
|
+
return {
|
|
378
|
+
origin: '*',
|
|
379
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
|
|
380
|
+
allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key'],
|
|
381
|
+
exposedHeaders: ['X-RateLimit-Limit', 'X-RateLimit-Remaining', 'X-RateLimit-Reset'],
|
|
382
|
+
credentials: false,
|
|
383
|
+
maxAge: 86400,
|
|
384
|
+
};
|
|
385
|
+
},
|
|
368
386
|
};
|
|
369
387
|
/**
|
|
370
388
|
* Security middleware creator
|
package/dist/security/index.d.ts
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Security & Compliance
|
|
3
|
-
*
|
|
4
|
-
* Comprehensive security infrastructure for authentication, authorization,
|
|
5
|
-
* encryption, audit logging, GDPR compliance, and secure headers
|
|
2
|
+
* Security & Compliance — re-exported from @revealui/security
|
|
3
|
+
* New code should import directly from '@revealui/security'.
|
|
6
4
|
*/
|
|
7
|
-
export
|
|
8
|
-
export { AuditReportGenerator, AuditSystem, AuditTrail, audit, createAuditMiddleware, InMemoryAuditStorage, } from './audit';
|
|
9
|
-
export type { AuthConfig, AuthSession, AuthToken, JWTPayload, OAuthConfig, User, } from './auth';
|
|
10
|
-
export { AuthSystem, OAuthClient, OAuthProviders, PasswordHasher, TwoFactorAuth, } from './auth';
|
|
11
|
-
export type { AuthorizationContext, Permission, Policy, PolicyCondition, Role, } from './authorization';
|
|
12
|
-
export { AuthorizationSystem, authorization, CommonRoles, canAccessResource, checkAttributeAccess, createAuthorizationMiddleware, PermissionBuilder, PermissionCache, PolicyBuilder, permissionCache, RequirePermission, RequireRole, } from './authorization';
|
|
13
|
-
export type { EncryptedData, EncryptionConfig, } from './encryption';
|
|
14
|
-
export { DataMasking, EncryptionSystem, EnvelopeEncryption, encryption, FieldEncryption, KeyRotationManager, TokenGenerator, } from './encryption';
|
|
15
|
-
export type { ConsentRecord, ConsentType, CookieConsentConfig, DataBreach, DataCategory, DataDeletionRequest, DataProcessingPurpose, PersonalDataExport, } from './gdpr';
|
|
16
|
-
export { ConsentManager, CookieConsentManager, consentManager, cookieConsentManager, DataAnonymization, DataBreachManager, DataDeletionSystem, DataExportSystem, dataBreachManager, dataDeletionSystem, dataExportSystem, PrivacyPolicyManager, privacyPolicyManager, } from './gdpr';
|
|
17
|
-
export type { CORSConfig, ContentSecurityPolicyConfig, HSTSConfig, PermissionsPolicyConfig, ReferrerPolicyValue, SecurityHeadersConfig, } from './headers';
|
|
18
|
-
export { CORSManager, CORSPresets, createSecurityMiddleware, SecurityHeaders, SecurityPresets, setRateLimitHeaders, } from './headers';
|
|
5
|
+
export * from '@revealui/security';
|
|
19
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,oBAAoB,CAAC"}
|
package/dist/security/index.js
CHANGED
|
@@ -1,18 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Security & Compliance
|
|
3
|
-
*
|
|
4
|
-
* Comprehensive security infrastructure for authentication, authorization,
|
|
5
|
-
* encryption, audit logging, GDPR compliance, and secure headers
|
|
2
|
+
* Security & Compliance — re-exported from @revealui/security
|
|
3
|
+
* New code should import directly from '@revealui/security'.
|
|
6
4
|
*/
|
|
7
|
-
|
|
8
|
-
export { AuditReportGenerator, AuditSystem, AuditTrail, audit, createAuditMiddleware, InMemoryAuditStorage, } from './audit';
|
|
9
|
-
// Authentication
|
|
10
|
-
export { AuthSystem, OAuthClient, OAuthProviders, PasswordHasher, TwoFactorAuth, } from './auth';
|
|
11
|
-
// Authorization
|
|
12
|
-
export { AuthorizationSystem, authorization, CommonRoles, canAccessResource, checkAttributeAccess, createAuthorizationMiddleware, PermissionBuilder, PermissionCache, PolicyBuilder, permissionCache, RequirePermission, RequireRole, } from './authorization';
|
|
13
|
-
// Encryption
|
|
14
|
-
export { DataMasking, EncryptionSystem, EnvelopeEncryption, encryption, FieldEncryption, KeyRotationManager, TokenGenerator, } from './encryption';
|
|
15
|
-
// GDPR compliance
|
|
16
|
-
export { ConsentManager, CookieConsentManager, consentManager, cookieConsentManager, DataAnonymization, DataBreachManager, DataDeletionSystem, DataExportSystem, dataBreachManager, dataDeletionSystem, dataExportSystem, PrivacyPolicyManager, privacyPolicyManager, } from './gdpr';
|
|
17
|
-
// Security headers
|
|
18
|
-
export { CORSManager, CORSPresets, createSecurityMiddleware, SecurityHeaders, SecurityPresets, setRateLimitHeaders, } from './headers';
|
|
5
|
+
export * from '@revealui/security';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEjE,cAAc,6BAA6B,CAAC;AAQ5C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderPage.d.ts","sourceRoot":"","sources":["../../src/server/renderPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,
|
|
1
|
+
{"version":3,"file":"renderPage.d.ts","sourceRoot":"","sources":["../../src/server/renderPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxD,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAczE;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,MAAM,CA6CtE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CAqB1E"}
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/storage/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vercel-blob.d.ts","sourceRoot":"","sources":["../../src/storage/vercel-blob.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"vercel-blob.d.ts","sourceRoot":"","sources":["../../src/storage/vercel-blob.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE;QACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAqFzE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/translations/index.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,gBAAgB;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG;QACb,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/translations/index.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,gBAAgB;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG;QACb,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;KACnD,CAAC;CACH;AAED,MAAM,WAAW,yBAAyB;IACxC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,MAAM,WAAW,IAAI;IACnB,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;CAC3D;AAED,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC"}
|