@redacto.io/consent-sdk-react 9.4.0 → 10.0.0-beta.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 (36) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/index.d.mts +4 -2
  3. package/dist/index.d.ts +4 -2
  4. package/dist/index.js +122 -15
  5. package/dist/index.mjs +122 -15
  6. package/dist/privacy-center.d.mts +31 -7
  7. package/dist/privacy-center.d.ts +31 -7
  8. package/dist/privacy-center.js +187 -44
  9. package/dist/privacy-center.mjs +187 -44
  10. package/package.json +1 -1
  11. package/src/RedactoNoticeConsent/RedactoNoticeConsent.test.tsx +5 -0
  12. package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +29 -4
  13. package/src/RedactoNoticeConsent/api/index.ts +131 -2
  14. package/src/RedactoNoticeConsent/api/types.ts +33 -1
  15. package/src/RedactoNoticeConsent/types.ts +1 -0
  16. package/src/RedactoNoticeConsentInline/RedactoNoticeConsentInline.tsx +3 -1
  17. package/src/RedactoNoticeConsentInline/api/index.ts +5 -2
  18. package/src/RedactoNoticeConsentInline/api/types.ts +1 -1
  19. package/src/RedactoNoticeConsentInline/types.ts +1 -0
  20. package/src/RedactoPrivacyCenter/PrivacyCenterLayout.tsx +6 -4
  21. package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +3 -1
  22. package/src/RedactoPrivacyCenter/api/actions.ts +10 -3
  23. package/src/RedactoPrivacyCenter/api/client.ts +67 -21
  24. package/src/RedactoPrivacyCenter/components/ConsentManager.tsx +12 -1
  25. package/src/RedactoPrivacyCenter/components/Form.tsx +58 -6
  26. package/src/RedactoPrivacyCenter/components/groupHelpers.ts +64 -1
  27. package/src/RedactoPrivacyCenter/context/AuthContext.tsx +7 -5
  28. package/src/RedactoPrivacyCenter/context/BaseUrlContext.tsx +8 -2
  29. package/src/RedactoPrivacyCenter/context/types.ts +1 -0
  30. package/src/RedactoPrivacyCenter/lib/api.ts +8 -0
  31. package/src/RedactoPrivacyCenter/lib/constants.ts +9 -0
  32. package/src/RedactoPrivacyCenter/lib/types.ts +11 -1
  33. package/src/RedactoPrivacyCenter/lib/utils.ts +28 -0
  34. package/tests/Form.test.tsx +5 -0
  35. package/tests/mocks.ts +1 -0
  36. package/tests/resolveContactFromJwt.test.ts +44 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @redacto.io/consent-sdk-react
2
2
 
3
+ ## 10.0.0-beta.0
4
+
5
+ ### Major Changes
6
+
7
+ - route consent writes & Privacy Center reads through the Go ledger (ledgerBaseUrl)
8
+
3
9
  ## 9.4.0
4
10
 
5
11
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -47,6 +47,7 @@ type Props$1 = Readonly<{
47
47
  accessToken: string;
48
48
  refreshToken: string;
49
49
  baseUrl?: string;
50
+ ledgerBaseUrl: string;
50
51
  settings?: Partial<Settings$1>;
51
52
  language?: string;
52
53
  blockUI?: boolean;
@@ -68,7 +69,7 @@ type Props$1 = Readonly<{
68
69
  * to view and manage their consent preferences. Supports both initial consent
69
70
  * collection and reconsent flows.
70
71
  */
71
- declare const RedactoNoticeConsent: ({ noticeId, accessToken, refreshToken, baseUrl, language, blockUI, onAccept, onDecline, onError, settings, applicationId, validateAgainst, digilockerMode, digilockerCallbackUrl, includeFullyConsentedData, reviewModeButtonText, }: Props$1) => react_jsx_runtime.JSX.Element;
72
+ declare const RedactoNoticeConsent: ({ noticeId, accessToken, refreshToken, baseUrl, ledgerBaseUrl, language, blockUI, onAccept, onDecline, onError, settings, applicationId, validateAgainst, digilockerMode, digilockerCallbackUrl, includeFullyConsentedData, reviewModeButtonText, }: Props$1) => react_jsx_runtime.JSX.Element;
72
73
 
73
74
  type Settings = {
74
75
  button: {
@@ -102,6 +103,7 @@ type Props = Readonly<{
102
103
  accessToken?: string;
103
104
  refreshToken?: string;
104
105
  baseUrl?: string;
106
+ ledgerBaseUrl: string;
105
107
  settings?: Partial<Settings>;
106
108
  language?: string;
107
109
  onAccept?: () => void;
@@ -112,7 +114,7 @@ type Props = Readonly<{
112
114
  }>;
113
115
 
114
116
  declare const RedactoConsentInline: react.MemoExoticComponent<{
115
- ({ org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, language, onAccept, onError, onValidationChange, settings, applicationId, }: Props): react_jsx_runtime.JSX.Element | null;
117
+ ({ org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, ledgerBaseUrl, language, onAccept, onError, onValidationChange, settings, applicationId, }: Props): react_jsx_runtime.JSX.Element | null;
116
118
  displayName: string;
117
119
  }>;
118
120
 
package/dist/index.d.ts CHANGED
@@ -47,6 +47,7 @@ type Props$1 = Readonly<{
47
47
  accessToken: string;
48
48
  refreshToken: string;
49
49
  baseUrl?: string;
50
+ ledgerBaseUrl: string;
50
51
  settings?: Partial<Settings$1>;
51
52
  language?: string;
52
53
  blockUI?: boolean;
@@ -68,7 +69,7 @@ type Props$1 = Readonly<{
68
69
  * to view and manage their consent preferences. Supports both initial consent
69
70
  * collection and reconsent flows.
70
71
  */
71
- declare const RedactoNoticeConsent: ({ noticeId, accessToken, refreshToken, baseUrl, language, blockUI, onAccept, onDecline, onError, settings, applicationId, validateAgainst, digilockerMode, digilockerCallbackUrl, includeFullyConsentedData, reviewModeButtonText, }: Props$1) => react_jsx_runtime.JSX.Element;
72
+ declare const RedactoNoticeConsent: ({ noticeId, accessToken, refreshToken, baseUrl, ledgerBaseUrl, language, blockUI, onAccept, onDecline, onError, settings, applicationId, validateAgainst, digilockerMode, digilockerCallbackUrl, includeFullyConsentedData, reviewModeButtonText, }: Props$1) => react_jsx_runtime.JSX.Element;
72
73
 
73
74
  type Settings = {
74
75
  button: {
@@ -102,6 +103,7 @@ type Props = Readonly<{
102
103
  accessToken?: string;
103
104
  refreshToken?: string;
104
105
  baseUrl?: string;
106
+ ledgerBaseUrl: string;
105
107
  settings?: Partial<Settings>;
106
108
  language?: string;
107
109
  onAccept?: () => void;
@@ -112,7 +114,7 @@ type Props = Readonly<{
112
114
  }>;
113
115
 
114
116
  declare const RedactoConsentInline: react.MemoExoticComponent<{
115
- ({ org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, language, onAccept, onError, onValidationChange, settings, applicationId, }: Props): react_jsx_runtime.JSX.Element | null;
117
+ ({ org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, ledgerBaseUrl, language, onAccept, onError, onValidationChange, settings, applicationId, }: Props): react_jsx_runtime.JSX.Element | null;
116
118
  displayName: string;
117
119
  }>;
118
120
 
package/dist/index.js CHANGED
@@ -181,7 +181,7 @@ var fetchConsentContent = async ({
181
181
  };
182
182
  var submitConsentEvent = async ({
183
183
  accessToken,
184
- baseUrl,
184
+ ledgerBaseUrl,
185
185
  noticeUuid,
186
186
  purposes,
187
187
  declined,
@@ -202,7 +202,10 @@ var submitConsentEvent = async ({
202
202
  if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
203
203
  throw new Error("Invalid token: missing organization or workspace UUID");
204
204
  }
205
- const apiBaseUrl = baseUrl || BASE_URL;
205
+ if (!ledgerBaseUrl) {
206
+ throw new Error("ledgerBaseUrl is required to submit consent");
207
+ }
208
+ const apiBaseUrl = ledgerBaseUrl;
206
209
  const validatedPurposes = purposes.map((purpose) => {
207
210
  if (!purpose.uuid) {
208
211
  throw new Error(`Invalid purpose data: missing uuid`);
@@ -248,6 +251,88 @@ var submitConsentEvent = async ({
248
251
  }
249
252
  apiCache.clear();
250
253
  };
254
+ var fetchNoticeConsentStatus = async ({
255
+ accessToken,
256
+ ledgerBaseUrl,
257
+ noticeUuid,
258
+ signal
259
+ }) => {
260
+ if (!accessToken || !ledgerBaseUrl || !noticeUuid) {
261
+ return null;
262
+ }
263
+ const decodedToken = decodeTokenSafely(accessToken);
264
+ if (!decodedToken) {
265
+ return null;
266
+ }
267
+ const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
268
+ if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
269
+ return null;
270
+ }
271
+ try {
272
+ const response = await fetch(
273
+ `${ledgerBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/check-consent`,
274
+ {
275
+ method: "POST",
276
+ headers: {
277
+ Authorization: `Bearer ${accessToken}`,
278
+ "Content-Type": "application/json"
279
+ },
280
+ body: "{}",
281
+ signal
282
+ }
283
+ );
284
+ if (!response.ok) {
285
+ return null;
286
+ }
287
+ const data = await response.json();
288
+ const body = data && typeof data === "object" && "detail" in data && data.detail ? data.detail : data;
289
+ if (!body || !Array.isArray(body.purposes)) {
290
+ return null;
291
+ }
292
+ return body;
293
+ } catch {
294
+ return null;
295
+ }
296
+ };
297
+ var buildLedgerConsentOverlay = (status, configPurposes) => {
298
+ var _a, _b;
299
+ const byUuid = new Map(status.purposes.map((p) => [p.uuid, p]));
300
+ const hasHistory = status.purposes.some(
301
+ (p) => (p.status || "INACTIVE") !== "INACTIVE"
302
+ );
303
+ if (!hasHistory) {
304
+ return null;
305
+ }
306
+ const purpose_selections = {};
307
+ for (const cp of configPurposes) {
308
+ const lp = byUuid.get(cp.uuid);
309
+ const purposeStatus = (lp == null ? void 0 : lp.status) || "INACTIVE";
310
+ const selectedByUuid = new Map(
311
+ ((lp == null ? void 0 : lp.data_elements) || []).map((de) => [de.uuid, de.selected])
312
+ );
313
+ const data_elements = {};
314
+ for (const de of cp.data_elements) {
315
+ data_elements[de.uuid] = {
316
+ selected: (_a = selectedByUuid.get(de.uuid)) != null ? _a : false,
317
+ enabled: de.enabled,
318
+ required: de.required
319
+ };
320
+ }
321
+ purpose_selections[cp.uuid] = {
322
+ selected: (_b = lp == null ? void 0 : lp.selected) != null ? _b : false,
323
+ status: purposeStatus,
324
+ needs_reconsent: purposeStatus !== "ACTIVE",
325
+ data_elements
326
+ };
327
+ }
328
+ const reconsent_required = configPurposes.some(
329
+ (cp) => {
330
+ var _a2;
331
+ return (((_a2 = purpose_selections[cp.uuid]) == null ? void 0 : _a2.status) || "INACTIVE") !== "ACTIVE";
332
+ }
333
+ );
334
+ return { reconsent_required, purpose_selections };
335
+ };
251
336
  var fetchTTSAudioUrls = async ({
252
337
  accessToken,
253
338
  baseUrl,
@@ -2294,6 +2379,7 @@ var RedactoNoticeConsent = ({
2294
2379
  accessToken,
2295
2380
  refreshToken,
2296
2381
  baseUrl,
2382
+ ledgerBaseUrl,
2297
2383
  language = "en",
2298
2384
  blockUI = true,
2299
2385
  onAccept,
@@ -2648,7 +2734,7 @@ var RedactoNoticeConsent = ({
2648
2734
  return content.dpo_info[key] || defaultText;
2649
2735
  };
2650
2736
  const fetchNotice = async () => {
2651
- var _a2;
2737
+ var _a2, _b2, _c2;
2652
2738
  if (isRequestInProgressRef.current) {
2653
2739
  return;
2654
2740
  }
@@ -2689,8 +2775,24 @@ var RedactoNoticeConsent = ({
2689
2775
  {}
2690
2776
  );
2691
2777
  setCollapsedPurposes(initialCollapsedState);
2692
- const isReconsentRequired = consentContentData.detail.reconsent_required;
2693
- const purposeSelections = consentContentData.detail.purpose_selections;
2778
+ let isReconsentRequired = consentContentData.detail.reconsent_required;
2779
+ let purposeSelections = consentContentData.detail.purpose_selections;
2780
+ if (ledgerBaseUrl && !applicationId) {
2781
+ const ledgerStatus = await fetchNoticeConsentStatus({
2782
+ accessToken,
2783
+ ledgerBaseUrl,
2784
+ noticeUuid: noticeId,
2785
+ signal: (_b2 = abortControllerRef.current) == null ? void 0 : _b2.signal
2786
+ });
2787
+ if (ledgerStatus) {
2788
+ const overlay = buildLedgerConsentOverlay(
2789
+ ledgerStatus,
2790
+ activeConfig.purposes
2791
+ );
2792
+ isReconsentRequired = (_c2 = overlay == null ? void 0 : overlay.reconsent_required) != null ? _c2 : false;
2793
+ purposeSelections = overlay == null ? void 0 : overlay.purpose_selections;
2794
+ }
2795
+ }
2694
2796
  const newCategorizedPurposes = isReconsentRequired ? {
2695
2797
  alreadyConsented: activeConfig.purposes.filter(
2696
2798
  (purpose) => {
@@ -2721,9 +2823,9 @@ var RedactoNoticeConsent = ({
2721
2823
  const initialDataElementState = activeConfig.purposes.reduce(
2722
2824
  (acc, purpose) => {
2723
2825
  purpose.data_elements.forEach((element) => {
2724
- var _a3, _b2;
2826
+ var _a3, _b3;
2725
2827
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2726
- if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2828
+ if ((_b3 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2727
2829
  acc[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2728
2830
  } else {
2729
2831
  acc[combinedId] = false;
@@ -2739,9 +2841,9 @@ var RedactoNoticeConsent = ({
2739
2841
  const initialSelections = {};
2740
2842
  newCategorizedPurposes.alreadyConsented.forEach((purpose) => {
2741
2843
  purpose.data_elements.forEach((element) => {
2742
- var _a3, _b2;
2844
+ var _a3, _b3;
2743
2845
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2744
- if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2846
+ if ((_b3 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2745
2847
  initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2746
2848
  } else {
2747
2849
  initialSelections[combinedId] = false;
@@ -2762,9 +2864,9 @@ var RedactoNoticeConsent = ({
2762
2864
  activeConfig.purposes.forEach(
2763
2865
  (purpose) => {
2764
2866
  purpose.data_elements.forEach((element) => {
2765
- var _a3, _b2;
2867
+ var _a3, _b3;
2766
2868
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2767
- if ((_b2 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2869
+ if ((_b3 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2768
2870
  initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2769
2871
  } else {
2770
2872
  initialSelections[combinedId] = false;
@@ -2895,7 +2997,7 @@ var RedactoNoticeConsent = ({
2895
2997
  if (content) {
2896
2998
  await submitConsentEvent({
2897
2999
  accessToken,
2898
- baseUrl,
3000
+ ledgerBaseUrl,
2899
3001
  noticeUuid: content.notice_uuid,
2900
3002
  purposes: content.purposes.map((purpose) => {
2901
3003
  const isAlreadyConsented = (categorizedPurposes == null ? void 0 : categorizedPurposes.alreadyConsented.some(
@@ -4676,13 +4778,16 @@ var submitConsentEvent2 = async ({
4676
4778
  org_uuid,
4677
4779
  workspace_uuid,
4678
4780
  accessToken,
4679
- baseUrl,
4781
+ ledgerBaseUrl,
4680
4782
  noticeUuid,
4681
4783
  purposes,
4682
4784
  declined,
4683
4785
  meta_data
4684
4786
  }) => {
4685
- const apiBaseUrl = baseUrl || BASE_URL2;
4787
+ if (!ledgerBaseUrl) {
4788
+ throw new Error("ledgerBaseUrl is required to submit consent");
4789
+ }
4790
+ const apiBaseUrl = ledgerBaseUrl;
4686
4791
  const payload = {
4687
4792
  notice_uuid: noticeUuid,
4688
4793
  purposes: purposes.map((purpose) => {
@@ -5133,6 +5238,7 @@ var RedactoConsentInlineComponent = ({
5133
5238
  notice_uuid,
5134
5239
  accessToken,
5135
5240
  baseUrl,
5241
+ ledgerBaseUrl,
5136
5242
  language = "en",
5137
5243
  onAccept,
5138
5244
  onError,
@@ -5366,7 +5472,7 @@ var RedactoConsentInlineComponent = ({
5366
5472
  org_uuid,
5367
5473
  workspace_uuid,
5368
5474
  accessToken: tokenToUse,
5369
- baseUrl,
5475
+ ledgerBaseUrl,
5370
5476
  noticeUuid: content.notice_uuid,
5371
5477
  purposes: content.purposes.map((purpose) => {
5372
5478
  const hasSelectedRequiredElement = purpose.data_elements.some(
@@ -5405,6 +5511,7 @@ var RedactoConsentInlineComponent = ({
5405
5511
  org_uuid,
5406
5512
  workspace_uuid,
5407
5513
  baseUrl,
5514
+ ledgerBaseUrl,
5408
5515
  selectedDataElements,
5409
5516
  selectedPurposes,
5410
5517
  applicationId,
package/dist/index.mjs CHANGED
@@ -155,7 +155,7 @@ var fetchConsentContent = async ({
155
155
  };
156
156
  var submitConsentEvent = async ({
157
157
  accessToken,
158
- baseUrl,
158
+ ledgerBaseUrl,
159
159
  noticeUuid,
160
160
  purposes,
161
161
  declined,
@@ -176,7 +176,10 @@ var submitConsentEvent = async ({
176
176
  if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
177
177
  throw new Error("Invalid token: missing organization or workspace UUID");
178
178
  }
179
- const apiBaseUrl = baseUrl || BASE_URL;
179
+ if (!ledgerBaseUrl) {
180
+ throw new Error("ledgerBaseUrl is required to submit consent");
181
+ }
182
+ const apiBaseUrl = ledgerBaseUrl;
180
183
  const validatedPurposes = purposes.map((purpose) => {
181
184
  if (!purpose.uuid) {
182
185
  throw new Error(`Invalid purpose data: missing uuid`);
@@ -222,6 +225,88 @@ var submitConsentEvent = async ({
222
225
  }
223
226
  apiCache.clear();
224
227
  };
228
+ var fetchNoticeConsentStatus = async ({
229
+ accessToken,
230
+ ledgerBaseUrl,
231
+ noticeUuid,
232
+ signal
233
+ }) => {
234
+ if (!accessToken || !ledgerBaseUrl || !noticeUuid) {
235
+ return null;
236
+ }
237
+ const decodedToken = decodeTokenSafely(accessToken);
238
+ if (!decodedToken) {
239
+ return null;
240
+ }
241
+ const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
242
+ if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
243
+ return null;
244
+ }
245
+ try {
246
+ const response = await fetch(
247
+ `${ledgerBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/check-consent`,
248
+ {
249
+ method: "POST",
250
+ headers: {
251
+ Authorization: `Bearer ${accessToken}`,
252
+ "Content-Type": "application/json"
253
+ },
254
+ body: "{}",
255
+ signal
256
+ }
257
+ );
258
+ if (!response.ok) {
259
+ return null;
260
+ }
261
+ const data = await response.json();
262
+ const body = data && typeof data === "object" && "detail" in data && data.detail ? data.detail : data;
263
+ if (!body || !Array.isArray(body.purposes)) {
264
+ return null;
265
+ }
266
+ return body;
267
+ } catch {
268
+ return null;
269
+ }
270
+ };
271
+ var buildLedgerConsentOverlay = (status, configPurposes) => {
272
+ var _a, _b;
273
+ const byUuid = new Map(status.purposes.map((p) => [p.uuid, p]));
274
+ const hasHistory = status.purposes.some(
275
+ (p) => (p.status || "INACTIVE") !== "INACTIVE"
276
+ );
277
+ if (!hasHistory) {
278
+ return null;
279
+ }
280
+ const purpose_selections = {};
281
+ for (const cp of configPurposes) {
282
+ const lp = byUuid.get(cp.uuid);
283
+ const purposeStatus = (lp == null ? void 0 : lp.status) || "INACTIVE";
284
+ const selectedByUuid = new Map(
285
+ ((lp == null ? void 0 : lp.data_elements) || []).map((de) => [de.uuid, de.selected])
286
+ );
287
+ const data_elements = {};
288
+ for (const de of cp.data_elements) {
289
+ data_elements[de.uuid] = {
290
+ selected: (_a = selectedByUuid.get(de.uuid)) != null ? _a : false,
291
+ enabled: de.enabled,
292
+ required: de.required
293
+ };
294
+ }
295
+ purpose_selections[cp.uuid] = {
296
+ selected: (_b = lp == null ? void 0 : lp.selected) != null ? _b : false,
297
+ status: purposeStatus,
298
+ needs_reconsent: purposeStatus !== "ACTIVE",
299
+ data_elements
300
+ };
301
+ }
302
+ const reconsent_required = configPurposes.some(
303
+ (cp) => {
304
+ var _a2;
305
+ return (((_a2 = purpose_selections[cp.uuid]) == null ? void 0 : _a2.status) || "INACTIVE") !== "ACTIVE";
306
+ }
307
+ );
308
+ return { reconsent_required, purpose_selections };
309
+ };
225
310
  var fetchTTSAudioUrls = async ({
226
311
  accessToken,
227
312
  baseUrl,
@@ -2241,6 +2326,7 @@ var RedactoNoticeConsent = ({
2241
2326
  accessToken,
2242
2327
  refreshToken,
2243
2328
  baseUrl,
2329
+ ledgerBaseUrl,
2244
2330
  language = "en",
2245
2331
  blockUI = true,
2246
2332
  onAccept,
@@ -2595,7 +2681,7 @@ var RedactoNoticeConsent = ({
2595
2681
  return content.dpo_info[key] || defaultText;
2596
2682
  };
2597
2683
  const fetchNotice = async () => {
2598
- var _a2;
2684
+ var _a2, _b2, _c2;
2599
2685
  if (isRequestInProgressRef.current) {
2600
2686
  return;
2601
2687
  }
@@ -2636,8 +2722,24 @@ var RedactoNoticeConsent = ({
2636
2722
  {}
2637
2723
  );
2638
2724
  setCollapsedPurposes(initialCollapsedState);
2639
- const isReconsentRequired = consentContentData.detail.reconsent_required;
2640
- const purposeSelections = consentContentData.detail.purpose_selections;
2725
+ let isReconsentRequired = consentContentData.detail.reconsent_required;
2726
+ let purposeSelections = consentContentData.detail.purpose_selections;
2727
+ if (ledgerBaseUrl && !applicationId) {
2728
+ const ledgerStatus = await fetchNoticeConsentStatus({
2729
+ accessToken,
2730
+ ledgerBaseUrl,
2731
+ noticeUuid: noticeId,
2732
+ signal: (_b2 = abortControllerRef.current) == null ? void 0 : _b2.signal
2733
+ });
2734
+ if (ledgerStatus) {
2735
+ const overlay = buildLedgerConsentOverlay(
2736
+ ledgerStatus,
2737
+ activeConfig.purposes
2738
+ );
2739
+ isReconsentRequired = (_c2 = overlay == null ? void 0 : overlay.reconsent_required) != null ? _c2 : false;
2740
+ purposeSelections = overlay == null ? void 0 : overlay.purpose_selections;
2741
+ }
2742
+ }
2641
2743
  const newCategorizedPurposes = isReconsentRequired ? {
2642
2744
  alreadyConsented: activeConfig.purposes.filter(
2643
2745
  (purpose) => {
@@ -2668,9 +2770,9 @@ var RedactoNoticeConsent = ({
2668
2770
  const initialDataElementState = activeConfig.purposes.reduce(
2669
2771
  (acc, purpose) => {
2670
2772
  purpose.data_elements.forEach((element) => {
2671
- var _a3, _b2;
2773
+ var _a3, _b3;
2672
2774
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2673
- if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2775
+ if ((_b3 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2674
2776
  acc[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2675
2777
  } else {
2676
2778
  acc[combinedId] = false;
@@ -2686,9 +2788,9 @@ var RedactoNoticeConsent = ({
2686
2788
  const initialSelections = {};
2687
2789
  newCategorizedPurposes.alreadyConsented.forEach((purpose) => {
2688
2790
  purpose.data_elements.forEach((element) => {
2689
- var _a3, _b2;
2791
+ var _a3, _b3;
2690
2792
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2691
- if ((_b2 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2793
+ if ((_b3 = (_a3 = purposeSelections == null ? void 0 : purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2692
2794
  initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2693
2795
  } else {
2694
2796
  initialSelections[combinedId] = false;
@@ -2709,9 +2811,9 @@ var RedactoNoticeConsent = ({
2709
2811
  activeConfig.purposes.forEach(
2710
2812
  (purpose) => {
2711
2813
  purpose.data_elements.forEach((element) => {
2712
- var _a3, _b2;
2814
+ var _a3, _b3;
2713
2815
  const combinedId = `${purpose.uuid}-${element.uuid}`;
2714
- if ((_b2 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b2[element.uuid]) {
2816
+ if ((_b3 = (_a3 = purposeSelections[purpose.uuid]) == null ? void 0 : _a3.data_elements) == null ? void 0 : _b3[element.uuid]) {
2715
2817
  initialSelections[combinedId] = purposeSelections[purpose.uuid].data_elements[element.uuid].selected;
2716
2818
  } else {
2717
2819
  initialSelections[combinedId] = false;
@@ -2842,7 +2944,7 @@ var RedactoNoticeConsent = ({
2842
2944
  if (content) {
2843
2945
  await submitConsentEvent({
2844
2946
  accessToken,
2845
- baseUrl,
2947
+ ledgerBaseUrl,
2846
2948
  noticeUuid: content.notice_uuid,
2847
2949
  purposes: content.purposes.map((purpose) => {
2848
2950
  const isAlreadyConsented = (categorizedPurposes == null ? void 0 : categorizedPurposes.alreadyConsented.some(
@@ -4623,13 +4725,16 @@ var submitConsentEvent2 = async ({
4623
4725
  org_uuid,
4624
4726
  workspace_uuid,
4625
4727
  accessToken,
4626
- baseUrl,
4728
+ ledgerBaseUrl,
4627
4729
  noticeUuid,
4628
4730
  purposes,
4629
4731
  declined,
4630
4732
  meta_data
4631
4733
  }) => {
4632
- const apiBaseUrl = baseUrl || BASE_URL2;
4734
+ if (!ledgerBaseUrl) {
4735
+ throw new Error("ledgerBaseUrl is required to submit consent");
4736
+ }
4737
+ const apiBaseUrl = ledgerBaseUrl;
4633
4738
  const payload = {
4634
4739
  notice_uuid: noticeUuid,
4635
4740
  purposes: purposes.map((purpose) => {
@@ -5080,6 +5185,7 @@ var RedactoConsentInlineComponent = ({
5080
5185
  notice_uuid,
5081
5186
  accessToken,
5082
5187
  baseUrl,
5188
+ ledgerBaseUrl,
5083
5189
  language = "en",
5084
5190
  onAccept,
5085
5191
  onError,
@@ -5313,7 +5419,7 @@ var RedactoConsentInlineComponent = ({
5313
5419
  org_uuid,
5314
5420
  workspace_uuid,
5315
5421
  accessToken: tokenToUse,
5316
- baseUrl,
5422
+ ledgerBaseUrl,
5317
5423
  noticeUuid: content.notice_uuid,
5318
5424
  purposes: content.purposes.map((purpose) => {
5319
5425
  const hasSelectedRequiredElement = purpose.data_elements.some(
@@ -5352,6 +5458,7 @@ var RedactoConsentInlineComponent = ({
5352
5458
  org_uuid,
5353
5459
  workspace_uuid,
5354
5460
  baseUrl,
5461
+ ledgerBaseUrl,
5355
5462
  selectedDataElements,
5356
5463
  selectedPurposes,
5357
5464
  applicationId,
@@ -31,9 +31,11 @@ type BaseRequest = {
31
31
  /**
32
32
  * Consent service client factory.
33
33
  * Creates a client instance with a specific base URL.
34
- * @param baseUrl - Consent server base URL
34
+ * @param baseUrl - Consent server base URL (Python service, e.g. http://host/consent)
35
+ * @param ledgerBaseUrl - Go ledger base URL (e.g. http://host:8090/consent-ledger).
36
+ * Used for user-consents reads which are served from the ledger's `/public/...` paths.
35
37
  */
36
- declare function createConsentClient(baseUrl: string): {
38
+ declare function createConsentClient(baseUrl: string, ledgerBaseUrl: string): {
37
39
  /**
38
40
  * Get form data (privacy center)
39
41
  */
@@ -92,9 +94,21 @@ declare function createConsentClient(baseUrl: string): {
92
94
  nominator_uuid?: string;
93
95
  }, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
94
96
  /**
95
- * Manage consent (privacy center) - revoke, regrant, or renew
97
+ * Manage consent (privacy center) - revoke, regrant, or renew.
98
+ *
99
+ * The Go ledger has no manage-consent route, so this is expressed as a
100
+ * `partial` submit-consent on the ledger — mirroring the Python dual-write
101
+ * relay (`build_consent_management_payload`): the affected purpose is
102
+ * re-submitted with `selected: false` to revoke or `selected: true` to
103
+ * regrant/renew, and `partial: true` so the rest of the notice's purposes
104
+ * are left untouched. The principal is resolved from the JWT, so no
105
+ * `contact`/identifiers are sent in the body, and `consent_event_uuid` is
106
+ * omitted so the ledger mints a fresh event.
96
107
  */
97
- manageConsent(baseRequest: BaseRequest, purposeId: string, contact: string, status: "revoke" | "regrant" | "renew", authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">, nominatorContact?: string, dataElementUuids?: string[], productUuid?: string): Promise<unknown>;
108
+ manageConsent(baseRequest: BaseRequest, purposeId: string, contact: string, status: "revoke" | "regrant" | "renew", authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">, nominatorContact?: string, dataElementUuids?: string[], productUuid?: string, noticeUuid?: string, dataElements?: Array<{
109
+ uuid: string;
110
+ selected: boolean;
111
+ }>): Promise<unknown>;
98
112
  /**
99
113
  * Get activities (privacy center)
100
114
  */
@@ -358,6 +372,7 @@ type PurposeItem = {
358
372
  method: string;
359
373
  data_elements: ConsentDataElement[];
360
374
  link_reason: string | null;
375
+ notice_uuid: string | null;
361
376
  };
362
377
  type ConsentGroup = {
363
378
  product_uuid: string;
@@ -609,6 +624,7 @@ declare const useInternalNavigation: () => NavigationContextType;
609
624
 
610
625
  interface RedactoPrivacyCenterProps {
611
626
  baseUrl: string;
627
+ ledgerBaseUrl: string;
612
628
  slug: string;
613
629
  accessToken: string;
614
630
  refreshToken: string;
@@ -616,7 +632,7 @@ interface RedactoPrivacyCenterProps {
616
632
  initialPage?: InternalPage;
617
633
  onBack?: 'back' | 'signout';
618
634
  }
619
- declare function RedactoPrivacyCenter({ baseUrl, slug, accessToken, refreshToken, onError, initialPage, onBack, }: RedactoPrivacyCenterProps): react_jsx_runtime.JSX.Element;
635
+ declare function RedactoPrivacyCenter({ baseUrl, ledgerBaseUrl, slug, accessToken, refreshToken, onError, initialPage, onBack, }: RedactoPrivacyCenterProps): react_jsx_runtime.JSX.Element;
620
636
 
621
637
  interface PrivacyCenterLayoutProps {
622
638
  children: ReactNode;
@@ -646,15 +662,18 @@ type AuthContextValue = Readonly<{
646
662
  }>;
647
663
  type BaseUrlContextValue = Readonly<{
648
664
  baseUrl: string;
665
+ ledgerBaseUrl: string;
649
666
  consentClient: ReturnType<typeof createConsentClient>;
650
667
  }>;
651
668
 
652
- declare const BaseUrlProvider: ({ children, baseUrl, }: {
669
+ declare const BaseUrlProvider: ({ children, baseUrl, ledgerBaseUrl, }: {
653
670
  children: ReactNode;
654
671
  baseUrl: string;
672
+ ledgerBaseUrl: string;
655
673
  }) => react_jsx_runtime.JSX.Element;
656
674
  declare const useBaseUrl: () => Readonly<{
657
675
  baseUrl: string;
676
+ ledgerBaseUrl: string;
658
677
  consentClient: ReturnType<typeof createConsentClient>;
659
678
  }>;
660
679
 
@@ -801,7 +820,7 @@ type FetchGroupPurposesParams = {
801
820
  consentClient?: BaseUrlContextValue['consentClient'];
802
821
  };
803
822
  declare const fetchGroupPurposes: (params: FetchGroupPurposesParams) => Promise<GroupPurposesOut | null>;
804
- declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, productUuid, }: {
823
+ declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, productUuid, noticeUuid, dataElements, }: {
805
824
  organizationId: string;
806
825
  workspaceId: string;
807
826
  purposeId: string;
@@ -812,6 +831,11 @@ declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact,
812
831
  nominatorContact?: string;
813
832
  dataElementUuids?: string[];
814
833
  productUuid?: string;
834
+ noticeUuid?: string;
835
+ dataElements?: Array<{
836
+ uuid: string;
837
+ selected: boolean;
838
+ }>;
815
839
  }) => Promise<boolean | null>;
816
840
  declare const fetchActivities: (organizationId: string, workspaceId: string, offset?: number, limit?: number, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<ActivityDetail | null>;
817
841
  declare const fetchCaseHistory: (organizationId: string, workspaceId: string, contact: string, offset?: number, limit?: number, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<CaseHistoryDetail | null>;