@tantainnovative/ndpr-toolkit 4.0.0 → 5.0.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/dist/chunk-4FXRJH37.js +1 -0
  3. package/dist/{chunk-3XU6FL2I.js → chunk-6YFPDGNB.js} +1 -1
  4. package/dist/{chunk-WMISQDSV.js → chunk-ASEUTU45.js} +1 -1
  5. package/dist/chunk-BRJKIF7E.mjs +1 -0
  6. package/dist/{chunk-XYGGUGTO.js → chunk-CSE36REY.js} +4 -4
  7. package/dist/chunk-DKLJ5DYN.js +1 -0
  8. package/dist/chunk-FRMVSG4N.mjs +1 -0
  9. package/dist/chunk-MAD7QYRK.js +1 -0
  10. package/dist/chunk-NBOJ2KGN.mjs +1 -0
  11. package/dist/chunk-PQ5IPUJN.mjs +1 -0
  12. package/dist/{chunk-BGV2AKT7.mjs → chunk-PSPYIRIF.mjs} +1 -1
  13. package/dist/chunk-QKXGVT2Q.js +1 -0
  14. package/dist/chunk-R2ZZMATR.js +1 -0
  15. package/dist/chunk-R3ZKV2J7.mjs +1 -0
  16. package/dist/chunk-RRVML7CU.mjs +1 -0
  17. package/dist/{chunk-NB6SKG76.mjs → chunk-SBSYHCPK.mjs} +1 -1
  18. package/dist/chunk-TLIHFGIJ.js +1 -0
  19. package/dist/{chunk-5F2IAUWJ.js → chunk-TVA6D6S4.js} +1 -1
  20. package/dist/{chunk-42JPSNVV.mjs → chunk-WPH6CJDL.mjs} +4 -4
  21. package/dist/{chunk-GUERZD4O.mjs → chunk-ZSRO4L3C.mjs} +1 -1
  22. package/dist/consent.d.mts +59 -19
  23. package/dist/consent.d.ts +59 -19
  24. package/dist/consent.js +1 -1
  25. package/dist/consent.mjs +1 -1
  26. package/dist/core.d.mts +124 -69
  27. package/dist/core.d.ts +124 -69
  28. package/dist/core.js +1 -1
  29. package/dist/core.mjs +1 -1
  30. package/dist/cross-border.d.mts +7 -6
  31. package/dist/cross-border.d.ts +7 -6
  32. package/dist/cross-border.js +1 -1
  33. package/dist/cross-border.mjs +1 -1
  34. package/dist/dsr.d.mts +86 -54
  35. package/dist/dsr.d.ts +86 -54
  36. package/dist/dsr.js +1 -1
  37. package/dist/dsr.mjs +1 -1
  38. package/dist/headless.d.mts +23 -9
  39. package/dist/headless.d.ts +23 -9
  40. package/dist/headless.js +1 -1
  41. package/dist/headless.mjs +1 -1
  42. package/dist/hooks.d.mts +23 -9
  43. package/dist/hooks.d.ts +23 -9
  44. package/dist/hooks.js +1 -1
  45. package/dist/hooks.mjs +1 -1
  46. package/dist/index.d.mts +144 -95
  47. package/dist/index.d.ts +144 -95
  48. package/dist/index.js +1 -1
  49. package/dist/index.mjs +1 -1
  50. package/dist/lawful-basis.d.mts +6 -6
  51. package/dist/lawful-basis.d.ts +6 -6
  52. package/dist/lawful-basis.js +1 -1
  53. package/dist/lawful-basis.mjs +1 -1
  54. package/dist/presets.d.mts +87 -2
  55. package/dist/presets.d.ts +87 -2
  56. package/dist/presets.js +1 -1
  57. package/dist/presets.mjs +1 -1
  58. package/dist/ropa-lite.d.mts +4 -1
  59. package/dist/ropa-lite.d.ts +4 -1
  60. package/dist/ropa-lite.js +1 -1
  61. package/dist/ropa-lite.mjs +1 -1
  62. package/dist/ropa.d.mts +16 -16
  63. package/dist/ropa.d.ts +16 -16
  64. package/dist/ropa.js +1 -1
  65. package/dist/ropa.mjs +1 -1
  66. package/dist/server.d.mts +123 -68
  67. package/dist/server.d.ts +123 -68
  68. package/dist/server.js +1 -1
  69. package/dist/server.mjs +1 -1
  70. package/dist/styles.css +18 -16
  71. package/package.json +1 -1
  72. package/dist/chunk-7FXNGGMO.js +0 -1
  73. package/dist/chunk-B46SJB5V.js +0 -1
  74. package/dist/chunk-BL5W472Q.js +0 -1
  75. package/dist/chunk-HOAC5VUF.js +0 -1
  76. package/dist/chunk-IHNAFXDM.mjs +0 -1
  77. package/dist/chunk-O2WEABB3.js +0 -1
  78. package/dist/chunk-OZHUINWS.js +0 -1
  79. package/dist/chunk-PJNKQPQP.mjs +0 -1
  80. package/dist/chunk-RBKFNCGO.mjs +0 -1
  81. package/dist/chunk-VPNK7OID.mjs +0 -1
  82. package/dist/chunk-WKUC65HL.mjs +0 -1
  83. package/dist/chunk-Z2M5VJX2.mjs +0 -1
package/dist/server.d.mts CHANGED
@@ -152,6 +152,10 @@ declare interface ApiAdapterSuccessContext<T = unknown> {
152
152
  */
153
153
  export declare function appendAuditEntry(entry: ConsentAuditEntry, storageKey?: string): void;
154
154
 
155
+ export declare const arabicLocale: Required<{
156
+ [K in keyof NDPRLocale]: Required<NonNullable<NDPRLocale[K]>>;
157
+ }>;
158
+
155
159
  /**
156
160
  * Assemble an ordered, NDPA-aligned array of privacy-policy sections from
157
161
  * a {@link TemplateContext}. This is the canonical "compute the policy"
@@ -1015,7 +1019,7 @@ export declare type DSRStatus = 'pending' | 'awaitingVerification' | 'inProgress
1015
1019
  /**
1016
1020
  * Validated DSR submission shape — matches what `<DSRRequestForm onSubmit>`
1017
1021
  * emits client-side. Use this as the typed parameter for your server-side
1018
- * handler after `validateDsrSubmission` returns `valid: true`.
1022
+ * handler after `validateDsrSubmissionStructured` returns `valid: true`.
1019
1023
  */
1020
1024
  export declare interface DsrSubmissionPayload {
1021
1025
  requestType: string;
@@ -1030,16 +1034,6 @@ export declare interface DsrSubmissionPayload {
1030
1034
  submittedAt: number;
1031
1035
  }
1032
1036
 
1033
- /** Result of validating a raw DSR submission payload. */
1034
- export declare interface DsrSubmissionValidationResult {
1035
- /** True when the payload conforms to the DSR submission contract. */
1036
- valid: boolean;
1037
- /** Field-keyed error messages. Empty when `valid` is true. */
1038
- errors: Record<string, string>;
1039
- /** The narrowed, typed payload — only populated when `valid` is true. */
1040
- data?: DsrSubmissionPayload;
1041
- }
1042
-
1043
1037
  /**
1044
1038
  * Data Subject Rights types aligned with NDPA 2023 Part VI (Sections 34-38)
1045
1039
  * and the related provisions in Part V (Section 27 — information to the data subject)
@@ -1196,15 +1190,33 @@ export declare function exportROPAToCSV(ropa: RecordOfProcessingActivities): str
1196
1190
  export declare function findUnfilledTokens(rendered: string): string[];
1197
1191
 
1198
1192
  /**
1199
- * Formats a DSR request for display or submission
1200
- * @param request The DSR request to format
1201
- * @returns Formatted request data
1193
+ * Format a DSR request for display or submission. Returns the formatted
1194
+ * payload plus a typed `errors` array of `{ field, code, message }` for any
1195
+ * required fields missing from the source request.
1196
+ *
1197
+ * Codes emitted:
1198
+ * - `request_id_required`
1199
+ * - `request_type_required`
1200
+ * - `request_status_required`
1201
+ * - `created_at_required`
1202
+ * - `subject_name_required`
1203
+ * - `subject_email_required`
1202
1204
  */
1203
- export declare function formatDSRRequest(request: DSRRequest): {
1205
+ export declare function formatDSRRequestStructured(request: DSRRequest): FormatDSRRequestStructuredResult;
1206
+
1207
+ /** Result of {@link formatDSRRequestStructured}. */
1208
+ export declare interface FormatDSRRequestStructuredResult {
1209
+ valid: boolean;
1210
+ errors: StructuredValidationError[];
1211
+ /** Formatted request payload — always populated regardless of `valid`. */
1204
1212
  formattedRequest: Record<string, unknown>;
1205
- isValid: boolean;
1206
- validationErrors: string[];
1207
- };
1213
+ /** Narrowed input — populated only on `valid: true`. */
1214
+ data?: DSRRequest;
1215
+ }
1216
+
1217
+ export declare const frenchLocale: Required<{
1218
+ [K in keyof NDPRLocale]: Required<NonNullable<NDPRLocale[K]>>;
1219
+ }>;
1208
1220
 
1209
1221
  /**
1210
1222
  * Generates a summary of all lawful basis documentation across processing activities.
@@ -2302,6 +2314,30 @@ export declare interface StorageAdapter<T = unknown> {
2302
2314
  remove(): void | Promise<void>;
2303
2315
  }
2304
2316
 
2317
+ /**
2318
+ * Single structured validation error with a stable, locale-independent
2319
+ * `code` consumers can switch on programmatically.
2320
+ */
2321
+ export declare interface StructuredValidationError {
2322
+ /** Dot-path of the offending field (e.g. `'timestamp'`, `'dataSubject.email'`, `'options[0].purpose'`). */
2323
+ field: string;
2324
+ /** Stable, snake_case error code — safe to switch on across locales. */
2325
+ code: string;
2326
+ /** Human-readable English message — informational only; do not regex-match. */
2327
+ message: string;
2328
+ }
2329
+
2330
+ /**
2331
+ * Result of a structured validator. `errors` is an array (one entry per
2332
+ * failed rule). `data` is the narrowed, typed payload, only populated on
2333
+ * `valid: true`.
2334
+ */
2335
+ export declare interface StructuredValidationResult<T> {
2336
+ valid: boolean;
2337
+ errors: StructuredValidationError[];
2338
+ data?: T;
2339
+ }
2340
+
2305
2341
  /** Full context used to generate an adaptive privacy policy. */
2306
2342
  export declare interface TemplateContext {
2307
2343
  /** Organisation details, extended with industry and size. */
@@ -2441,66 +2477,43 @@ export declare const UNFILLED_PREFIX = "\u00ABTODO: ";
2441
2477
  export declare const UNFILLED_SUFFIX = "\u00BB";
2442
2478
 
2443
2479
  /**
2444
- * Validates consent settings to ensure they meet NDPA requirements
2445
- * @param settings The consent settings to validate
2446
- * @returns An object containing validation result and any error messages
2447
- */
2448
- export declare function validateConsent(settings: ConsentSettings): {
2449
- valid: boolean;
2450
- errors: string[];
2451
- };
2452
-
2453
- /**
2454
- * Validates that consent options meet NDPA Section 26 requirements.
2455
- * Each consent option must specify a purpose for which data will be processed,
2456
- * as consent must be specific and informed per the Nigeria Data Protection Act.
2457
- * @param options The consent options to validate
2458
- * @returns An object containing validation result and any error messages
2480
+ * Validates consent options against NDPA Section 26 requirements. Each option
2481
+ * is checked for a non-empty `purpose`. Failing options are reported with
2482
+ * `field: 'options[i].purpose'` so consumers can map errors back to the
2483
+ * originating option index.
2484
+ *
2485
+ * Codes emitted:
2486
+ * - `options_required` — empty / missing options array
2487
+ * - `purpose_required` — single option missing a purpose
2459
2488
  */
2460
- export declare function validateConsentOptions(options: ConsentOption[]): {
2461
- valid: boolean;
2462
- errors: string[];
2463
- };
2489
+ export declare function validateConsentOptionsStructured(options: ConsentOption[]): StructuredValidationResult<ConsentOption[]>;
2464
2490
 
2465
2491
  /**
2466
- * Validate a raw DSR submission payload against the same rules
2467
- * `<DSRRequestForm />` enforces client-side. Designed to be called from a
2468
- * server-side handler (Next.js Route Handler, NestJS controller, Express
2469
- * middleware, Cloudflare Worker) so client and server stay in sync without
2470
- * the consumer hand-rolling zod / class-validator schemas.
2492
+ * Validates consent settings against NDPA requirements. Returns structured
2493
+ * `{ field, code, message }[]` errors so consumers can switch on `code`
2494
+ * across locales without regex-matching English strings.
2471
2495
  *
2472
- * Defensive — accepts `unknown` and narrows. Safe to call directly on
2473
- * `await request.json()`.
2496
+ * Codes emitted:
2497
+ * - `consents_required`
2498
+ * - `timestamp_required`
2499
+ * - `timestamp_invalid`
2500
+ * - `version_required`
2501
+ * - `method_required`
2502
+ * - `has_interacted_required`
2503
+ * - `consent_stale`
2474
2504
  *
2475
- * @example **Next.js Route Handler**
2505
+ * @example
2476
2506
  * ```ts
2477
- * // app/api/dsr/route.ts
2478
- * import { validateDsrSubmission } from '@tantainnovative/ndpr-toolkit/server';
2479
- *
2480
- * export async function POST(req: Request) {
2481
- * const { valid, errors, data } = validateDsrSubmission(await req.json());
2482
- * if (!valid) return Response.json({ errors }, { status: 422 });
2483
- * // `data` is the typed DsrSubmissionPayload
2484
- * await dsrStore.create(data);
2485
- * return Response.json({ ok: true }, { status: 201 });
2507
+ * const { valid, errors, data } = validateConsentStructured(settings);
2508
+ * if (!valid) {
2509
+ * const stale = errors.find((e) => e.code === 'consent_stale');
2510
+ * if (stale) showRefreshBanner();
2486
2511
  * }
2487
2512
  * ```
2488
- *
2489
- * @example **Lock to specific request types**
2490
- * ```ts
2491
- * validateDsrSubmission(payload, {
2492
- * allowedRequestTypes: ['access', 'erasure', 'rectification'],
2493
- * });
2494
- * ```
2495
- *
2496
- * @example **Skip identity verification (e.g. authenticated session)**
2497
- * ```ts
2498
- * validateDsrSubmission(payload, { requireIdentityVerification: false });
2499
- * ```
2500
2513
  */
2501
- export declare function validateDsrSubmission(payload: unknown, options?: ValidateDsrSubmissionOptions): DsrSubmissionValidationResult;
2514
+ export declare function validateConsentStructured(settings: ConsentSettings): StructuredValidationResult<ConsentSettings>;
2502
2515
 
2503
- /** Options for {@link validateDsrSubmission}. */
2516
+ /** Options for {@link validateDsrSubmissionStructured}. */
2504
2517
  export declare interface ValidateDsrSubmissionOptions {
2505
2518
  /**
2506
2519
  * Whether the data subject is required to provide an identifier
@@ -2517,6 +2530,48 @@ export declare interface ValidateDsrSubmissionOptions {
2517
2530
  allowedRequestTypes?: string[];
2518
2531
  }
2519
2532
 
2533
+ /**
2534
+ * Validate a raw DSR submission payload against the same rules
2535
+ * `<DSRRequestForm />` enforces client-side. Designed to be called from a
2536
+ * server-side handler (Next.js Route Handler, NestJS controller, Express
2537
+ * middleware, Cloudflare Worker) so client and server stay in sync without
2538
+ * the consumer hand-rolling zod / class-validator schemas.
2539
+ *
2540
+ * Defensive — accepts `unknown` and narrows. Safe to call directly on
2541
+ * `await request.json()`. Returns `{ field, code, message }[]` errors so
2542
+ * callers can switch on `code` programmatically across locales.
2543
+ *
2544
+ * Codes emitted:
2545
+ * - `payload_not_object`
2546
+ * - `request_type_required`
2547
+ * - `request_type_not_allowed`
2548
+ * - `data_subject_required`
2549
+ * - `full_name_required`
2550
+ * - `email_required`
2551
+ * - `email_invalid_format`
2552
+ * - `phone_invalid_type`
2553
+ * - `identifier_type_required`
2554
+ * - `identifier_value_required`
2555
+ * - `submitted_at_invalid`
2556
+ * - `additional_info_invalid_type`
2557
+ * - `payload_final_narrowing_failed`
2558
+ *
2559
+ * @example **Next.js Route Handler**
2560
+ * ```ts
2561
+ * import { validateDsrSubmissionStructured } from '@tantainnovative/ndpr-toolkit/server';
2562
+ *
2563
+ * export async function POST(req: Request) {
2564
+ * const { valid, errors, data } = validateDsrSubmissionStructured(await req.json());
2565
+ * if (!valid) {
2566
+ * return Response.json({ errors }, { status: 422 });
2567
+ * }
2568
+ * await dsrStore.create(data);
2569
+ * return Response.json({ ok: true }, { status: 201 });
2570
+ * }
2571
+ * ```
2572
+ */
2573
+ export declare function validateDsrSubmissionStructured(payload: unknown, options?: ValidateDsrSubmissionOptions): StructuredValidationResult<DsrSubmissionPayload>;
2574
+
2520
2575
  /**
2521
2576
  * Validates that all required fields are present on a processing activity
2522
2577
  * and that the lawful basis is properly documented.
package/dist/server.d.ts CHANGED
@@ -152,6 +152,10 @@ declare interface ApiAdapterSuccessContext<T = unknown> {
152
152
  */
153
153
  export declare function appendAuditEntry(entry: ConsentAuditEntry, storageKey?: string): void;
154
154
 
155
+ export declare const arabicLocale: Required<{
156
+ [K in keyof NDPRLocale]: Required<NonNullable<NDPRLocale[K]>>;
157
+ }>;
158
+
155
159
  /**
156
160
  * Assemble an ordered, NDPA-aligned array of privacy-policy sections from
157
161
  * a {@link TemplateContext}. This is the canonical "compute the policy"
@@ -1015,7 +1019,7 @@ export declare type DSRStatus = 'pending' | 'awaitingVerification' | 'inProgress
1015
1019
  /**
1016
1020
  * Validated DSR submission shape — matches what `<DSRRequestForm onSubmit>`
1017
1021
  * emits client-side. Use this as the typed parameter for your server-side
1018
- * handler after `validateDsrSubmission` returns `valid: true`.
1022
+ * handler after `validateDsrSubmissionStructured` returns `valid: true`.
1019
1023
  */
1020
1024
  export declare interface DsrSubmissionPayload {
1021
1025
  requestType: string;
@@ -1030,16 +1034,6 @@ export declare interface DsrSubmissionPayload {
1030
1034
  submittedAt: number;
1031
1035
  }
1032
1036
 
1033
- /** Result of validating a raw DSR submission payload. */
1034
- export declare interface DsrSubmissionValidationResult {
1035
- /** True when the payload conforms to the DSR submission contract. */
1036
- valid: boolean;
1037
- /** Field-keyed error messages. Empty when `valid` is true. */
1038
- errors: Record<string, string>;
1039
- /** The narrowed, typed payload — only populated when `valid` is true. */
1040
- data?: DsrSubmissionPayload;
1041
- }
1042
-
1043
1037
  /**
1044
1038
  * Data Subject Rights types aligned with NDPA 2023 Part VI (Sections 34-38)
1045
1039
  * and the related provisions in Part V (Section 27 — information to the data subject)
@@ -1196,15 +1190,33 @@ export declare function exportROPAToCSV(ropa: RecordOfProcessingActivities): str
1196
1190
  export declare function findUnfilledTokens(rendered: string): string[];
1197
1191
 
1198
1192
  /**
1199
- * Formats a DSR request for display or submission
1200
- * @param request The DSR request to format
1201
- * @returns Formatted request data
1193
+ * Format a DSR request for display or submission. Returns the formatted
1194
+ * payload plus a typed `errors` array of `{ field, code, message }` for any
1195
+ * required fields missing from the source request.
1196
+ *
1197
+ * Codes emitted:
1198
+ * - `request_id_required`
1199
+ * - `request_type_required`
1200
+ * - `request_status_required`
1201
+ * - `created_at_required`
1202
+ * - `subject_name_required`
1203
+ * - `subject_email_required`
1202
1204
  */
1203
- export declare function formatDSRRequest(request: DSRRequest): {
1205
+ export declare function formatDSRRequestStructured(request: DSRRequest): FormatDSRRequestStructuredResult;
1206
+
1207
+ /** Result of {@link formatDSRRequestStructured}. */
1208
+ export declare interface FormatDSRRequestStructuredResult {
1209
+ valid: boolean;
1210
+ errors: StructuredValidationError[];
1211
+ /** Formatted request payload — always populated regardless of `valid`. */
1204
1212
  formattedRequest: Record<string, unknown>;
1205
- isValid: boolean;
1206
- validationErrors: string[];
1207
- };
1213
+ /** Narrowed input — populated only on `valid: true`. */
1214
+ data?: DSRRequest;
1215
+ }
1216
+
1217
+ export declare const frenchLocale: Required<{
1218
+ [K in keyof NDPRLocale]: Required<NonNullable<NDPRLocale[K]>>;
1219
+ }>;
1208
1220
 
1209
1221
  /**
1210
1222
  * Generates a summary of all lawful basis documentation across processing activities.
@@ -2302,6 +2314,30 @@ export declare interface StorageAdapter<T = unknown> {
2302
2314
  remove(): void | Promise<void>;
2303
2315
  }
2304
2316
 
2317
+ /**
2318
+ * Single structured validation error with a stable, locale-independent
2319
+ * `code` consumers can switch on programmatically.
2320
+ */
2321
+ export declare interface StructuredValidationError {
2322
+ /** Dot-path of the offending field (e.g. `'timestamp'`, `'dataSubject.email'`, `'options[0].purpose'`). */
2323
+ field: string;
2324
+ /** Stable, snake_case error code — safe to switch on across locales. */
2325
+ code: string;
2326
+ /** Human-readable English message — informational only; do not regex-match. */
2327
+ message: string;
2328
+ }
2329
+
2330
+ /**
2331
+ * Result of a structured validator. `errors` is an array (one entry per
2332
+ * failed rule). `data` is the narrowed, typed payload, only populated on
2333
+ * `valid: true`.
2334
+ */
2335
+ export declare interface StructuredValidationResult<T> {
2336
+ valid: boolean;
2337
+ errors: StructuredValidationError[];
2338
+ data?: T;
2339
+ }
2340
+
2305
2341
  /** Full context used to generate an adaptive privacy policy. */
2306
2342
  export declare interface TemplateContext {
2307
2343
  /** Organisation details, extended with industry and size. */
@@ -2441,66 +2477,43 @@ export declare const UNFILLED_PREFIX = "\u00ABTODO: ";
2441
2477
  export declare const UNFILLED_SUFFIX = "\u00BB";
2442
2478
 
2443
2479
  /**
2444
- * Validates consent settings to ensure they meet NDPA requirements
2445
- * @param settings The consent settings to validate
2446
- * @returns An object containing validation result and any error messages
2447
- */
2448
- export declare function validateConsent(settings: ConsentSettings): {
2449
- valid: boolean;
2450
- errors: string[];
2451
- };
2452
-
2453
- /**
2454
- * Validates that consent options meet NDPA Section 26 requirements.
2455
- * Each consent option must specify a purpose for which data will be processed,
2456
- * as consent must be specific and informed per the Nigeria Data Protection Act.
2457
- * @param options The consent options to validate
2458
- * @returns An object containing validation result and any error messages
2480
+ * Validates consent options against NDPA Section 26 requirements. Each option
2481
+ * is checked for a non-empty `purpose`. Failing options are reported with
2482
+ * `field: 'options[i].purpose'` so consumers can map errors back to the
2483
+ * originating option index.
2484
+ *
2485
+ * Codes emitted:
2486
+ * - `options_required` — empty / missing options array
2487
+ * - `purpose_required` — single option missing a purpose
2459
2488
  */
2460
- export declare function validateConsentOptions(options: ConsentOption[]): {
2461
- valid: boolean;
2462
- errors: string[];
2463
- };
2489
+ export declare function validateConsentOptionsStructured(options: ConsentOption[]): StructuredValidationResult<ConsentOption[]>;
2464
2490
 
2465
2491
  /**
2466
- * Validate a raw DSR submission payload against the same rules
2467
- * `<DSRRequestForm />` enforces client-side. Designed to be called from a
2468
- * server-side handler (Next.js Route Handler, NestJS controller, Express
2469
- * middleware, Cloudflare Worker) so client and server stay in sync without
2470
- * the consumer hand-rolling zod / class-validator schemas.
2492
+ * Validates consent settings against NDPA requirements. Returns structured
2493
+ * `{ field, code, message }[]` errors so consumers can switch on `code`
2494
+ * across locales without regex-matching English strings.
2471
2495
  *
2472
- * Defensive — accepts `unknown` and narrows. Safe to call directly on
2473
- * `await request.json()`.
2496
+ * Codes emitted:
2497
+ * - `consents_required`
2498
+ * - `timestamp_required`
2499
+ * - `timestamp_invalid`
2500
+ * - `version_required`
2501
+ * - `method_required`
2502
+ * - `has_interacted_required`
2503
+ * - `consent_stale`
2474
2504
  *
2475
- * @example **Next.js Route Handler**
2505
+ * @example
2476
2506
  * ```ts
2477
- * // app/api/dsr/route.ts
2478
- * import { validateDsrSubmission } from '@tantainnovative/ndpr-toolkit/server';
2479
- *
2480
- * export async function POST(req: Request) {
2481
- * const { valid, errors, data } = validateDsrSubmission(await req.json());
2482
- * if (!valid) return Response.json({ errors }, { status: 422 });
2483
- * // `data` is the typed DsrSubmissionPayload
2484
- * await dsrStore.create(data);
2485
- * return Response.json({ ok: true }, { status: 201 });
2507
+ * const { valid, errors, data } = validateConsentStructured(settings);
2508
+ * if (!valid) {
2509
+ * const stale = errors.find((e) => e.code === 'consent_stale');
2510
+ * if (stale) showRefreshBanner();
2486
2511
  * }
2487
2512
  * ```
2488
- *
2489
- * @example **Lock to specific request types**
2490
- * ```ts
2491
- * validateDsrSubmission(payload, {
2492
- * allowedRequestTypes: ['access', 'erasure', 'rectification'],
2493
- * });
2494
- * ```
2495
- *
2496
- * @example **Skip identity verification (e.g. authenticated session)**
2497
- * ```ts
2498
- * validateDsrSubmission(payload, { requireIdentityVerification: false });
2499
- * ```
2500
2513
  */
2501
- export declare function validateDsrSubmission(payload: unknown, options?: ValidateDsrSubmissionOptions): DsrSubmissionValidationResult;
2514
+ export declare function validateConsentStructured(settings: ConsentSettings): StructuredValidationResult<ConsentSettings>;
2502
2515
 
2503
- /** Options for {@link validateDsrSubmission}. */
2516
+ /** Options for {@link validateDsrSubmissionStructured}. */
2504
2517
  export declare interface ValidateDsrSubmissionOptions {
2505
2518
  /**
2506
2519
  * Whether the data subject is required to provide an identifier
@@ -2517,6 +2530,48 @@ export declare interface ValidateDsrSubmissionOptions {
2517
2530
  allowedRequestTypes?: string[];
2518
2531
  }
2519
2532
 
2533
+ /**
2534
+ * Validate a raw DSR submission payload against the same rules
2535
+ * `<DSRRequestForm />` enforces client-side. Designed to be called from a
2536
+ * server-side handler (Next.js Route Handler, NestJS controller, Express
2537
+ * middleware, Cloudflare Worker) so client and server stay in sync without
2538
+ * the consumer hand-rolling zod / class-validator schemas.
2539
+ *
2540
+ * Defensive — accepts `unknown` and narrows. Safe to call directly on
2541
+ * `await request.json()`. Returns `{ field, code, message }[]` errors so
2542
+ * callers can switch on `code` programmatically across locales.
2543
+ *
2544
+ * Codes emitted:
2545
+ * - `payload_not_object`
2546
+ * - `request_type_required`
2547
+ * - `request_type_not_allowed`
2548
+ * - `data_subject_required`
2549
+ * - `full_name_required`
2550
+ * - `email_required`
2551
+ * - `email_invalid_format`
2552
+ * - `phone_invalid_type`
2553
+ * - `identifier_type_required`
2554
+ * - `identifier_value_required`
2555
+ * - `submitted_at_invalid`
2556
+ * - `additional_info_invalid_type`
2557
+ * - `payload_final_narrowing_failed`
2558
+ *
2559
+ * @example **Next.js Route Handler**
2560
+ * ```ts
2561
+ * import { validateDsrSubmissionStructured } from '@tantainnovative/ndpr-toolkit/server';
2562
+ *
2563
+ * export async function POST(req: Request) {
2564
+ * const { valid, errors, data } = validateDsrSubmissionStructured(await req.json());
2565
+ * if (!valid) {
2566
+ * return Response.json({ errors }, { status: 422 });
2567
+ * }
2568
+ * await dsrStore.create(data);
2569
+ * return Response.json({ ok: true }, { status: 201 });
2570
+ * }
2571
+ * ```
2572
+ */
2573
+ export declare function validateDsrSubmissionStructured(payload: unknown, options?: ValidateDsrSubmissionOptions): StructuredValidationResult<DsrSubmissionPayload>;
2574
+
2520
2575
  /**
2521
2576
  * Validates that all required fields are present on a processing activity
2522
2577
  * and that the lawful basis is properly documented.
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- 'use strict';var chunkR3CU7DTT_js=require('./chunk-R3CU7DTT.js'),chunk3XU6FL2I_js=require('./chunk-3XU6FL2I.js'),chunkNUOHT3LO_js=require('./chunk-NUOHT3LO.js'),chunkJS7SYL5P_js=require('./chunk-JS7SYL5P.js'),chunkRDALAH3Y_js=require('./chunk-RDALAH3Y.js'),chunk3YTAOT5O_js=require('./chunk-3YTAOT5O.js'),chunkD2ZKDQVL_js=require('./chunk-D2ZKDQVL.js'),chunk6LJHLE6G_js=require('./chunk-6LJHLE6G.js'),chunkYFBDJ4FH_js=require('./chunk-YFBDJ4FH.js'),chunkWZYCBW2R_js=require('./chunk-WZYCBW2R.js'),chunk4CVBQC66_js=require('./chunk-4CVBQC66.js'),chunk3IA3KDII_js=require('./chunk-3IA3KDII.js'),chunkC2KEXHRX_js=require('./chunk-C2KEXHRX.js'),chunkB46SJB5V_js=require('./chunk-B46SJB5V.js'),chunkUXUMYP4L_js=require('./chunk-UXUMYP4L.js'),chunkOZHUINWS_js=require('./chunk-OZHUINWS.js'),chunkTQZWJGJ2_js=require('./chunk-TQZWJGJ2.js'),chunkZVOIR4QH_js=require('./chunk-ZVOIR4QH.js'),chunkTTMGFC6C_js=require('./chunk-TTMGFC6C.js'),chunkVWED6UTN_js=require('./chunk-VWED6UTN.js');require('./chunk-RFPLZDIO.js');Object.defineProperty(exports,"apiAdapter",{enumerable:true,get:function(){return chunkR3CU7DTT_js.a}});Object.defineProperty(exports,"composeAdapters",{enumerable:true,get:function(){return chunkR3CU7DTT_js.c}});Object.defineProperty(exports,"memoryAdapter",{enumerable:true,get:function(){return chunkR3CU7DTT_js.b}});Object.defineProperty(exports,"hausaLocale",{enumerable:true,get:function(){return chunk3XU6FL2I_js.c}});Object.defineProperty(exports,"igboLocale",{enumerable:true,get:function(){return chunk3XU6FL2I_js.b}});Object.defineProperty(exports,"pidginLocale",{enumerable:true,get:function(){return chunk3XU6FL2I_js.d}});Object.defineProperty(exports,"yorubaLocale",{enumerable:true,get:function(){return chunk3XU6FL2I_js.a}});Object.defineProperty(exports,"ORG_POLICY_TEMPLATE_REGISTRY",{enumerable:true,get:function(){return chunkNUOHT3LO_js.a}});Object.defineProperty(exports,"createOrgTemplate",{enumerable:true,get:function(){return chunkNUOHT3LO_js.b}});Object.defineProperty(exports,"templateContextFor",{enumerable:true,get:function(){return chunkNUOHT3LO_js.b}});Object.defineProperty(exports,"exportDOCX",{enumerable:true,get:function(){return chunkJS7SYL5P_js.d}});Object.defineProperty(exports,"exportHTML",{enumerable:true,get:function(){return chunkJS7SYL5P_js.a}});Object.defineProperty(exports,"exportMarkdown",{enumerable:true,get:function(){return chunkJS7SYL5P_js.b}});Object.defineProperty(exports,"exportPDF",{enumerable:true,get:function(){return chunkJS7SYL5P_js.c}});Object.defineProperty(exports,"getComplianceScore",{enumerable:true,get:function(){return chunkRDALAH3Y_js.a}});Object.defineProperty(exports,"calculateBreachSeverity",{enumerable:true,get:function(){return chunk3YTAOT5O_js.a}});Object.defineProperty(exports,"DEFAULT_POLICY_SECTIONS",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.c}});Object.defineProperty(exports,"DEFAULT_POLICY_VARIABLES",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.d}});Object.defineProperty(exports,"createBusinessPolicyTemplate",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.e}});Object.defineProperty(exports,"findUnfilledTokens",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.a}});Object.defineProperty(exports,"generatePolicyText",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.b}});Object.defineProperty(exports,"DEFAULT_DATA_CATEGORIES",{enumerable:true,get:function(){return chunk6LJHLE6G_js.d}});Object.defineProperty(exports,"UNFILLED_PREFIX",{enumerable:true,get:function(){return chunk6LJHLE6G_js.a}});Object.defineProperty(exports,"UNFILLED_SUFFIX",{enumerable:true,get:function(){return chunk6LJHLE6G_js.b}});Object.defineProperty(exports,"assemblePolicy",{enumerable:true,get:function(){return chunk6LJHLE6G_js.c}});Object.defineProperty(exports,"createDefaultContext",{enumerable:true,get:function(){return chunk6LJHLE6G_js.e}});Object.defineProperty(exports,"evaluatePolicyCompliance",{enumerable:true,get:function(){return chunk6LJHLE6G_js.f}});Object.defineProperty(exports,"assessTransferRisk",{enumerable:true,get:function(){return chunkYFBDJ4FH_js.h}});Object.defineProperty(exports,"getTransferMechanismDescription",{enumerable:true,get:function(){return chunkYFBDJ4FH_js.f}});Object.defineProperty(exports,"isNDPCApprovalRequired",{enumerable:true,get:function(){return chunkYFBDJ4FH_js.e}});Object.defineProperty(exports,"validateTransfer",{enumerable:true,get:function(){return chunkYFBDJ4FH_js.g}});Object.defineProperty(exports,"assessComplianceGaps",{enumerable:true,get:function(){return chunkWZYCBW2R_js.c}});Object.defineProperty(exports,"generateLawfulBasisSummary",{enumerable:true,get:function(){return chunkWZYCBW2R_js.d}});Object.defineProperty(exports,"getLawfulBasisDescription",{enumerable:true,get:function(){return chunkWZYCBW2R_js.b}});Object.defineProperty(exports,"validateProcessingActivity",{enumerable:true,get:function(){return chunkWZYCBW2R_js.a}});Object.defineProperty(exports,"exportROPAToCSV",{enumerable:true,get:function(){return chunk4CVBQC66_js.c}});Object.defineProperty(exports,"generateROPASummary",{enumerable:true,get:function(){return chunk4CVBQC66_js.b}});Object.defineProperty(exports,"identifyComplianceGaps",{enumerable:true,get:function(){return chunk4CVBQC66_js.d}});Object.defineProperty(exports,"validateProcessingRecord",{enumerable:true,get:function(){return chunk4CVBQC66_js.a}});Object.defineProperty(exports,"appendAuditEntry",{enumerable:true,get:function(){return chunk3IA3KDII_js.c}});Object.defineProperty(exports,"createAuditEntry",{enumerable:true,get:function(){return chunk3IA3KDII_js.a}});Object.defineProperty(exports,"getAuditLog",{enumerable:true,get:function(){return chunk3IA3KDII_js.b}});Object.defineProperty(exports,"cookieAdapter",{enumerable:true,get:function(){return chunkC2KEXHRX_js.b}});Object.defineProperty(exports,"sessionStorageAdapter",{enumerable:true,get:function(){return chunkC2KEXHRX_js.a}});Object.defineProperty(exports,"validateConsent",{enumerable:true,get:function(){return chunkB46SJB5V_js.a}});Object.defineProperty(exports,"validateConsentOptions",{enumerable:true,get:function(){return chunkB46SJB5V_js.b}});Object.defineProperty(exports,"sanitizeInput",{enumerable:true,get:function(){return chunkUXUMYP4L_js.a}});Object.defineProperty(exports,"formatDSRRequest",{enumerable:true,get:function(){return chunkOZHUINWS_js.b}});Object.defineProperty(exports,"validateDsrSubmission",{enumerable:true,get:function(){return chunkOZHUINWS_js.a}});Object.defineProperty(exports,"assessDPIARisk",{enumerable:true,get:function(){return chunkTQZWJGJ2_js.a}});Object.defineProperty(exports,"LEGAL_DISCLAIMER_LONG",{enumerable:true,get:function(){return chunkZVOIR4QH_js.b}});Object.defineProperty(exports,"LEGAL_DISCLAIMER_SHORT",{enumerable:true,get:function(){return chunkZVOIR4QH_js.a}});Object.defineProperty(exports,"legalDisclaimerBlock",{enumerable:true,get:function(){return chunkZVOIR4QH_js.c}});Object.defineProperty(exports,"defaultLocale",{enumerable:true,get:function(){return chunkTTMGFC6C_js.a}});Object.defineProperty(exports,"mergeLocale",{enumerable:true,get:function(){return chunkTTMGFC6C_js.b}});Object.defineProperty(exports,"localStorageAdapter",{enumerable:true,get:function(){return chunkVWED6UTN_js.a}});
1
+ 'use strict';var chunkR3CU7DTT_js=require('./chunk-R3CU7DTT.js'),chunk6YFPDGNB_js=require('./chunk-6YFPDGNB.js'),chunkNUOHT3LO_js=require('./chunk-NUOHT3LO.js'),chunkJS7SYL5P_js=require('./chunk-JS7SYL5P.js'),chunkRDALAH3Y_js=require('./chunk-RDALAH3Y.js'),chunk3YTAOT5O_js=require('./chunk-3YTAOT5O.js'),chunkD2ZKDQVL_js=require('./chunk-D2ZKDQVL.js'),chunk6LJHLE6G_js=require('./chunk-6LJHLE6G.js'),chunkYFBDJ4FH_js=require('./chunk-YFBDJ4FH.js'),chunkWZYCBW2R_js=require('./chunk-WZYCBW2R.js'),chunk4CVBQC66_js=require('./chunk-4CVBQC66.js'),chunk3IA3KDII_js=require('./chunk-3IA3KDII.js'),chunkC2KEXHRX_js=require('./chunk-C2KEXHRX.js'),chunkDKLJ5DYN_js=require('./chunk-DKLJ5DYN.js'),chunkUXUMYP4L_js=require('./chunk-UXUMYP4L.js'),chunkR2ZZMATR_js=require('./chunk-R2ZZMATR.js'),chunkTQZWJGJ2_js=require('./chunk-TQZWJGJ2.js'),chunkZVOIR4QH_js=require('./chunk-ZVOIR4QH.js'),chunkTTMGFC6C_js=require('./chunk-TTMGFC6C.js'),chunkVWED6UTN_js=require('./chunk-VWED6UTN.js');require('./chunk-RFPLZDIO.js');Object.defineProperty(exports,"apiAdapter",{enumerable:true,get:function(){return chunkR3CU7DTT_js.a}});Object.defineProperty(exports,"composeAdapters",{enumerable:true,get:function(){return chunkR3CU7DTT_js.c}});Object.defineProperty(exports,"memoryAdapter",{enumerable:true,get:function(){return chunkR3CU7DTT_js.b}});Object.defineProperty(exports,"arabicLocale",{enumerable:true,get:function(){return chunk6YFPDGNB_js.e}});Object.defineProperty(exports,"frenchLocale",{enumerable:true,get:function(){return chunk6YFPDGNB_js.f}});Object.defineProperty(exports,"hausaLocale",{enumerable:true,get:function(){return chunk6YFPDGNB_js.c}});Object.defineProperty(exports,"igboLocale",{enumerable:true,get:function(){return chunk6YFPDGNB_js.b}});Object.defineProperty(exports,"pidginLocale",{enumerable:true,get:function(){return chunk6YFPDGNB_js.d}});Object.defineProperty(exports,"yorubaLocale",{enumerable:true,get:function(){return chunk6YFPDGNB_js.a}});Object.defineProperty(exports,"ORG_POLICY_TEMPLATE_REGISTRY",{enumerable:true,get:function(){return chunkNUOHT3LO_js.a}});Object.defineProperty(exports,"createOrgTemplate",{enumerable:true,get:function(){return chunkNUOHT3LO_js.b}});Object.defineProperty(exports,"templateContextFor",{enumerable:true,get:function(){return chunkNUOHT3LO_js.b}});Object.defineProperty(exports,"exportDOCX",{enumerable:true,get:function(){return chunkJS7SYL5P_js.d}});Object.defineProperty(exports,"exportHTML",{enumerable:true,get:function(){return chunkJS7SYL5P_js.a}});Object.defineProperty(exports,"exportMarkdown",{enumerable:true,get:function(){return chunkJS7SYL5P_js.b}});Object.defineProperty(exports,"exportPDF",{enumerable:true,get:function(){return chunkJS7SYL5P_js.c}});Object.defineProperty(exports,"getComplianceScore",{enumerable:true,get:function(){return chunkRDALAH3Y_js.a}});Object.defineProperty(exports,"calculateBreachSeverity",{enumerable:true,get:function(){return chunk3YTAOT5O_js.a}});Object.defineProperty(exports,"DEFAULT_POLICY_SECTIONS",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.c}});Object.defineProperty(exports,"DEFAULT_POLICY_VARIABLES",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.d}});Object.defineProperty(exports,"createBusinessPolicyTemplate",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.e}});Object.defineProperty(exports,"findUnfilledTokens",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.a}});Object.defineProperty(exports,"generatePolicyText",{enumerable:true,get:function(){return chunkD2ZKDQVL_js.b}});Object.defineProperty(exports,"DEFAULT_DATA_CATEGORIES",{enumerable:true,get:function(){return chunk6LJHLE6G_js.d}});Object.defineProperty(exports,"UNFILLED_PREFIX",{enumerable:true,get:function(){return chunk6LJHLE6G_js.a}});Object.defineProperty(exports,"UNFILLED_SUFFIX",{enumerable:true,get:function(){return chunk6LJHLE6G_js.b}});Object.defineProperty(exports,"assemblePolicy",{enumerable:true,get:function(){return chunk6LJHLE6G_js.c}});Object.defineProperty(exports,"createDefaultContext",{enumerable:true,get:function(){return chunk6LJHLE6G_js.e}});Object.defineProperty(exports,"evaluatePolicyCompliance",{enumerable:true,get:function(){return chunk6LJHLE6G_js.f}});Object.defineProperty(exports,"assessTransferRisk",{enumerable:true,get:function(){return chunkYFBDJ4FH_js.h}});Object.defineProperty(exports,"getTransferMechanismDescription",{enumerable:true,get:function(){return chunkYFBDJ4FH_js.f}});Object.defineProperty(exports,"isNDPCApprovalRequired",{enumerable:true,get:function(){return chunkYFBDJ4FH_js.e}});Object.defineProperty(exports,"validateTransfer",{enumerable:true,get:function(){return chunkYFBDJ4FH_js.g}});Object.defineProperty(exports,"assessComplianceGaps",{enumerable:true,get:function(){return chunkWZYCBW2R_js.c}});Object.defineProperty(exports,"generateLawfulBasisSummary",{enumerable:true,get:function(){return chunkWZYCBW2R_js.d}});Object.defineProperty(exports,"getLawfulBasisDescription",{enumerable:true,get:function(){return chunkWZYCBW2R_js.b}});Object.defineProperty(exports,"validateProcessingActivity",{enumerable:true,get:function(){return chunkWZYCBW2R_js.a}});Object.defineProperty(exports,"exportROPAToCSV",{enumerable:true,get:function(){return chunk4CVBQC66_js.c}});Object.defineProperty(exports,"generateROPASummary",{enumerable:true,get:function(){return chunk4CVBQC66_js.b}});Object.defineProperty(exports,"identifyComplianceGaps",{enumerable:true,get:function(){return chunk4CVBQC66_js.d}});Object.defineProperty(exports,"validateProcessingRecord",{enumerable:true,get:function(){return chunk4CVBQC66_js.a}});Object.defineProperty(exports,"appendAuditEntry",{enumerable:true,get:function(){return chunk3IA3KDII_js.c}});Object.defineProperty(exports,"createAuditEntry",{enumerable:true,get:function(){return chunk3IA3KDII_js.a}});Object.defineProperty(exports,"getAuditLog",{enumerable:true,get:function(){return chunk3IA3KDII_js.b}});Object.defineProperty(exports,"cookieAdapter",{enumerable:true,get:function(){return chunkC2KEXHRX_js.b}});Object.defineProperty(exports,"sessionStorageAdapter",{enumerable:true,get:function(){return chunkC2KEXHRX_js.a}});Object.defineProperty(exports,"validateConsentOptionsStructured",{enumerable:true,get:function(){return chunkDKLJ5DYN_js.b}});Object.defineProperty(exports,"validateConsentStructured",{enumerable:true,get:function(){return chunkDKLJ5DYN_js.a}});Object.defineProperty(exports,"sanitizeInput",{enumerable:true,get:function(){return chunkUXUMYP4L_js.a}});Object.defineProperty(exports,"formatDSRRequestStructured",{enumerable:true,get:function(){return chunkR2ZZMATR_js.b}});Object.defineProperty(exports,"validateDsrSubmissionStructured",{enumerable:true,get:function(){return chunkR2ZZMATR_js.a}});Object.defineProperty(exports,"assessDPIARisk",{enumerable:true,get:function(){return chunkTQZWJGJ2_js.a}});Object.defineProperty(exports,"LEGAL_DISCLAIMER_LONG",{enumerable:true,get:function(){return chunkZVOIR4QH_js.b}});Object.defineProperty(exports,"LEGAL_DISCLAIMER_SHORT",{enumerable:true,get:function(){return chunkZVOIR4QH_js.a}});Object.defineProperty(exports,"legalDisclaimerBlock",{enumerable:true,get:function(){return chunkZVOIR4QH_js.c}});Object.defineProperty(exports,"defaultLocale",{enumerable:true,get:function(){return chunkTTMGFC6C_js.a}});Object.defineProperty(exports,"mergeLocale",{enumerable:true,get:function(){return chunkTTMGFC6C_js.b}});Object.defineProperty(exports,"localStorageAdapter",{enumerable:true,get:function(){return chunkVWED6UTN_js.a}});
package/dist/server.mjs CHANGED
@@ -1 +1 @@
1
- export{a as apiAdapter,c as composeAdapters,b as memoryAdapter}from'./chunk-7PMPKVY3.mjs';export{c as hausaLocale,b as igboLocale,d as pidginLocale,a as yorubaLocale}from'./chunk-BGV2AKT7.mjs';export{a as ORG_POLICY_TEMPLATE_REGISTRY,b as createOrgTemplate,b as templateContextFor}from'./chunk-CWY2FMIC.mjs';export{d as exportDOCX,a as exportHTML,b as exportMarkdown,c as exportPDF}from'./chunk-IVSNHT24.mjs';export{a as getComplianceScore}from'./chunk-7RBO42IW.mjs';export{a as calculateBreachSeverity}from'./chunk-WTGKZX7J.mjs';export{c as DEFAULT_POLICY_SECTIONS,d as DEFAULT_POLICY_VARIABLES,e as createBusinessPolicyTemplate,a as findUnfilledTokens,b as generatePolicyText}from'./chunk-NBQQ2GN3.mjs';export{d as DEFAULT_DATA_CATEGORIES,a as UNFILLED_PREFIX,b as UNFILLED_SUFFIX,c as assemblePolicy,e as createDefaultContext,f as evaluatePolicyCompliance}from'./chunk-BIJSMSUU.mjs';export{h as assessTransferRisk,f as getTransferMechanismDescription,e as isNDPCApprovalRequired,g as validateTransfer}from'./chunk-7BJXI2HI.mjs';export{c as assessComplianceGaps,d as generateLawfulBasisSummary,b as getLawfulBasisDescription,a as validateProcessingActivity}from'./chunk-LWIKDDSU.mjs';export{c as exportROPAToCSV,b as generateROPASummary,d as identifyComplianceGaps,a as validateProcessingRecord}from'./chunk-XP5PL6K7.mjs';export{c as appendAuditEntry,a as createAuditEntry,b as getAuditLog}from'./chunk-V7UFP6QU.mjs';export{b as cookieAdapter,a as sessionStorageAdapter}from'./chunk-XC3DLYEG.mjs';export{a as validateConsent,b as validateConsentOptions}from'./chunk-PJNKQPQP.mjs';export{a as sanitizeInput}from'./chunk-EWVK45Z3.mjs';export{b as formatDSRRequest,a as validateDsrSubmission}from'./chunk-VPNK7OID.mjs';export{a as assessDPIARisk}from'./chunk-LRRENTT5.mjs';export{b as LEGAL_DISCLAIMER_LONG,a as LEGAL_DISCLAIMER_SHORT,c as legalDisclaimerBlock}from'./chunk-ITCY2Z66.mjs';export{a as defaultLocale,b as mergeLocale}from'./chunk-V5TZJJWU.mjs';export{a as localStorageAdapter}from'./chunk-DBZSN4WP.mjs';import'./chunk-ZJYULEER.mjs';
1
+ export{a as apiAdapter,c as composeAdapters,b as memoryAdapter}from'./chunk-7PMPKVY3.mjs';export{e as arabicLocale,f as frenchLocale,c as hausaLocale,b as igboLocale,d as pidginLocale,a as yorubaLocale}from'./chunk-PSPYIRIF.mjs';export{a as ORG_POLICY_TEMPLATE_REGISTRY,b as createOrgTemplate,b as templateContextFor}from'./chunk-CWY2FMIC.mjs';export{d as exportDOCX,a as exportHTML,b as exportMarkdown,c as exportPDF}from'./chunk-IVSNHT24.mjs';export{a as getComplianceScore}from'./chunk-7RBO42IW.mjs';export{a as calculateBreachSeverity}from'./chunk-WTGKZX7J.mjs';export{c as DEFAULT_POLICY_SECTIONS,d as DEFAULT_POLICY_VARIABLES,e as createBusinessPolicyTemplate,a as findUnfilledTokens,b as generatePolicyText}from'./chunk-NBQQ2GN3.mjs';export{d as DEFAULT_DATA_CATEGORIES,a as UNFILLED_PREFIX,b as UNFILLED_SUFFIX,c as assemblePolicy,e as createDefaultContext,f as evaluatePolicyCompliance}from'./chunk-BIJSMSUU.mjs';export{h as assessTransferRisk,f as getTransferMechanismDescription,e as isNDPCApprovalRequired,g as validateTransfer}from'./chunk-7BJXI2HI.mjs';export{c as assessComplianceGaps,d as generateLawfulBasisSummary,b as getLawfulBasisDescription,a as validateProcessingActivity}from'./chunk-LWIKDDSU.mjs';export{c as exportROPAToCSV,b as generateROPASummary,d as identifyComplianceGaps,a as validateProcessingRecord}from'./chunk-XP5PL6K7.mjs';export{c as appendAuditEntry,a as createAuditEntry,b as getAuditLog}from'./chunk-V7UFP6QU.mjs';export{b as cookieAdapter,a as sessionStorageAdapter}from'./chunk-XC3DLYEG.mjs';export{b as validateConsentOptionsStructured,a as validateConsentStructured}from'./chunk-R3ZKV2J7.mjs';export{a as sanitizeInput}from'./chunk-EWVK45Z3.mjs';export{b as formatDSRRequestStructured,a as validateDsrSubmissionStructured}from'./chunk-RRVML7CU.mjs';export{a as assessDPIARisk}from'./chunk-LRRENTT5.mjs';export{b as LEGAL_DISCLAIMER_LONG,a as LEGAL_DISCLAIMER_SHORT,c as legalDisclaimerBlock}from'./chunk-ITCY2Z66.mjs';export{a as defaultLocale,b as mergeLocale}from'./chunk-V5TZJJWU.mjs';export{a as localStorageAdapter}from'./chunk-DBZSN4WP.mjs';import'./chunk-ZJYULEER.mjs';
package/dist/styles.css CHANGED
@@ -197,8 +197,7 @@
197
197
  .ndpr-consent-banner--bottom,
198
198
  .ndpr-consent-banner--top {
199
199
  position: fixed;
200
- left: 0;
201
- right: 0;
200
+ inset-inline: 0;
202
201
  z-index: var(--ndpr-z-banner);
203
202
  border-radius: 0;
204
203
  }
@@ -206,16 +205,16 @@
206
205
  .ndpr-consent-banner--bottom {
207
206
  bottom: 0;
208
207
  border-bottom: none;
209
- border-left: none;
210
- border-right: none;
208
+ border-inline-start: none;
209
+ border-inline-end: none;
211
210
  animation: ndpr-slide-in-bottom var(--ndpr-transition-slow);
212
211
  }
213
212
 
214
213
  .ndpr-consent-banner--top {
215
214
  top: 0;
216
215
  border-top: none;
217
- border-left: none;
218
- border-right: none;
216
+ border-inline-start: none;
217
+ border-inline-end: none;
219
218
  animation: ndpr-slide-in-top var(--ndpr-transition-slow);
220
219
  }
221
220
 
@@ -232,14 +231,14 @@
232
231
 
233
232
  .ndpr-consent-banner--card.ndpr-consent-banner--bottom {
234
233
  bottom: var(--ndpr-space-4);
235
- left: auto;
236
- right: var(--ndpr-space-4);
234
+ inset-inline-start: auto;
235
+ inset-inline-end: var(--ndpr-space-4);
237
236
  }
238
237
 
239
238
  .ndpr-consent-banner--card.ndpr-consent-banner--top {
240
239
  top: var(--ndpr-space-4);
241
- left: auto;
242
- right: var(--ndpr-space-4);
240
+ inset-inline-start: auto;
241
+ inset-inline-end: var(--ndpr-space-4);
243
242
  }
244
243
 
245
244
  .ndpr-consent-banner--modal {
@@ -359,7 +358,7 @@
359
358
 
360
359
  .ndpr-consent-banner__required-marker {
361
360
  color: rgb(var(--ndpr-destructive));
362
- margin-left: var(--ndpr-space-1);
361
+ margin-inline-start: var(--ndpr-space-1);
363
362
  }
364
363
 
365
364
  .ndpr-consent-banner__option-description {
@@ -539,6 +538,9 @@
539
538
  content: '';
540
539
  position: absolute;
541
540
  top: 1px;
541
+ /* Physical `left` kept (paired with `translateX` below); switching to
542
+ * inset-inline-start without a logical transform would desync the resting
543
+ * position from the checked-state translation in RTL contexts. */
542
544
  left: 1px;
543
545
  width: 1.25rem;
544
546
  height: 1.25rem;
@@ -574,7 +576,7 @@
574
576
  }
575
577
 
576
578
  .ndpr-consent-manager__required-marker {
577
- margin-left: var(--ndpr-space-1);
579
+ margin-inline-start: var(--ndpr-space-1);
578
580
  font-size: var(--ndpr-font-size-xs);
579
581
  color: rgb(var(--ndpr-destructive));
580
582
  }
@@ -660,7 +662,7 @@
660
662
  }
661
663
 
662
664
  .ndpr-form-field__required {
663
- margin-left: var(--ndpr-space-1);
665
+ margin-inline-start: var(--ndpr-space-1);
664
666
  color: rgb(var(--ndpr-destructive));
665
667
  }
666
668
 
@@ -1094,7 +1096,7 @@
1094
1096
 
1095
1097
  .ndpr-table__head {
1096
1098
  background: rgb(var(--ndpr-surface));
1097
- text-align: left;
1099
+ text-align: start;
1098
1100
  font-size: var(--ndpr-font-size-xs);
1099
1101
  font-weight: 600;
1100
1102
  text-transform: uppercase;
@@ -1123,7 +1125,7 @@
1123
1125
  }
1124
1126
 
1125
1127
  .ndpr-table__cell--actions {
1126
- text-align: right;
1128
+ text-align: end;
1127
1129
  white-space: nowrap;
1128
1130
  }
1129
1131
 
@@ -1298,7 +1300,7 @@
1298
1300
  content: '';
1299
1301
  position: absolute;
1300
1302
  top: 1rem;
1301
- left: 50%;
1303
+ inset-inline-start: 50%;
1302
1304
  width: 100%;
1303
1305
  height: 2px;
1304
1306
  background: rgb(var(--ndpr-border));