@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
|
@@ -192,35 +192,73 @@ export class AuthorizationSystem {
|
|
|
192
192
|
*/
|
|
193
193
|
export const authorization = new AuthorizationSystem();
|
|
194
194
|
/**
|
|
195
|
-
* Common roles
|
|
195
|
+
* Common roles — aligned with DB schema (`users.role` column)
|
|
196
|
+
* and `UserRoleSchema` in @revealui/contracts.
|
|
197
|
+
*
|
|
198
|
+
* Values: owner | admin | editor | viewer | agent | contributor
|
|
196
199
|
*/
|
|
197
200
|
export const CommonRoles = {
|
|
201
|
+
owner: {
|
|
202
|
+
id: 'owner',
|
|
203
|
+
name: 'Owner',
|
|
204
|
+
description: 'Full control — inherits admin',
|
|
205
|
+
permissions: [{ resource: '*', action: '*' }],
|
|
206
|
+
inherits: ['admin'],
|
|
207
|
+
},
|
|
198
208
|
admin: {
|
|
199
209
|
id: 'admin',
|
|
200
210
|
name: 'Administrator',
|
|
201
211
|
description: 'Full system access',
|
|
202
212
|
permissions: [{ resource: '*', action: '*' }],
|
|
203
213
|
},
|
|
204
|
-
|
|
205
|
-
id: '
|
|
206
|
-
name: '
|
|
207
|
-
description: '
|
|
214
|
+
editor: {
|
|
215
|
+
id: 'editor',
|
|
216
|
+
name: 'Editor',
|
|
217
|
+
description: 'Can read and modify content',
|
|
208
218
|
permissions: [
|
|
219
|
+
{ resource: 'content', action: 'read' },
|
|
220
|
+
{ resource: 'content', action: 'create' },
|
|
221
|
+
{ resource: 'content', action: 'update' },
|
|
209
222
|
{ resource: 'profile', action: 'read' },
|
|
210
223
|
{ resource: 'profile', action: 'update' },
|
|
211
|
-
{ resource: '
|
|
212
|
-
{ resource: '
|
|
224
|
+
{ resource: 'sites', action: 'read' },
|
|
225
|
+
{ resource: 'marketplace', action: 'read' },
|
|
213
226
|
],
|
|
214
227
|
},
|
|
215
|
-
|
|
216
|
-
id: '
|
|
217
|
-
name: '
|
|
218
|
-
description: '
|
|
228
|
+
viewer: {
|
|
229
|
+
id: 'viewer',
|
|
230
|
+
name: 'Viewer',
|
|
231
|
+
description: 'Read-only access',
|
|
219
232
|
permissions: [
|
|
220
|
-
{ resource: '
|
|
233
|
+
{ resource: 'content', action: 'read' },
|
|
234
|
+
{ resource: 'profile', action: 'read' },
|
|
235
|
+
{ resource: 'sites', action: 'read' },
|
|
221
236
|
{ resource: 'public', action: 'read' },
|
|
222
237
|
],
|
|
223
238
|
},
|
|
239
|
+
agent: {
|
|
240
|
+
id: 'agent',
|
|
241
|
+
name: 'AI Agent',
|
|
242
|
+
description: 'Can execute tasks and read content',
|
|
243
|
+
permissions: [
|
|
244
|
+
{ resource: 'tasks', action: 'create' },
|
|
245
|
+
{ resource: 'tasks', action: 'read' },
|
|
246
|
+
{ resource: 'content', action: 'read' },
|
|
247
|
+
{ resource: 'rag', action: 'read' },
|
|
248
|
+
{ resource: 'rag', action: 'create' },
|
|
249
|
+
],
|
|
250
|
+
},
|
|
251
|
+
contributor: {
|
|
252
|
+
id: 'contributor',
|
|
253
|
+
name: 'Contributor',
|
|
254
|
+
description: 'Can suggest changes — create drafts but not publish or delete',
|
|
255
|
+
permissions: [
|
|
256
|
+
{ resource: 'content', action: 'read' },
|
|
257
|
+
{ resource: 'content', action: 'create' },
|
|
258
|
+
{ resource: 'profile', action: 'read' },
|
|
259
|
+
{ resource: 'profile', action: 'update' },
|
|
260
|
+
],
|
|
261
|
+
},
|
|
224
262
|
};
|
|
225
263
|
/**
|
|
226
264
|
* Permission builder
|
|
@@ -375,9 +413,11 @@ export function checkAttributeAccess(context, resource, action, requiredAttribut
|
|
|
375
413
|
export class PermissionCache {
|
|
376
414
|
cache = new Map();
|
|
377
415
|
ttl;
|
|
378
|
-
|
|
379
|
-
|
|
416
|
+
maxEntries;
|
|
417
|
+
constructor(ttl = 300000, maxEntries = 10_000) {
|
|
418
|
+
// 5 minutes default, 10k max entries
|
|
380
419
|
this.ttl = ttl;
|
|
420
|
+
this.maxEntries = maxEntries;
|
|
381
421
|
}
|
|
382
422
|
/**
|
|
383
423
|
* Get cached permission
|
|
@@ -400,6 +440,24 @@ export class PermissionCache {
|
|
|
400
440
|
*/
|
|
401
441
|
set(userId, resource, action, allowed) {
|
|
402
442
|
const key = this.getCacheKey(userId, resource, action);
|
|
443
|
+
// Evict expired entries when approaching max size
|
|
444
|
+
if (this.cache.size >= this.maxEntries) {
|
|
445
|
+
const now = Date.now();
|
|
446
|
+
for (const [k, v] of this.cache) {
|
|
447
|
+
if (now > v.expiresAt)
|
|
448
|
+
this.cache.delete(k);
|
|
449
|
+
}
|
|
450
|
+
// If still over limit after purge, drop oldest entries (FIFO via Map insertion order)
|
|
451
|
+
if (this.cache.size >= this.maxEntries) {
|
|
452
|
+
const excess = this.cache.size - this.maxEntries + 1;
|
|
453
|
+
const keys = this.cache.keys();
|
|
454
|
+
for (let i = 0; i < excess; i++) {
|
|
455
|
+
const next = keys.next();
|
|
456
|
+
if (!next.done)
|
|
457
|
+
this.cache.delete(next.value);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
403
461
|
this.cache.set(key, {
|
|
404
462
|
allowed,
|
|
405
463
|
expiresAt: Date.now() + this.ttl,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Data encryption for at-rest and in-transit protection
|
|
5
5
|
*/
|
|
6
6
|
export interface EncryptionConfig {
|
|
7
|
-
algorithm: 'AES-GCM' | 'AES-
|
|
7
|
+
algorithm: 'AES-GCM' | 'AES-CTR';
|
|
8
8
|
keySize: 128 | 192 | 256;
|
|
9
9
|
ivSize?: number;
|
|
10
10
|
}
|
|
@@ -125,6 +125,7 @@ export declare class KeyRotationManager {
|
|
|
125
125
|
private encryption;
|
|
126
126
|
private currentKeyId;
|
|
127
127
|
private oldKeys;
|
|
128
|
+
private keyCreationDates;
|
|
128
129
|
constructor(encryption: EncryptionSystem, initialKeyId: string);
|
|
129
130
|
/**
|
|
130
131
|
* Rotate to new key
|
|
@@ -139,9 +140,10 @@ export declare class KeyRotationManager {
|
|
|
139
140
|
*/
|
|
140
141
|
getCurrentKeyId(): string;
|
|
141
142
|
/**
|
|
142
|
-
* Clean up old keys
|
|
143
|
+
* Clean up old keys created before the specified date.
|
|
144
|
+
* Never removes the current active key.
|
|
143
145
|
*/
|
|
144
|
-
cleanupOldKeys(
|
|
146
|
+
cleanupOldKeys(olderThan: Date): void;
|
|
145
147
|
}
|
|
146
148
|
/**
|
|
147
149
|
* Envelope encryption for large data
|
|
@@ -167,48 +169,58 @@ export declare class EnvelopeEncryption {
|
|
|
167
169
|
/**
|
|
168
170
|
* Data masking utilities
|
|
169
171
|
*/
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
172
|
+
/**
|
|
173
|
+
* Mask email
|
|
174
|
+
*/
|
|
175
|
+
declare function maskEmail(email: string): string;
|
|
176
|
+
/**
|
|
177
|
+
* Mask phone number
|
|
178
|
+
*/
|
|
179
|
+
declare function maskPhone(phone: string): string;
|
|
180
|
+
/**
|
|
181
|
+
* Mask credit card
|
|
182
|
+
*/
|
|
183
|
+
declare function maskCreditCard(card: string): string;
|
|
184
|
+
/**
|
|
185
|
+
* Mask SSN
|
|
186
|
+
*/
|
|
187
|
+
declare function maskSSN(ssn: string): string;
|
|
188
|
+
/**
|
|
189
|
+
* Mask string (keep first and last character)
|
|
190
|
+
*/
|
|
191
|
+
declare function maskString(str: string, keepChars?: number): string;
|
|
192
|
+
export declare const DataMasking: {
|
|
193
|
+
readonly maskEmail: typeof maskEmail;
|
|
194
|
+
readonly maskPhone: typeof maskPhone;
|
|
195
|
+
readonly maskCreditCard: typeof maskCreditCard;
|
|
196
|
+
readonly maskSSN: typeof maskSSN;
|
|
197
|
+
readonly maskString: typeof maskString;
|
|
198
|
+
};
|
|
192
199
|
/**
|
|
193
200
|
* Secure random token generator
|
|
194
201
|
*/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Generate secure token. `length` is the number of random bytes;
|
|
204
|
+
* the returned string is hex-encoded, so it will be `length * 2` characters.
|
|
205
|
+
*/
|
|
206
|
+
declare function generateToken(length?: number): string;
|
|
207
|
+
/**
|
|
208
|
+
* Generate UUID v4
|
|
209
|
+
*/
|
|
210
|
+
declare function generateUUID(): string;
|
|
211
|
+
/**
|
|
212
|
+
* Generate API key
|
|
213
|
+
*/
|
|
214
|
+
declare function generateAPIKey(prefix?: string): string;
|
|
215
|
+
/**
|
|
216
|
+
* Generate session ID
|
|
217
|
+
*/
|
|
218
|
+
declare function generateSessionID(): string;
|
|
219
|
+
export declare const TokenGenerator: {
|
|
220
|
+
readonly generate: typeof generateToken;
|
|
221
|
+
readonly generateUUID: typeof generateUUID;
|
|
222
|
+
readonly generateAPIKey: typeof generateAPIKey;
|
|
223
|
+
readonly generateSessionID: typeof generateSessionID;
|
|
224
|
+
};
|
|
225
|
+
export {};
|
|
214
226
|
//# sourceMappingURL=encryption.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/security/encryption.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,SAAS,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/security/encryption.ts"],"names":[],"mappings":"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"}
|
|
@@ -315,9 +315,11 @@ export class KeyRotationManager {
|
|
|
315
315
|
encryption;
|
|
316
316
|
currentKeyId;
|
|
317
317
|
oldKeys = new Map();
|
|
318
|
+
keyCreationDates = new Map();
|
|
318
319
|
constructor(encryption, initialKeyId) {
|
|
319
320
|
this.encryption = encryption;
|
|
320
321
|
this.currentKeyId = initialKeyId;
|
|
322
|
+
this.keyCreationDates.set(initialKeyId, new Date());
|
|
321
323
|
}
|
|
322
324
|
/**
|
|
323
325
|
* Rotate to new key
|
|
@@ -331,6 +333,7 @@ export class KeyRotationManager {
|
|
|
331
333
|
// Set new key
|
|
332
334
|
this.encryption.storeKey(newKeyId, newKey);
|
|
333
335
|
this.currentKeyId = newKeyId;
|
|
336
|
+
this.keyCreationDates.set(newKeyId, new Date());
|
|
334
337
|
}
|
|
335
338
|
/**
|
|
336
339
|
* Re-encrypt data with new key
|
|
@@ -354,12 +357,17 @@ export class KeyRotationManager {
|
|
|
354
357
|
return this.currentKeyId;
|
|
355
358
|
}
|
|
356
359
|
/**
|
|
357
|
-
* Clean up old keys
|
|
360
|
+
* Clean up old keys created before the specified date.
|
|
361
|
+
* Never removes the current active key.
|
|
358
362
|
*/
|
|
359
|
-
cleanupOldKeys(
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
+
cleanupOldKeys(olderThan) {
|
|
364
|
+
for (const [keyId, createdAt] of this.keyCreationDates.entries()) {
|
|
365
|
+
if (keyId !== this.currentKeyId && createdAt < olderThan) {
|
|
366
|
+
this.oldKeys.delete(keyId);
|
|
367
|
+
this.encryption.removeKey(keyId);
|
|
368
|
+
this.keyCreationDates.delete(keyId);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
363
371
|
}
|
|
364
372
|
}
|
|
365
373
|
/**
|
|
@@ -418,100 +426,109 @@ export class EnvelopeEncryption {
|
|
|
418
426
|
/**
|
|
419
427
|
* Data masking utilities
|
|
420
428
|
*/
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
return `${prefix}${masked}${suffix}`;
|
|
478
|
-
}
|
|
429
|
+
/**
|
|
430
|
+
* Mask email
|
|
431
|
+
*/
|
|
432
|
+
function maskEmail(email) {
|
|
433
|
+
const [local, domain] = email.split('@');
|
|
434
|
+
if (!(local && domain))
|
|
435
|
+
return email;
|
|
436
|
+
const maskedLocal = local.length > 2
|
|
437
|
+
? local[0] + '*'.repeat(local.length - 2) + local[local.length - 1]
|
|
438
|
+
: `${local[0]}*`;
|
|
439
|
+
return `${maskedLocal}@${domain}`;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Mask phone number
|
|
443
|
+
*/
|
|
444
|
+
function maskPhone(phone) {
|
|
445
|
+
const digits = phone.replace(/\D/g, '');
|
|
446
|
+
if (digits.length < 4)
|
|
447
|
+
return phone;
|
|
448
|
+
const lastFour = digits.slice(-4);
|
|
449
|
+
const masked = '*'.repeat(digits.length - 4) + lastFour;
|
|
450
|
+
return phone.replace(/\d/g, (char, index) => {
|
|
451
|
+
const digitIndex = phone.slice(0, index + 1).replace(/\D/g, '').length - 1;
|
|
452
|
+
return masked[digitIndex] || char;
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Mask credit card
|
|
457
|
+
*/
|
|
458
|
+
function maskCreditCard(card) {
|
|
459
|
+
const digits = card.replace(/\D/g, '');
|
|
460
|
+
if (digits.length < 4)
|
|
461
|
+
return card;
|
|
462
|
+
const lastFour = digits.slice(-4);
|
|
463
|
+
return `****-****-****-${lastFour}`;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Mask SSN
|
|
467
|
+
*/
|
|
468
|
+
function maskSSN(ssn) {
|
|
469
|
+
const digits = ssn.replace(/\D/g, '');
|
|
470
|
+
if (digits.length !== 9)
|
|
471
|
+
return ssn;
|
|
472
|
+
return `***-**-${digits.slice(-4)}`;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Mask string (keep first and last character)
|
|
476
|
+
*/
|
|
477
|
+
function maskString(str, keepChars = 1) {
|
|
478
|
+
if (str.length <= keepChars * 2) {
|
|
479
|
+
return '*'.repeat(str.length);
|
|
480
|
+
}
|
|
481
|
+
const prefix = str.slice(0, keepChars);
|
|
482
|
+
const suffix = str.slice(-keepChars);
|
|
483
|
+
const masked = '*'.repeat(str.length - keepChars * 2);
|
|
484
|
+
return `${prefix}${masked}${suffix}`;
|
|
479
485
|
}
|
|
486
|
+
export const DataMasking = {
|
|
487
|
+
maskEmail,
|
|
488
|
+
maskPhone,
|
|
489
|
+
maskCreditCard,
|
|
490
|
+
maskSSN,
|
|
491
|
+
maskString,
|
|
492
|
+
};
|
|
480
493
|
/**
|
|
481
494
|
* Secure random token generator
|
|
482
495
|
*/
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
throw new Error('Crypto API not available');
|
|
501
|
-
}
|
|
502
|
-
return crypto.randomUUID();
|
|
503
|
-
}
|
|
504
|
-
/**
|
|
505
|
-
* Generate API key
|
|
506
|
-
*/
|
|
507
|
-
static generateAPIKey(prefix = 'sk') {
|
|
508
|
-
const token = TokenGenerator.generate(32);
|
|
509
|
-
return `${prefix}_${token}`;
|
|
510
|
-
}
|
|
511
|
-
/**
|
|
512
|
-
* Generate session ID
|
|
513
|
-
*/
|
|
514
|
-
static generateSessionID() {
|
|
515
|
-
return TokenGenerator.generate(64);
|
|
496
|
+
/**
|
|
497
|
+
* Generate secure token. `length` is the number of random bytes;
|
|
498
|
+
* the returned string is hex-encoded, so it will be `length * 2` characters.
|
|
499
|
+
*/
|
|
500
|
+
function generateToken(length = 32) {
|
|
501
|
+
const bytes = encryption.randomBytes(length);
|
|
502
|
+
return Array.from(bytes)
|
|
503
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
504
|
+
.join('');
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Generate UUID v4
|
|
508
|
+
*/
|
|
509
|
+
function generateUUID() {
|
|
510
|
+
const crypto = globalThis.crypto;
|
|
511
|
+
if (!crypto) {
|
|
512
|
+
throw new Error('Crypto API not available');
|
|
516
513
|
}
|
|
514
|
+
return crypto.randomUUID();
|
|
517
515
|
}
|
|
516
|
+
/**
|
|
517
|
+
* Generate API key
|
|
518
|
+
*/
|
|
519
|
+
function generateAPIKey(prefix = 'sk') {
|
|
520
|
+
const token = generateToken(32);
|
|
521
|
+
return `${prefix}_${token}`;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Generate session ID
|
|
525
|
+
*/
|
|
526
|
+
function generateSessionID() {
|
|
527
|
+
return generateToken(64);
|
|
528
|
+
}
|
|
529
|
+
export const TokenGenerator = {
|
|
530
|
+
generate: generateToken,
|
|
531
|
+
generateUUID,
|
|
532
|
+
generateAPIKey,
|
|
533
|
+
generateSessionID,
|
|
534
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GDPR Storage Abstraction
|
|
3
|
+
*
|
|
4
|
+
* Record-oriented storage interface for GDPR compliance data.
|
|
5
|
+
* Provides a clean seam for replacing the default in-memory implementation
|
|
6
|
+
* with a database-backed store in production.
|
|
7
|
+
*/
|
|
8
|
+
import type { ConsentRecord, ConsentType, DataBreach, DataDeletionRequest } from './gdpr.js';
|
|
9
|
+
/**
|
|
10
|
+
* Storage interface for GDPR consent records and deletion requests.
|
|
11
|
+
*
|
|
12
|
+
* All methods are async to support database-backed implementations.
|
|
13
|
+
* The default `InMemoryGDPRStorage` is suitable for testing and development
|
|
14
|
+
* but must be replaced with a persistent store for production use.
|
|
15
|
+
*/
|
|
16
|
+
export interface GDPRStorage {
|
|
17
|
+
/**
|
|
18
|
+
* Store or update a consent record, keyed by `userId:consentType`.
|
|
19
|
+
*/
|
|
20
|
+
setConsent(userId: string, type: ConsentType, record: ConsentRecord): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Retrieve a consent record by user and type. Returns `undefined` if not found.
|
|
23
|
+
*/
|
|
24
|
+
getConsent(userId: string, type: ConsentType): Promise<ConsentRecord | undefined>;
|
|
25
|
+
/**
|
|
26
|
+
* Retrieve all consent records for a given user.
|
|
27
|
+
*/
|
|
28
|
+
getConsentsByUser(userId: string): Promise<ConsentRecord[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Retrieve every consent record in storage (used for aggregate statistics).
|
|
31
|
+
*/
|
|
32
|
+
getAllConsents(): Promise<ConsentRecord[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Store a deletion request, keyed by its `id`.
|
|
35
|
+
*/
|
|
36
|
+
setDeletionRequest(request: DataDeletionRequest): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Retrieve a deletion request by ID. Returns `undefined` if not found.
|
|
39
|
+
*/
|
|
40
|
+
getDeletionRequest(requestId: string): Promise<DataDeletionRequest | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* Retrieve all deletion requests for a given user.
|
|
43
|
+
*/
|
|
44
|
+
getDeletionRequestsByUser(userId: string): Promise<DataDeletionRequest[]>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Storage interface for data breach records.
|
|
48
|
+
*
|
|
49
|
+
* All methods are async to support database-backed implementations.
|
|
50
|
+
* The default `InMemoryBreachStorage` is suitable for testing and development
|
|
51
|
+
* but must be replaced with a persistent store for production GDPR compliance.
|
|
52
|
+
*/
|
|
53
|
+
export interface BreachStorage {
|
|
54
|
+
/**
|
|
55
|
+
* Store a data breach record.
|
|
56
|
+
*/
|
|
57
|
+
setBreach(breach: DataBreach): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Retrieve a breach by ID. Returns `undefined` if not found.
|
|
60
|
+
*/
|
|
61
|
+
getBreach(id: string): Promise<DataBreach | undefined>;
|
|
62
|
+
/**
|
|
63
|
+
* Retrieve all breach records.
|
|
64
|
+
*/
|
|
65
|
+
getAllBreaches(): Promise<DataBreach[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Update an existing breach record (e.g., status change, add mitigation).
|
|
68
|
+
*/
|
|
69
|
+
updateBreach(id: string, updates: Partial<DataBreach>): Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* In-memory implementation of `BreachStorage`.
|
|
73
|
+
*
|
|
74
|
+
* WARNING: All data is lost on process restart or serverless cold start.
|
|
75
|
+
* GDPR requires breach records be retained — use database-backed storage in production.
|
|
76
|
+
*/
|
|
77
|
+
export declare class InMemoryBreachStorage implements BreachStorage {
|
|
78
|
+
private breaches;
|
|
79
|
+
setBreach(breach: DataBreach): Promise<void>;
|
|
80
|
+
getBreach(id: string): Promise<DataBreach | undefined>;
|
|
81
|
+
getAllBreaches(): Promise<DataBreach[]>;
|
|
82
|
+
updateBreach(id: string, updates: Partial<DataBreach>): Promise<void>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* In-memory implementation of `GDPRStorage`.
|
|
86
|
+
*
|
|
87
|
+
* WARNING: All data is lost on process restart or serverless cold start.
|
|
88
|
+
* Use this only for development, testing, or as a reference implementation.
|
|
89
|
+
* Production deployments MUST supply a database-backed `GDPRStorage`.
|
|
90
|
+
*/
|
|
91
|
+
export declare class InMemoryGDPRStorage implements GDPRStorage {
|
|
92
|
+
private consents;
|
|
93
|
+
private deletionRequests;
|
|
94
|
+
setConsent(userId: string, type: ConsentType, record: ConsentRecord): Promise<void>;
|
|
95
|
+
getConsent(userId: string, type: ConsentType): Promise<ConsentRecord | undefined>;
|
|
96
|
+
getConsentsByUser(userId: string): Promise<ConsentRecord[]>;
|
|
97
|
+
getAllConsents(): Promise<ConsentRecord[]>;
|
|
98
|
+
setDeletionRequest(request: DataDeletionRequest): Promise<void>;
|
|
99
|
+
getDeletionRequest(requestId: string): Promise<DataDeletionRequest | undefined>;
|
|
100
|
+
getDeletionRequestsByUser(userId: string): Promise<DataDeletionRequest[]>;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=gdpr-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gdpr-storage.d.ts","sourceRoot":"","sources":["../../src/security/gdpr-storage.ts"],"names":[],"mappings":"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"}
|