@redacto.io/consent-sdk-react-native 5.0.0-beta.5 → 5.0.0-beta.7

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/README.md CHANGED
@@ -64,6 +64,81 @@ pnpm add @tanstack/react-query i18next react-i18next dayjs \
64
64
 
65
65
  > **Note:** `react-native-svg` must be linked for native builds. Follow the [react-native-svg setup guide](https://github.com/software-mansion/react-native-svg#installation).
66
66
 
67
+ ## Sandbox Mode (No Backend Required)
68
+
69
+ Sandbox mode lets you build and test a full consent PoC — **notice → Privacy Center → DSAR** — straight from your app, with **no backend and no token minting**. Instead of your server generating a JWT, you paste a **static sandbox token** into the SDK. Everything you create is recorded as test data, isolated from your live records.
70
+
71
+ Going live is a config swap, not a rewrite: drop the sandbox props and pass a real JWT (see [Backend Server Setup](#backend-server-setup)).
72
+
73
+ ### 1. Get your sandbox credentials
74
+
75
+ In the **Redacto Dashboard → API Keys → Sandbox** tab, copy:
76
+
77
+ - your **Sandbox token** (a static string; it never expires and needs no refresh)
78
+ - your **Organization ID** and **Workspace ID** (shown under *Workspace identifiers* on the same page)
79
+
80
+ ### 2. Collect consent
81
+
82
+ Pass the sandbox `token`, org/workspace, and a test identity (`email`, `mobile`, or `ucic`). No `accessToken` is needed:
83
+
84
+ ```tsx
85
+ import { RedactoNoticeConsent } from "@redacto.io/consent-sdk-react-native";
86
+
87
+ <RedactoNoticeConsent
88
+ noticeId={NOTICE_UUID}
89
+ token={SANDBOX_TOKEN}
90
+ organisationUuid={ORG_UUID}
91
+ workspaceUuid={WORKSPACE_UUID}
92
+ email="test.user@example.com" // or `mobile`, or `ucic`
93
+ onAccept={() => console.log("consent recorded (test)")}
94
+ onDecline={() => {}}
95
+ />;
96
+ ```
97
+
98
+ ### 3. Manage consent & raise a DSAR
99
+
100
+ Point the Privacy Center at the same sandbox token and test identity. The same test user can now review the consent from step 2, withdraw it, and file a DSAR — end to end, all as test data:
101
+
102
+ ```tsx
103
+ import { RedactoPrivacyCenter } from "@redacto.io/consent-sdk-react-native/privacy-center";
104
+
105
+ <RedactoPrivacyCenter
106
+ baseUrl={BASE_URL}
107
+ slug="acme-co"
108
+ token={SANDBOX_TOKEN}
109
+ organisationUuid={ORG_UUID}
110
+ workspaceUuid={WORKSPACE_UUID}
111
+ email="test.user@example.com" // or `mobile`, or `ucic`
112
+ onError={(error) => {
113
+ console.error(error);
114
+ return false;
115
+ }}
116
+ />;
117
+ ```
118
+
119
+ ### Sandbox props
120
+
121
+ Both `RedactoNoticeConsent` and `RedactoPrivacyCenter` accept the same sandbox props:
122
+
123
+ | Prop | Required | Description |
124
+ | --------------------------- | ------------ | ----------------------------------------------------------------------------------- |
125
+ | `token` | Yes | Static sandbox token from the Dashboard. Its presence activates sandbox mode. |
126
+ | `organisationUuid` | Yes | Organization ID from the Dashboard. |
127
+ | `workspaceUuid` | Yes | Workspace ID from the Dashboard. |
128
+ | `email` / `mobile` / `ucic` | One required | The test subject. Precedence when more than one is set: `ucic` > `email` > `mobile`. |
129
+
130
+ ### How it works
131
+
132
+ - The SDK sends the sandbox token as an `X-Consent-Token` header and the test identity inside each request (query params on reads, body on writes) — no JWT decode, no token refresh (a `401` fails fast).
133
+ - The server records everything under `environment=test`, namespaced so sandbox data never mixes with — or reads — your live records.
134
+ - Sandbox always talks to the consent server; it never routes to the Go ledger.
135
+
136
+ ### Going live
137
+
138
+ Sandbox and production use the same components. To ship, remove the sandbox props and pass a real `accessToken` / `refreshToken` (JWT) minted by your backend — see [Backend Server Setup](#backend-server-setup) below. New records are then written as `environment=live`.
139
+
140
+ > Sandbox is available on `RedactoNoticeConsent` and `RedactoPrivacyCenter`. The inline widget (`RedactoNoticeConsentInline`) is JWT-only.
141
+
67
142
  ## Backend Server Setup
68
143
 
69
144
  The SDK never talks to Redacto with your CMS API key directly — your backend acts as a token broker. Obtain your **CMS-API-Key** from the Redacto Dashboard, store it in your backend's environment, and expose two endpoints to your mobile app:
@@ -49,8 +49,12 @@ function toLanguageCode(lang) {
49
49
  return (_c = (_b = (_a = codeByLabel.get(trimmed)) != null ? _a : codeByName.get(lower)) != null ? _b : codeByLower.get(lower)) != null ? _c : trimmed;
50
50
  }
51
51
 
52
+ // src/shared/sandbox.ts
53
+ var SANDBOX_TOKEN_HEADER = "X-Consent-Token";
54
+
52
55
  export {
53
56
  __require,
57
+ SANDBOX_TOKEN_HEADER,
54
58
  languageOptions,
55
59
  toLanguageCode
56
60
  };
package/dist/index.d.mts CHANGED
@@ -28,8 +28,34 @@ type Settings$1 = {
28
28
 
29
29
  type Props$1 = Readonly<{
30
30
  noticeId: string;
31
- accessToken: string;
32
- refreshToken: string;
31
+ /**
32
+ * JWT access token. Optional so sandbox integrations (see `token`) can
33
+ * omit it. Required in the normal JWT flow.
34
+ */
35
+ accessToken?: string;
36
+ /** JWT refresh token. Optional; accepted for source-compat, currently unused. */
37
+ refreshToken?: string;
38
+ /**
39
+ * Sandbox PoC: a pasted static token. When set, the SDK runs against the
40
+ * sandbox with no JWT — it sends the single `X-Consent-Token` header, carries
41
+ * the acting identity (`email` || `mobile` || `ucic`) in each request's own
42
+ * payload, takes org/workspace from `organisationUuid`/`workspaceUuid`, and
43
+ * does no token refresh.
44
+ */
45
+ token?: string;
46
+ /** Sandbox test subject email (carried in the request payload when set). */
47
+ email?: string;
48
+ /** Sandbox test subject mobile (fallback subject when `email` is absent). */
49
+ mobile?: string;
50
+ /**
51
+ * Sandbox UCIC: the client's own user id / org_user_id, e.g. a UUID or
52
+ * customer code; optional third identifier alongside email/mobile.
53
+ */
54
+ ucic?: string;
55
+ /** Sandbox org UUID (replaces the JWT-decoded org in sandbox mode). */
56
+ organisationUuid?: string;
57
+ /** Sandbox workspace UUID (replaces the JWT-decoded workspace in sandbox mode). */
58
+ workspaceUuid?: string;
33
59
  baseUrl?: string;
34
60
  /** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
35
61
  ledgerBaseUrl?: string;
package/dist/index.d.ts CHANGED
@@ -28,8 +28,34 @@ type Settings$1 = {
28
28
 
29
29
  type Props$1 = Readonly<{
30
30
  noticeId: string;
31
- accessToken: string;
32
- refreshToken: string;
31
+ /**
32
+ * JWT access token. Optional so sandbox integrations (see `token`) can
33
+ * omit it. Required in the normal JWT flow.
34
+ */
35
+ accessToken?: string;
36
+ /** JWT refresh token. Optional; accepted for source-compat, currently unused. */
37
+ refreshToken?: string;
38
+ /**
39
+ * Sandbox PoC: a pasted static token. When set, the SDK runs against the
40
+ * sandbox with no JWT — it sends the single `X-Consent-Token` header, carries
41
+ * the acting identity (`email` || `mobile` || `ucic`) in each request's own
42
+ * payload, takes org/workspace from `organisationUuid`/`workspaceUuid`, and
43
+ * does no token refresh.
44
+ */
45
+ token?: string;
46
+ /** Sandbox test subject email (carried in the request payload when set). */
47
+ email?: string;
48
+ /** Sandbox test subject mobile (fallback subject when `email` is absent). */
49
+ mobile?: string;
50
+ /**
51
+ * Sandbox UCIC: the client's own user id / org_user_id, e.g. a UUID or
52
+ * customer code; optional third identifier alongside email/mobile.
53
+ */
54
+ ucic?: string;
55
+ /** Sandbox org UUID (replaces the JWT-decoded org in sandbox mode). */
56
+ organisationUuid?: string;
57
+ /** Sandbox workspace UUID (replaces the JWT-decoded workspace in sandbox mode). */
58
+ workspaceUuid?: string;
33
59
  baseUrl?: string;
34
60
  /** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
35
61
  ledgerBaseUrl?: string;
package/dist/index.js CHANGED
@@ -43,6 +43,67 @@ var import_react_native_svg3 = __toESM(require("react-native-svg"));
43
43
  // src/RedactoNoticeConsent/api/index.ts
44
44
  var import_jwt_decode = require("jwt-decode");
45
45
 
46
+ // src/shared/sandbox.ts
47
+ var SANDBOX_TOKEN_HEADER = "X-Consent-Token";
48
+
49
+ // src/RedactoNoticeConsent/api/sandbox.ts
50
+ var resolveSandboxAuth = (params) => {
51
+ var _a, _b, _c, _d, _e;
52
+ const token = (_a = params.token) == null ? void 0 : _a.trim();
53
+ if (!token) {
54
+ return null;
55
+ }
56
+ const organisationUuid = (_b = params.organisationUuid) == null ? void 0 : _b.trim();
57
+ const workspaceUuid = (_c = params.workspaceUuid) == null ? void 0 : _c.trim();
58
+ const ucic = (_d = params.sandboxUcic) == null ? void 0 : _d.trim();
59
+ const subject = (_e = params.sandboxSubject) == null ? void 0 : _e.trim();
60
+ if (!organisationUuid || !workspaceUuid) {
61
+ throw new Error(
62
+ "Sandbox mode requires organisationUuid and workspaceUuid props"
63
+ );
64
+ }
65
+ if (!ucic && !subject) {
66
+ throw new Error("Sandbox mode requires a UCIC, email, or mobile");
67
+ }
68
+ return { token, ucic, subject: subject != null ? subject : "", organisationUuid, workspaceUuid };
69
+ };
70
+ var resolveRequestAuth = (accessToken, sandboxParams, decodeTokenSafely2) => {
71
+ const sandbox = resolveSandboxAuth(sandboxParams);
72
+ if (sandbox) {
73
+ return {
74
+ organisationUuid: sandbox.organisationUuid,
75
+ workspaceUuid: sandbox.workspaceUuid,
76
+ sandbox
77
+ };
78
+ }
79
+ const decodedToken = accessToken ? decodeTokenSafely2(accessToken) : null;
80
+ if (!decodedToken) {
81
+ throw new Error("Invalid access token");
82
+ }
83
+ const { organisation_uuid, workspace_uuid } = decodedToken;
84
+ if (!organisation_uuid || !workspace_uuid) {
85
+ throw new Error("Invalid token: missing organization or workspace UUID");
86
+ }
87
+ return {
88
+ organisationUuid: organisation_uuid,
89
+ workspaceUuid: workspace_uuid,
90
+ sandbox: null
91
+ };
92
+ };
93
+ var buildAuthHeaders = (accessToken, sandbox) => {
94
+ if (sandbox) {
95
+ return { [SANDBOX_TOKEN_HEADER]: sandbox.token };
96
+ }
97
+ return { Authorization: `Bearer ${accessToken}` };
98
+ };
99
+ var sandboxBodyIdentity = (sandbox) => {
100
+ if (sandbox.ucic) {
101
+ return { org_user_id: sandbox.ucic };
102
+ }
103
+ return sandbox.subject.includes("@") ? { primary_email: sandbox.subject } : { primary_mobile: sandbox.subject };
104
+ };
105
+ var sandboxQueryIdentity = (sandbox) => sandboxBodyIdentity(sandbox);
106
+
46
107
  // src/constants.ts
47
108
  var DEFAULT_CONSENT_API_BASE_URL = "https://api.redacto.io/consent";
48
109
 
@@ -125,21 +186,19 @@ var fetchConsentContent = async ({
125
186
  specific_uuid,
126
187
  validate_against = "all",
127
188
  include_fully_consented_data = false,
128
- signal
189
+ signal,
190
+ ...sandboxParams
129
191
  }) => {
130
- if (!noticeId || !accessToken || !validate_against) {
131
- throw new Error("noticeId and accessToken are required");
192
+ if (!noticeId || !validate_against) {
193
+ throw new Error("noticeId is required");
132
194
  }
133
- const decodedToken = decodeTokenSafely(accessToken);
134
- if (!decodedToken) {
135
- throw new Error("Invalid access token");
136
- }
137
- const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
138
- if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
139
- throw new Error("Invalid token: missing organization or workspace UUID");
195
+ if (!accessToken && !sandboxParams.token) {
196
+ throw new Error("accessToken or token is required");
140
197
  }
198
+ const { organisationUuid: ORGANISATION_UUID, workspaceUuid: WORKSPACE_UUID, sandbox } = resolveRequestAuth(accessToken, sandboxParams, decodeTokenSafely);
141
199
  const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
142
- const cacheKey = `${accessToken}-${noticeId}-${validate_against}-${language}-${specific_uuid || ""}-${include_fully_consented_data}`;
200
+ const cacheIdentity = sandbox ? `sandbox:${sandbox.organisationUuid}:${sandbox.workspaceUuid}:${sandbox.ucic || sandbox.subject}` : accessToken;
201
+ const cacheKey = `${cacheIdentity}-${noticeId}-${validate_against}-${language}-${specific_uuid || ""}-${include_fully_consented_data}`;
143
202
  if (validate_against === "all" && !specific_uuid) {
144
203
  const cachedData = getCachedData(cacheKey);
145
204
  if (cachedData) {
@@ -156,10 +215,15 @@ var fetchConsentContent = async ({
156
215
  if (include_fully_consented_data) {
157
216
  url.searchParams.append("include_fully_consented_data", "true");
158
217
  }
218
+ if (sandbox) {
219
+ for (const [key, value] of Object.entries(sandboxQueryIdentity(sandbox))) {
220
+ url.searchParams.append(key, value);
221
+ }
222
+ }
159
223
  const response = await fetch(url.toString(), {
160
224
  method: "GET",
161
225
  headers: {
162
- Authorization: `Bearer ${accessToken}`,
226
+ ...buildAuthHeaders(accessToken, sandbox),
163
227
  "Accept-Language": language,
164
228
  "Content-Type": "application/json"
165
229
  },
@@ -199,20 +263,17 @@ var submitConsentEvent = async ({
199
263
  guardianVerificationReference,
200
264
  selfDeclaredAdult,
201
265
  language,
202
- signal
266
+ signal,
267
+ ...sandboxParams
203
268
  }) => {
204
- if (!noticeUuid || !accessToken || !Array.isArray(purposes)) {
205
- throw new Error("noticeUuid, accessToken, and purposes array are required");
269
+ if (!noticeUuid || !Array.isArray(purposes)) {
270
+ throw new Error("noticeUuid and purposes array are required");
206
271
  }
207
- const decodedToken = decodeTokenSafely(accessToken);
208
- if (!decodedToken) {
209
- throw new Error("Invalid access token");
272
+ if (!accessToken && !sandboxParams.token) {
273
+ throw new Error("accessToken or token is required");
210
274
  }
211
- const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
212
- if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
213
- throw new Error("Invalid token: missing organization or workspace UUID");
214
- }
215
- const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
275
+ const { organisationUuid: ORGANISATION_UUID, workspaceUuid: WORKSPACE_UUID, sandbox } = resolveRequestAuth(accessToken, sandboxParams, decodeTokenSafely);
276
+ const apiBaseUrl = (sandbox ? null : ledgerBaseUrl) || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
216
277
  const validatedPurposes = purposes.map((purpose) => {
217
278
  if (!purpose.uuid) {
218
279
  throw new Error("Invalid purpose data: missing uuid");
@@ -238,15 +299,16 @@ var submitConsentEvent = async ({
238
299
  self_declared_adult: selfDeclaredAdult,
239
300
  language: toLanguageCode(language)
240
301
  };
302
+ const requestBody = sandbox ? { ...payload, ...sandboxBodyIdentity(sandbox) } : payload;
241
303
  const response = await fetch(
242
304
  `${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/submit-consent`,
243
305
  {
244
306
  method: "POST",
245
307
  headers: {
246
- Authorization: `Bearer ${accessToken}`,
308
+ ...buildAuthHeaders(accessToken, sandbox),
247
309
  "Content-Type": "application/json"
248
310
  },
249
- body: JSON.stringify(payload),
311
+ body: JSON.stringify(requestBody),
250
312
  signal
251
313
  }
252
314
  );
@@ -274,26 +336,27 @@ var fetchTTSAudioUrls = async ({
274
336
  baseUrl,
275
337
  noticeUuid,
276
338
  language,
277
- signal
339
+ signal,
340
+ ...sandboxParams
278
341
  }) => {
279
- if (!accessToken || !noticeUuid || !language) {
280
- throw new Error("accessToken, noticeUuid, and language are required");
281
- }
282
- const decodedToken = decodeTokenSafely(accessToken);
283
- if (!decodedToken) {
284
- throw new Error("Invalid access token");
285
- }
286
- const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
287
- if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
288
- throw new Error("Invalid token: missing organization or workspace UUID");
342
+ if (!accessToken && !sandboxParams.token || !noticeUuid || !language) {
343
+ throw new Error("accessToken (or token), noticeUuid, and language are required");
289
344
  }
345
+ const { organisationUuid: ORGANISATION_UUID, workspaceUuid: WORKSPACE_UUID, sandbox } = resolveRequestAuth(accessToken, sandboxParams, decodeTokenSafely);
290
346
  const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
291
347
  const normalizedLanguage = language === "en" || language === "EN" ? "English" : language;
292
- const url = `${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/audio/${encodeURIComponent(normalizedLanguage)}`;
293
- const response = await fetch(url, {
348
+ const url = new URL(
349
+ `${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/audio/${encodeURIComponent(normalizedLanguage)}`
350
+ );
351
+ if (sandbox) {
352
+ for (const [key, value] of Object.entries(sandboxQueryIdentity(sandbox))) {
353
+ url.searchParams.append(key, value);
354
+ }
355
+ }
356
+ const response = await fetch(url.toString(), {
294
357
  method: "GET",
295
358
  headers: {
296
- Authorization: `Bearer ${accessToken}`,
359
+ ...buildAuthHeaders(accessToken, sandbox),
297
360
  Accept: "application/json",
298
361
  "Content-Type": "application/json"
299
362
  },
@@ -1800,6 +1863,12 @@ var RedactoNoticeConsent = ({
1800
1863
  noticeId,
1801
1864
  accessToken,
1802
1865
  refreshToken: _refreshToken,
1866
+ token,
1867
+ email,
1868
+ mobile,
1869
+ ucic,
1870
+ organisationUuid,
1871
+ workspaceUuid,
1803
1872
  baseUrl,
1804
1873
  ledgerBaseUrl,
1805
1874
  settings,
@@ -1815,6 +1884,16 @@ var RedactoNoticeConsent = ({
1815
1884
  }) => {
1816
1885
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
1817
1886
  const { isMobile } = useResponsive();
1887
+ const sandboxParams = (0, import_react2.useMemo)(
1888
+ () => ({
1889
+ token,
1890
+ sandboxUcic: ucic,
1891
+ sandboxSubject: email || mobile,
1892
+ organisationUuid,
1893
+ workspaceUuid
1894
+ }),
1895
+ [token, ucic, email, mobile, organisationUuid, workspaceUuid]
1896
+ );
1818
1897
  const [content, setContent] = (0, import_react2.useState)(null);
1819
1898
  const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
1820
1899
  const [isSubmitting, setIsSubmitting] = (0, import_react2.useState)(false);
@@ -1877,12 +1956,13 @@ var RedactoNoticeConsent = ({
1877
1956
  validate_against: validateAgainst,
1878
1957
  include_fully_consented_data: includeFullyConsentedData,
1879
1958
  specific_uuid: applicationId,
1880
- signal: abortControllerRef.current.signal
1959
+ signal: abortControllerRef.current.signal,
1960
+ ...sandboxParams
1881
1961
  });
1882
1962
  const activeConfig2 = data.detail.active_config;
1883
1963
  let purposeSelections = data.detail.purpose_selections;
1884
1964
  let reconsentRequired = data.detail.reconsent_required || false;
1885
- if (ledgerBaseUrl && !applicationId) {
1965
+ if (accessToken && ledgerBaseUrl && !applicationId && !token) {
1886
1966
  const ledgerStatus = await fetchNoticeConsentStatus({
1887
1967
  accessToken,
1888
1968
  ledgerBaseUrl,
@@ -1959,7 +2039,7 @@ var RedactoNoticeConsent = ({
1959
2039
  } finally {
1960
2040
  setIsLoading(false);
1961
2041
  }
1962
- }, [noticeId, accessToken, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
2042
+ }, [noticeId, accessToken, sandboxParams, token, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
1963
2043
  (0, import_react2.useEffect)(() => {
1964
2044
  hasBootstrappedLanguageRef.current = false;
1965
2045
  }, [noticeId, accessToken]);
@@ -1981,7 +2061,8 @@ var RedactoNoticeConsent = ({
1981
2061
  accessToken,
1982
2062
  baseUrl,
1983
2063
  noticeUuid: content.detail.active_config.notice_uuid,
1984
- language: selectedLanguage
2064
+ language: selectedLanguage,
2065
+ ...sandboxParams
1985
2066
  });
1986
2067
  const urls = {
1987
2068
  notice_text: data.detail.notice_text_audio_url,
@@ -2035,7 +2116,7 @@ var RedactoNoticeConsent = ({
2035
2116
  setTtsAudioUrls({});
2036
2117
  setIsTTSAvailable(false);
2037
2118
  }
2038
- }, [content, accessToken, baseUrl, selectedLanguage]);
2119
+ }, [content, accessToken, sandboxParams, baseUrl, selectedLanguage]);
2039
2120
  const clearPlaybackWatchers = (0, import_react2.useCallback)(() => {
2040
2121
  if (playbackSubscriptionRef.current) {
2041
2122
  playbackSubscriptionRef.current.remove();
@@ -2376,7 +2457,8 @@ var RedactoNoticeConsent = ({
2376
2457
  meta_data: applicationId ? { specific_uuid: applicationId } : void 0,
2377
2458
  guardianVerificationReference: verificationReferenceRef.current || void 0,
2378
2459
  selfDeclaredAdult: selfDeclaredAdult || void 0,
2379
- language: selectedLanguage
2460
+ language: selectedLanguage,
2461
+ ...sandboxParams
2380
2462
  });
2381
2463
  await stopAudio();
2382
2464
  clearApiCache();
@@ -2391,7 +2473,7 @@ var RedactoNoticeConsent = ({
2391
2473
  } finally {
2392
2474
  setIsSubmitting(false);
2393
2475
  }
2394
- }, [content, accessToken, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, selectedLanguage, stopAudio, onAccept, onError]);
2476
+ }, [content, accessToken, sandboxParams, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, selectedLanguage, selfDeclaredAdult, stopAudio, onAccept, onError]);
2395
2477
  const handleDecline = (0, import_react2.useCallback)(() => {
2396
2478
  stopAudio();
2397
2479
  stopPolling();
@@ -2993,14 +3075,16 @@ var fetchConsentContent2 = async ({
2993
3075
  org_uuid,
2994
3076
  workspace_uuid,
2995
3077
  notice_uuid,
3078
+ accessToken,
2996
3079
  baseUrl,
2997
3080
  language = "en",
2998
3081
  specific_uuid,
2999
3082
  signal
3000
3083
  }) => {
3001
3084
  const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
3085
+ const noticesUrl = `${apiBaseUrl}/public/organisations/${org_uuid}/workspaces/${workspace_uuid}/notices`;
3002
3086
  const url = new URL(
3003
- `${apiBaseUrl}/public/organisations/${org_uuid}/workspaces/${workspace_uuid}/notices/get-notice/${notice_uuid}`
3087
+ accessToken ? `${noticesUrl}/${notice_uuid}` : `${noticesUrl}/get-notice/${notice_uuid}`
3004
3088
  );
3005
3089
  if (specific_uuid) {
3006
3090
  url.searchParams.append("specific_uuid", specific_uuid);
@@ -3009,7 +3093,8 @@ var fetchConsentContent2 = async ({
3009
3093
  method: "GET",
3010
3094
  headers: {
3011
3095
  "Content-Type": "application/json",
3012
- "Accept-Language": language
3096
+ "Accept-Language": language,
3097
+ ...accessToken ? { Authorization: `Bearer ${accessToken}` } : {}
3013
3098
  },
3014
3099
  signal
3015
3100
  });
@@ -3450,11 +3535,13 @@ var RedactoConsentInlineComponent = ({
3450
3535
  const fetchNotice = (0, import_react3.useCallback)(async (signal) => {
3451
3536
  setIsLoading(true);
3452
3537
  setFetchError(null);
3538
+ setHasAlreadyConsented(false);
3453
3539
  try {
3454
3540
  const consentContentData = await fetchConsentContent2({
3455
3541
  org_uuid,
3456
3542
  workspace_uuid,
3457
3543
  notice_uuid,
3544
+ accessToken,
3458
3545
  baseUrl,
3459
3546
  language,
3460
3547
  specific_uuid: applicationId,
@@ -3504,7 +3591,7 @@ var RedactoConsentInlineComponent = ({
3504
3591
  setIsLoading(false);
3505
3592
  }
3506
3593
  }
3507
- }, [org_uuid, workspace_uuid, notice_uuid, baseUrl, language, applicationId, onError]);
3594
+ }, [org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, language, applicationId, onError]);
3508
3595
  (0, import_react3.useEffect)(() => {
3509
3596
  const controller = new AbortController();
3510
3597
  void fetchNotice(controller.signal);