@redacto.io/consent-sdk-react-native 4.0.1-beta.0 → 5.0.0-beta.1

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/index.mjs CHANGED
@@ -131,6 +131,7 @@ var fetchConsentContent = async ({
131
131
  var submitConsentEvent = async ({
132
132
  accessToken,
133
133
  baseUrl,
134
+ ledgerBaseUrl,
134
135
  noticeUuid,
135
136
  purposes,
136
137
  declined,
@@ -150,7 +151,7 @@ var submitConsentEvent = async ({
150
151
  if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
151
152
  throw new Error("Invalid token: missing organization or workspace UUID");
152
153
  }
153
- const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
154
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
154
155
  const validatedPurposes = purposes.map((purpose) => {
155
156
  if (!purpose.uuid) {
156
157
  throw new Error("Invalid purpose data: missing uuid");
@@ -399,6 +400,122 @@ var verifyGuardianStatus = async ({
399
400
  };
400
401
  };
401
402
 
403
+ // src/shared/notice-consent-status.ts
404
+ import { jwtDecode as jwtDecode2 } from "jwt-decode";
405
+ var decodeNoticeConsentToken = (token) => {
406
+ try {
407
+ return jwtDecode2(token);
408
+ } catch {
409
+ return null;
410
+ }
411
+ };
412
+ var fetchNoticeConsentStatusForScope = async ({
413
+ accessToken,
414
+ ledgerBaseUrl,
415
+ organisationUuid,
416
+ workspaceUuid,
417
+ noticeUuid,
418
+ signal
419
+ }) => {
420
+ if (!accessToken || !ledgerBaseUrl || !organisationUuid || !workspaceUuid || !noticeUuid) {
421
+ return null;
422
+ }
423
+ try {
424
+ const response = await fetch(
425
+ `${ledgerBaseUrl}/public/organisations/${organisationUuid}/workspaces/${workspaceUuid}/notices/${noticeUuid}/check-consent`,
426
+ {
427
+ method: "POST",
428
+ headers: {
429
+ Authorization: `Bearer ${accessToken}`,
430
+ "Content-Type": "application/json"
431
+ },
432
+ body: "{}",
433
+ signal
434
+ }
435
+ );
436
+ if (!response.ok) {
437
+ return null;
438
+ }
439
+ const data = await response.json();
440
+ const body = data && typeof data === "object" && "detail" in data && data.detail ? data.detail : data;
441
+ if (!body || !Array.isArray(body.purposes)) {
442
+ return null;
443
+ }
444
+ return body;
445
+ } catch {
446
+ return null;
447
+ }
448
+ };
449
+ var fetchNoticeConsentStatus = async ({
450
+ accessToken,
451
+ ledgerBaseUrl,
452
+ noticeUuid,
453
+ signal
454
+ }) => {
455
+ if (!accessToken || !ledgerBaseUrl || !noticeUuid) {
456
+ return null;
457
+ }
458
+ const decodedToken = decodeNoticeConsentToken(accessToken);
459
+ if (!decodedToken) {
460
+ return null;
461
+ }
462
+ const {
463
+ organisation_uuid: ORGANISATION_UUID,
464
+ workspace_uuid: WORKSPACE_UUID
465
+ } = decodedToken;
466
+ if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
467
+ return null;
468
+ }
469
+ return fetchNoticeConsentStatusForScope({
470
+ accessToken,
471
+ ledgerBaseUrl,
472
+ organisationUuid: ORGANISATION_UUID,
473
+ workspaceUuid: WORKSPACE_UUID,
474
+ noticeUuid,
475
+ signal
476
+ });
477
+ };
478
+ var isNoticeFullyConsented = (status) => status.consented && status.all_mandatory_active;
479
+ var buildLedgerConsentOverlay = (status, configPurposes) => {
480
+ var _a, _b;
481
+ const byUuid = new Map(status.purposes.map((p) => [p.uuid, p]));
482
+ const hasHistory = status.purposes.some(
483
+ (p) => (p.status || "INACTIVE") !== "INACTIVE"
484
+ );
485
+ if (!hasHistory) {
486
+ return null;
487
+ }
488
+ const purpose_selections = {};
489
+ for (const cp of configPurposes) {
490
+ const lp = byUuid.get(cp.uuid);
491
+ const purposeStatus = (lp == null ? void 0 : lp.status) || "INACTIVE";
492
+ const selectedByUuid = new Map(
493
+ ((lp == null ? void 0 : lp.data_elements) || []).map((de) => [de.uuid, de.selected])
494
+ );
495
+ const data_elements = {};
496
+ for (const de of cp.data_elements) {
497
+ data_elements[de.uuid] = {
498
+ selected: (_a = selectedByUuid.get(de.uuid)) != null ? _a : false,
499
+ enabled: de.enabled,
500
+ required: de.required
501
+ };
502
+ }
503
+ purpose_selections[cp.uuid] = {
504
+ selected: (_b = lp == null ? void 0 : lp.selected) != null ? _b : false,
505
+ status: purposeStatus,
506
+ needs_reconsent: purposeStatus !== "ACTIVE",
507
+ data_elements
508
+ };
509
+ }
510
+ const reconsent_required = configPurposes.some(
511
+ (cp) => {
512
+ var _a2;
513
+ return (((_a2 = purpose_selections[cp.uuid]) == null ? void 0 : _a2.status) || "INACTIVE") !== "ACTIVE";
514
+ }
515
+ );
516
+ return { reconsent_required, purpose_selections };
517
+ };
518
+
402
519
  // src/RedactoNoticeConsent/components/Checkbox.tsx
403
520
  import { TouchableOpacity, View, StyleSheet } from "react-native";
404
521
  import Svg, { Path } from "react-native-svg";
@@ -1629,6 +1746,7 @@ var RedactoNoticeConsent = ({
1629
1746
  accessToken,
1630
1747
  refreshToken: _refreshToken,
1631
1748
  baseUrl,
1749
+ ledgerBaseUrl,
1632
1750
  settings,
1633
1751
  language = "en",
1634
1752
  blockUI = false,
@@ -1688,6 +1806,7 @@ var RedactoNoticeConsent = ({
1688
1806
  const abortControllerRef = useRef2(null);
1689
1807
  const hasBootstrappedLanguageRef = useRef2(false);
1690
1808
  const fetchContent = useCallback(async () => {
1809
+ var _a2, _b2;
1691
1810
  if (abortControllerRef.current) {
1692
1811
  abortControllerRef.current.abort();
1693
1812
  }
@@ -1706,8 +1825,23 @@ var RedactoNoticeConsent = ({
1706
1825
  signal: abortControllerRef.current.signal
1707
1826
  });
1708
1827
  const activeConfig2 = data.detail.active_config;
1709
- const purposeSelections = data.detail.purpose_selections;
1710
- const reconsentRequired = data.detail.reconsent_required || false;
1828
+ let purposeSelections = data.detail.purpose_selections;
1829
+ let reconsentRequired = data.detail.reconsent_required || false;
1830
+ if (ledgerBaseUrl && !applicationId) {
1831
+ const ledgerStatus = await fetchNoticeConsentStatus({
1832
+ accessToken,
1833
+ ledgerBaseUrl,
1834
+ noticeUuid: noticeId,
1835
+ signal: (_a2 = abortControllerRef.current) == null ? void 0 : _a2.signal
1836
+ });
1837
+ if (ledgerStatus) {
1838
+ const overlay = buildLedgerConsentOverlay(ledgerStatus, activeConfig2.purposes);
1839
+ reconsentRequired = (_b2 = overlay == null ? void 0 : overlay.reconsent_required) != null ? _b2 : false;
1840
+ purposeSelections = overlay == null ? void 0 : overlay.purpose_selections;
1841
+ data.detail.purpose_selections = purposeSelections;
1842
+ data.detail.reconsent_required = reconsentRequired;
1843
+ }
1844
+ }
1711
1845
  const noticeIsMinor = data.detail.is_minor || false;
1712
1846
  setIsMinor(noticeIsMinor);
1713
1847
  const initialCollapsed = {};
@@ -1720,9 +1854,9 @@ var RedactoNoticeConsent = ({
1720
1854
  const purposeSelected = sel ? sel.selected : false;
1721
1855
  initialPurposeState[purpose.uuid] = purposeSelected;
1722
1856
  purpose.data_elements.forEach((el) => {
1723
- var _a2, _b2, _c2;
1857
+ var _a3, _b3, _c2;
1724
1858
  const combinedId = `${purpose.uuid}-${el.uuid}`;
1725
- const elementSel = (_c2 = (_b2 = (_a2 = sel == null ? void 0 : sel.data_elements) == null ? void 0 : _a2[el.uuid]) == null ? void 0 : _b2.selected) != null ? _c2 : false;
1859
+ const elementSel = (_c2 = (_b3 = (_a3 = sel == null ? void 0 : sel.data_elements) == null ? void 0 : _a3[el.uuid]) == null ? void 0 : _b3.selected) != null ? _c2 : false;
1726
1860
  initialDataElementState[combinedId] = elementSel;
1727
1861
  initialDataElementSelectionsMap[combinedId] = elementSel;
1728
1862
  });
@@ -1770,7 +1904,7 @@ var RedactoNoticeConsent = ({
1770
1904
  } finally {
1771
1905
  setIsLoading(false);
1772
1906
  }
1773
- }, [noticeId, accessToken, baseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
1907
+ }, [noticeId, accessToken, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
1774
1908
  useEffect2(() => {
1775
1909
  hasBootstrappedLanguageRef.current = false;
1776
1910
  }, [noticeId, accessToken]);
@@ -2173,6 +2307,7 @@ var RedactoNoticeConsent = ({
2173
2307
  await submitConsentEvent({
2174
2308
  accessToken,
2175
2309
  baseUrl,
2310
+ ledgerBaseUrl,
2176
2311
  noticeUuid: activeConfig2.notice_uuid,
2177
2312
  purposes: activeConfig2.purposes.map((purpose) => ({
2178
2313
  ...purpose,
@@ -2200,7 +2335,7 @@ var RedactoNoticeConsent = ({
2200
2335
  } finally {
2201
2336
  setIsSubmitting(false);
2202
2337
  }
2203
- }, [content, accessToken, baseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
2338
+ }, [content, accessToken, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
2204
2339
  const handleDecline = useCallback(() => {
2205
2340
  stopAudio();
2206
2341
  stopPolling();
@@ -2861,13 +2996,14 @@ var submitConsentEvent2 = async ({
2861
2996
  workspace_uuid,
2862
2997
  accessToken,
2863
2998
  baseUrl,
2999
+ ledgerBaseUrl,
2864
3000
  noticeUuid,
2865
3001
  purposes,
2866
3002
  declined,
2867
3003
  meta_data
2868
3004
  }) => {
2869
3005
  var _a, _b;
2870
- const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
3006
+ const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
2871
3007
  const payload = {
2872
3008
  notice_uuid: noticeUuid,
2873
3009
  purposes: purposes.map((purpose) => {
@@ -3189,6 +3325,7 @@ var RedactoConsentInlineComponent = ({
3189
3325
  notice_uuid,
3190
3326
  accessToken,
3191
3327
  baseUrl,
3328
+ ledgerBaseUrl,
3192
3329
  language = "en",
3193
3330
  onAccept,
3194
3331
  onDecline: _onDecline,
@@ -3207,6 +3344,9 @@ var RedactoConsentInlineComponent = ({
3207
3344
  const [selectedPurposes, setSelectedPurposes] = useState2({});
3208
3345
  const [selectedDataElements, setSelectedDataElements] = useState2({});
3209
3346
  const [hasAlreadyConsented, setHasAlreadyConsented] = useState2(false);
3347
+ const [isCheckingConsent, setIsCheckingConsent] = useState2(
3348
+ Boolean(ledgerBaseUrl) && !applicationId
3349
+ );
3210
3350
  const [fetchError, setFetchError] = useState2(null);
3211
3351
  const [errorMessage, setErrorMessage] = useState2(null);
3212
3352
  const [isLanguageDropdownOpen, setIsLanguageDropdownOpen] = useState2(false);
@@ -3327,6 +3467,40 @@ var RedactoConsentInlineComponent = ({
3327
3467
  controller.abort();
3328
3468
  };
3329
3469
  }, [fetchNotice]);
3470
+ useEffect3(() => {
3471
+ if (!ledgerBaseUrl || applicationId) {
3472
+ return;
3473
+ }
3474
+ if (!accessToken || !content) {
3475
+ return;
3476
+ }
3477
+ let active = true;
3478
+ const controller = new AbortController();
3479
+ const checkLedgerConsent = async () => {
3480
+ try {
3481
+ const ledgerStatus = await fetchNoticeConsentStatusForScope({
3482
+ accessToken,
3483
+ ledgerBaseUrl,
3484
+ organisationUuid: org_uuid,
3485
+ workspaceUuid: workspace_uuid,
3486
+ noticeUuid: notice_uuid,
3487
+ signal: controller.signal
3488
+ });
3489
+ if (active && ledgerStatus && isNoticeFullyConsented(ledgerStatus)) {
3490
+ setHasAlreadyConsented(true);
3491
+ }
3492
+ } finally {
3493
+ if (active) {
3494
+ setIsCheckingConsent(false);
3495
+ }
3496
+ }
3497
+ };
3498
+ void checkLedgerConsent();
3499
+ return () => {
3500
+ active = false;
3501
+ controller.abort();
3502
+ };
3503
+ }, [ledgerBaseUrl, applicationId, accessToken, content, org_uuid, workspace_uuid, notice_uuid]);
3330
3504
  const togglePurposeCollapse = useCallback2((purposeUuid) => {
3331
3505
  setCollapsedPurposes((prev) => ({ ...prev, [purposeUuid]: !prev[purposeUuid] }));
3332
3506
  }, []);
@@ -3377,6 +3551,7 @@ var RedactoConsentInlineComponent = ({
3377
3551
  workspace_uuid,
3378
3552
  accessToken: tokenToUse,
3379
3553
  baseUrl,
3554
+ ledgerBaseUrl,
3380
3555
  noticeUuid: content.notice_uuid,
3381
3556
  purposes: content.purposes.map((purpose) => {
3382
3557
  const hasSelectedRequiredElement = purpose.data_elements.some(
@@ -3415,6 +3590,7 @@ var RedactoConsentInlineComponent = ({
3415
3590
  org_uuid,
3416
3591
  workspace_uuid,
3417
3592
  baseUrl,
3593
+ ledgerBaseUrl,
3418
3594
  selectedDataElements,
3419
3595
  selectedPurposes,
3420
3596
  applicationId,
@@ -3422,7 +3598,7 @@ var RedactoConsentInlineComponent = ({
3422
3598
  ]
3423
3599
  );
3424
3600
  useEffect3(() => {
3425
- if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !hasSubmittedRef.current) {
3601
+ if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !isCheckingConsent && !hasAlreadyConsented && !hasSubmittedRef.current) {
3426
3602
  hasSubmittedRef.current = true;
3427
3603
  const autoSubmit = async () => {
3428
3604
  try {
@@ -3434,7 +3610,7 @@ var RedactoConsentInlineComponent = ({
3434
3610
  };
3435
3611
  autoSubmit();
3436
3612
  }
3437
- }, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, handleAcceptWithToken, onError]);
3613
+ }, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, isCheckingConsent, hasAlreadyConsented, handleAcceptWithToken, onError]);
3438
3614
  useEffect3(() => {
3439
3615
  if (!accessToken) {
3440
3616
  hasSubmittedRef.current = false;
@@ -244,6 +244,7 @@ type UserConsent = {
244
244
  product_name?: string;
245
245
  product_description?: string | null;
246
246
  nominator_info?: NominatorInfo;
247
+ notice_uuid?: string | null;
247
248
  };
248
249
  type NominatorInfo = {
249
250
  org_user_id: string;
@@ -269,6 +270,7 @@ type PurposeItem = {
269
270
  method: string;
270
271
  data_elements: ConsentDataElement[];
271
272
  link_reason: string | null;
273
+ notice_uuid?: string | null;
272
274
  };
273
275
  type ConsentGroup = {
274
276
  product_uuid: string;
@@ -439,6 +441,8 @@ declare function useInternalNavigation(): NavigationContextType;
439
441
 
440
442
  interface RedactoPrivacyCenterProps {
441
443
  baseUrl: string;
444
+ /** Go ledger base URL — serves user-consents; omit to use the legacy Python privacy-center consent endpoints. */
445
+ ledgerBaseUrl?: string;
442
446
  slug: string;
443
447
  /**
444
448
  * @deprecated The Privacy Center now themes itself from per-org branding.
@@ -453,7 +457,7 @@ interface RedactoPrivacyCenterProps {
453
457
  initialCaseUuid?: string;
454
458
  onBack?: 'back' | 'signout';
455
459
  }
456
- declare function RedactoPrivacyCenter({ baseUrl, slug, theme: _theme, accessToken, refreshToken, onError, initialPage, initialCaseUuid, onBack, }: RedactoPrivacyCenterProps): React.JSX.Element;
460
+ declare function RedactoPrivacyCenter({ baseUrl, ledgerBaseUrl, slug, theme: _theme, accessToken, refreshToken, onError, initialPage, initialCaseUuid, onBack, }: RedactoPrivacyCenterProps): React.JSX.Element;
457
461
 
458
462
  declare function ConsentManager(): React__default.JSX.Element;
459
463
 
@@ -550,9 +554,14 @@ type BaseRequest = {
550
554
  /**
551
555
  * Consent service client factory.
552
556
  * Creates a client instance with a specific base URL.
553
- * @param baseUrl - Consent server base URL
557
+ * @param baseUrl - Consent server base URL (Python service, e.g. http://host/consent)
558
+ * @param ledgerBaseUrl - Go ledger base URL (e.g. http://host:8090/consent-ledger).
559
+ * Used for user-consents reads/writes served from the ledger's `/public/...` paths.
560
+ * When omitted, those calls fall back to the legacy Python
561
+ * `/dsar/privacy-center` endpoints and payloads (pre-ledger behavior), so
562
+ * integrations without a deployed ledger keep working.
554
563
  */
555
- declare function createConsentClient(baseUrl: string): {
564
+ declare function createConsentClient(baseUrl: string, ledgerBaseUrl?: string): {
556
565
  /**
557
566
  * Get form data (privacy center)
558
567
  */
@@ -611,9 +620,23 @@ declare function createConsentClient(baseUrl: string): {
611
620
  nominator_uuid?: string;
612
621
  }, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
613
622
  /**
614
- * Manage consent (privacy center) - revoke, regrant, or renew
623
+ * Manage consent (privacy center) - revoke, regrant, or renew.
624
+ *
625
+ * The Go ledger has no manage-consent route, so with a ledger configured
626
+ * this is expressed as a `partial` submit-consent on the ledger — mirroring
627
+ * the Python dual-write relay: the affected purpose is re-submitted with
628
+ * `selected: false` to revoke or `selected: true` to regrant/renew, and
629
+ * `partial: true` so the rest of the notice's purposes are left untouched.
630
+ * The principal is resolved from the JWT, so no `contact`/identifiers are
631
+ * sent in the body.
632
+ *
633
+ * Without a ledger, the legacy Python `/manage-consent?status=` endpoint is
634
+ * used with its `{ purpose_uuid, contact, ... }` payload.
615
635
  */
616
- manageConsent(baseRequest: BaseRequest, purposeId: string, contact: string, status: "revoke" | "regrant" | "renew", authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">, nominatorContact?: string, dataElementUuids?: string[]): Promise<unknown>;
636
+ manageConsent(baseRequest: BaseRequest, purposeId: string, contact: string, status: "revoke" | "regrant" | "renew", authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">, nominatorContact?: string, dataElementUuids?: string[], noticeUuid?: string, dataElements?: Array<{
637
+ uuid: string;
638
+ selected: boolean;
639
+ }>): Promise<unknown>;
617
640
  /**
618
641
  * Get activities (privacy center)
619
642
  */
@@ -686,11 +709,14 @@ declare function createConsentClient(baseUrl: string): {
686
709
 
687
710
  interface BaseUrlContextValue {
688
711
  baseUrl: string;
712
+ /** Go ledger base URL — serves user-consents; omit to use the legacy Python privacy-center consent endpoints. */
713
+ ledgerBaseUrl?: string;
689
714
  consentClient: ReturnType<typeof createConsentClient>;
690
715
  }
691
- declare function BaseUrlProvider({ children, baseUrl }: {
716
+ declare function BaseUrlProvider({ children, baseUrl, ledgerBaseUrl, }: {
692
717
  children: ReactNode;
693
718
  baseUrl: string;
719
+ ledgerBaseUrl?: string;
694
720
  }): React.JSX.Element;
695
721
  declare function useBaseUrl(): BaseUrlContextValue;
696
722
 
@@ -746,7 +772,7 @@ type FetchUserConsentsParams = {
746
772
  consentClient?: BaseUrlContextValue['consentClient'];
747
773
  };
748
774
  declare const fetchUserConsents: (params: FetchUserConsentsParams) => Promise<UserConsentDetail | null>;
749
- declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, }: {
775
+ declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, noticeUuid, dataElements, }: {
750
776
  organizationId: string;
751
777
  workspaceId: string;
752
778
  purposeId: string;
@@ -756,6 +782,11 @@ declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact,
756
782
  consentClient?: BaseUrlContextValue["consentClient"];
757
783
  nominatorContact?: string;
758
784
  dataElementUuids?: string[];
785
+ noticeUuid?: string;
786
+ dataElements?: Array<{
787
+ uuid: string;
788
+ selected: boolean;
789
+ }>;
759
790
  }) => Promise<boolean | null>;
760
791
  declare const fetchActivities: (organizationId: string, workspaceId: string, offset?: number, limit?: number, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<ActivityDetail | null>;
761
792
  declare const fetchCaseHistory: (organizationId: string, workspaceId: string, contact: string, offset?: number, limit?: number, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<CaseHistoryDetail | null>;
@@ -244,6 +244,7 @@ type UserConsent = {
244
244
  product_name?: string;
245
245
  product_description?: string | null;
246
246
  nominator_info?: NominatorInfo;
247
+ notice_uuid?: string | null;
247
248
  };
248
249
  type NominatorInfo = {
249
250
  org_user_id: string;
@@ -269,6 +270,7 @@ type PurposeItem = {
269
270
  method: string;
270
271
  data_elements: ConsentDataElement[];
271
272
  link_reason: string | null;
273
+ notice_uuid?: string | null;
272
274
  };
273
275
  type ConsentGroup = {
274
276
  product_uuid: string;
@@ -439,6 +441,8 @@ declare function useInternalNavigation(): NavigationContextType;
439
441
 
440
442
  interface RedactoPrivacyCenterProps {
441
443
  baseUrl: string;
444
+ /** Go ledger base URL — serves user-consents; omit to use the legacy Python privacy-center consent endpoints. */
445
+ ledgerBaseUrl?: string;
442
446
  slug: string;
443
447
  /**
444
448
  * @deprecated The Privacy Center now themes itself from per-org branding.
@@ -453,7 +457,7 @@ interface RedactoPrivacyCenterProps {
453
457
  initialCaseUuid?: string;
454
458
  onBack?: 'back' | 'signout';
455
459
  }
456
- declare function RedactoPrivacyCenter({ baseUrl, slug, theme: _theme, accessToken, refreshToken, onError, initialPage, initialCaseUuid, onBack, }: RedactoPrivacyCenterProps): React.JSX.Element;
460
+ declare function RedactoPrivacyCenter({ baseUrl, ledgerBaseUrl, slug, theme: _theme, accessToken, refreshToken, onError, initialPage, initialCaseUuid, onBack, }: RedactoPrivacyCenterProps): React.JSX.Element;
457
461
 
458
462
  declare function ConsentManager(): React__default.JSX.Element;
459
463
 
@@ -550,9 +554,14 @@ type BaseRequest = {
550
554
  /**
551
555
  * Consent service client factory.
552
556
  * Creates a client instance with a specific base URL.
553
- * @param baseUrl - Consent server base URL
557
+ * @param baseUrl - Consent server base URL (Python service, e.g. http://host/consent)
558
+ * @param ledgerBaseUrl - Go ledger base URL (e.g. http://host:8090/consent-ledger).
559
+ * Used for user-consents reads/writes served from the ledger's `/public/...` paths.
560
+ * When omitted, those calls fall back to the legacy Python
561
+ * `/dsar/privacy-center` endpoints and payloads (pre-ledger behavior), so
562
+ * integrations without a deployed ledger keep working.
554
563
  */
555
- declare function createConsentClient(baseUrl: string): {
564
+ declare function createConsentClient(baseUrl: string, ledgerBaseUrl?: string): {
556
565
  /**
557
566
  * Get form data (privacy center)
558
567
  */
@@ -611,9 +620,23 @@ declare function createConsentClient(baseUrl: string): {
611
620
  nominator_uuid?: string;
612
621
  }, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
613
622
  /**
614
- * Manage consent (privacy center) - revoke, regrant, or renew
623
+ * Manage consent (privacy center) - revoke, regrant, or renew.
624
+ *
625
+ * The Go ledger has no manage-consent route, so with a ledger configured
626
+ * this is expressed as a `partial` submit-consent on the ledger — mirroring
627
+ * the Python dual-write relay: the affected purpose is re-submitted with
628
+ * `selected: false` to revoke or `selected: true` to regrant/renew, and
629
+ * `partial: true` so the rest of the notice's purposes are left untouched.
630
+ * The principal is resolved from the JWT, so no `contact`/identifiers are
631
+ * sent in the body.
632
+ *
633
+ * Without a ledger, the legacy Python `/manage-consent?status=` endpoint is
634
+ * used with its `{ purpose_uuid, contact, ... }` payload.
615
635
  */
616
- manageConsent(baseRequest: BaseRequest, purposeId: string, contact: string, status: "revoke" | "regrant" | "renew", authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">, nominatorContact?: string, dataElementUuids?: string[]): Promise<unknown>;
636
+ manageConsent(baseRequest: BaseRequest, purposeId: string, contact: string, status: "revoke" | "regrant" | "renew", authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">, nominatorContact?: string, dataElementUuids?: string[], noticeUuid?: string, dataElements?: Array<{
637
+ uuid: string;
638
+ selected: boolean;
639
+ }>): Promise<unknown>;
617
640
  /**
618
641
  * Get activities (privacy center)
619
642
  */
@@ -686,11 +709,14 @@ declare function createConsentClient(baseUrl: string): {
686
709
 
687
710
  interface BaseUrlContextValue {
688
711
  baseUrl: string;
712
+ /** Go ledger base URL — serves user-consents; omit to use the legacy Python privacy-center consent endpoints. */
713
+ ledgerBaseUrl?: string;
689
714
  consentClient: ReturnType<typeof createConsentClient>;
690
715
  }
691
- declare function BaseUrlProvider({ children, baseUrl }: {
716
+ declare function BaseUrlProvider({ children, baseUrl, ledgerBaseUrl, }: {
692
717
  children: ReactNode;
693
718
  baseUrl: string;
719
+ ledgerBaseUrl?: string;
694
720
  }): React.JSX.Element;
695
721
  declare function useBaseUrl(): BaseUrlContextValue;
696
722
 
@@ -746,7 +772,7 @@ type FetchUserConsentsParams = {
746
772
  consentClient?: BaseUrlContextValue['consentClient'];
747
773
  };
748
774
  declare const fetchUserConsents: (params: FetchUserConsentsParams) => Promise<UserConsentDetail | null>;
749
- declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, }: {
775
+ declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, noticeUuid, dataElements, }: {
750
776
  organizationId: string;
751
777
  workspaceId: string;
752
778
  purposeId: string;
@@ -756,6 +782,11 @@ declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact,
756
782
  consentClient?: BaseUrlContextValue["consentClient"];
757
783
  nominatorContact?: string;
758
784
  dataElementUuids?: string[];
785
+ noticeUuid?: string;
786
+ dataElements?: Array<{
787
+ uuid: string;
788
+ selected: boolean;
789
+ }>;
759
790
  }) => Promise<boolean | null>;
760
791
  declare const fetchActivities: (organizationId: string, workspaceId: string, offset?: number, limit?: number, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<ActivityDetail | null>;
761
792
  declare const fetchCaseHistory: (organizationId: string, workspaceId: string, contact: string, offset?: number, limit?: number, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<CaseHistoryDetail | null>;