redacto_consent_sdk 2.0.0 copy "redacto_consent_sdk: ^2.0.0" to clipboard
redacto_consent_sdk: ^2.0.0 copied to clipboard

Flutter SDK for integrating Redacto consent notices.

Changelog #

2.0.0 #

Stable M3 release, versioned alongside @redacto.io/consent-sdk-js 1.0.0, @redacto.io/consent-sdk-react 10.0.0 and @redacto.io/consent-sdk-react-native 5.0.0. Identical in content to 2.0.0-beta.4; the full set of changes since 1.0.1 is listed under the 2.0.0-beta.* entries below. Highlights:

  • Go consent ledger support (ledgerBaseUrl) across the notice widgets and the Privacy Center — consent writes, the notice read, user-consents, receipts and revoke/regrant/renew. Omitting ledgerBaseUrl keeps every call on the legacy Python endpoints.
  • Privacy Center gains the Notification Hub, the shared-contact profile picker, a terminal session-expired state, and a refresh-token breaker that stops re-submitting a dead token.
  • DSAR request form fixes: purposes sourced from user-consents, product-anchored cases, supporting-document upload, erasure auto-revoke, and an access time-period picker.
  • Consent events (notice and Privacy Center) record the language the notice was displayed in.
  • Sandbox mode for RedactoNoticeConsent and RedactoPrivacyCenter via a pasted static token.
  • Removed the unsupported Bhojpuri (bho) locale.

2.0.0-beta.4 #

Parity fixes against consent-sdk-react for the erasure / notice flows (#584).

  • Erasure auto-revoke on fulfilment: DSAR erasure now shows the revoke-consent confirmation modal and sends revoke_consent_on_fulfilment (including false), matching React / RN. Previously only the translation strings existed; the feature was never wired.
  • Access requests expose a time-period picker (today / last 7 days / last 30 days / last 3 months) instead of hardcoding time_period: 30.
  • Notice banners consume the inline reconsent overlay from the notice read and drop the redundant check-consent round-trip that could wipe purpose selections.
  • A failed notice read shows a fetch-error view with Refresh / close instead of a blank white card that blocked dismissal under blockUI.

2.0.0-beta.3 #

The Privacy Center resolves the acting contact from the JWT's identifier claims instead of an opaque row id.

  • Revoke / regrant / renew in RedactoPrivacyCenter no longer fails against the Python backend with 403 contact_mismatch. The contact was resolved from a chain that consulted user_uuid / sub ahead of user_data, and TokenService.generate_tokens never mints a top-level contact / primary_email / email claim but always mints user_uuid — so every real token resolved to a uuid, which Python's /manage-consent then rejected when it cross-checked the body's contact against the subject it derives from user_data alone. The Go ledger sends no contact and resolves the principal from the token, which is why the same action worked there and masked the bug. Resolution is now contact → primary_email → user_data.primary_email → user_data.primary_mobile → user_data.org_user_id, porting resolveContactFromJwt from @redacto.io/consent-sdk-react; blank and whitespace-only claims are skipped rather than winning the chain. This also fixes mobile-only logins, which previously had no usable contact, and stops the uuid leaking into the account label in the nav drawer. Under a shared contact both sibling principals resolve the shared email rather than org_user_id — the server derives its subject the same way, and isolation comes from extract_org_user_id_from_jwt(), which the client never supplies.

2.0.0-beta.2 #

The notice read is fetched from the Go consent ledger, and the Privacy Center / DSAR parity gaps opened by the ledger cutover are closed.

  • The notice read is now served by the Go ledger whenever a ledgerBaseUrl is configured, in both RedactoNoticeConsent and RedactoNoticeConsentInline — mirroring @redacto.io/consent-sdk-react (CON-I1030), which had routed only its modal. Previously the read always went to baseUrl, so a deployment whose tokens are minted on the ledger (the demo backend does this whenever LEDGER_BASE_URL is set) got a 401 from the consent server, which does not accept ledger-issued JWTs — the notice modal then rendered with no content. FetchConsentContentParams and FetchInlineConsentContentParams gain an optional ledgerBaseUrl; resolution is ledgerBaseUrl ?? baseUrl ?? default with empty strings counting as unset, matching the || fallback in the JS/React/RN SDKs.
  • Routing lives in ConsentApi rather than at each call site, so every caller of the two reads gets it, and the exceptions are stated once: the magic-link flow (applicationId/specific_uuid) and sandbox sessions stay on the consent server, which the ledger read supports for neither, and the tokenless inline read stays there too because the ledger does not implement notices/get-notice/{uuid}. Guardian verification (guardian-info, guardian/initiate-verification, guardian/verify-status) has no ledger equivalent and is unchanged on the consent server. Omitting ledgerBaseUrl keeps every call on the legacy Python endpoints, as before.
  • ConsentApi.fetchConsentContent's response cache now keys on the resolved base URL, so a ledger read and a consent-server read for the same principal and notice can no longer be served from each other's entry.
  • Declining a notice does not record a consent event. The port of @redacto.io/consent-sdk-react CON-I1670 landed here ahead of the React change itself, so this SDK briefly wrote an explicit "no" while react, react-native and js did not. Reverted to a plain close so all four SDKs adopt the behaviour together when the React PR ships; the API layer's declined support is unchanged and still covered by tests.
  • New: the shared-contact profile picker, previously absent from this SDK. When a signed-in email or mobile maps to more than one data principal, RedactoPrivacyCenter now asks which profile to view instead of silently showing whichever one the server resolved. PrivacyCenterApi gains listIdentities, selectPrincipal and adoptTokens, with IdentityCandidate / SelectPrincipalResponse models; RedactoJwtPayload exposes orgUserId from the token's user_data. The gate resolves before any consent read, so nothing is ever fetched against a token not yet scoped to a principal, and it degrades to the normal view on any failure — a backend without the endpoint keeps working. Each row leads with org_user_id, the only value that distinguishes principals sharing a contact, falling back to email → mobile → uuid. A "switch profile" action appears in the navbar only when more than one profile exists. Ports SelectUserGate / SelectUser from @redacto.io/consent-sdk-react (CON-I1221 + #522); the session pin is held in widget state rather than sessionStorage, which has no Flutter equivalent, so a routine token refresh does not re-open the picker.
  • PrivacyCenterApi no longer re-submits a dead refresh token on every call. It had single-flight dedup but no memory of failure, so once a refresh token was expired or invalid, each authenticated call and each poller tick re-attempted it. A refresh that fails with 400/401/403/422 now trips a breaker keyed by the token value — one attempt, then no network call at all until a different token appears, so re-authentication always recovers. Transient failures (5xx/408/429, network, timeout) instead open a backoff window doubling from 30s to a 5m ceiling, leaving the token usable. isRefreshBlocked is exposed so pollers can skip doomed work; the notification bell and the case-messages poll both consult it. Ports the breaker added to @redacto.io/consent-sdk-react after the 2026-06-22 incident.
  • RedactoPrivacyCenter now has a terminal session-expired state. A refresh that fails terminally — or a missing refresh token — fires the new PrivacyCenterApi.onSessionExpired, which gates all fetching behind a dedicated "Your session has expired" screen instead of letting each widget 401 independently and render empty or stale content. Exit is a deliberate user action via the existing onBack prop; the React reference dropped its automatic redirect for the same reason. sessionExpiredTitle / sessionExpiredDescription were sourced from the React SDK's own locales, which carry all 23 languages.
  • New: the Notification Hub, previously absent from this SDK. PrivacyCenterApi gains getNotifications, getNotificationSummary, markNotificationRead, markAllNotificationsRead and acknowledgeNotification, with PrivacyNotification, NotificationCta, NotificationSummary and NotificationListResponse models. RedactoPrivacyCenter shows a bell with an unread badge in the navbar (polling every 30s, matching the React POLL_INTERVAL) and a new PrivacyCenterPage.notifications listing summary counts, category filter tabs (all / consent / requests / system), paginated rows and mark-all-read. Notification CTAs are honoured: an acknowledge CTA records the acknowledgement server-side, and a link CTA marks the notification read and opens a case-details URL in place. Ports NotificationHub from @redacto.io/consent-sdk-react; the bell opens the list page directly rather than a hover dropdown, which has no mobile equivalent.
  • Regenerated pc_translations.dart from the React Native locale sources, which the checked-in file had drifted from — every locale gains 84 keys (310 → 415 for English). English was missing the entire Notification Hub string set (notificationHub, unread, actionNeeded, markAllAsRead, justNow, minutesAgo, … 23 keys) that all 22 other locales already had, so the hub would have rendered untranslated for English users. Five keys the previous file carried but the RN source does not (paginationRange, noNotificationsYet, viewAllNotifications, loadingNotifications, refreshNotifications) moved into tool/pc_locale_supplement.json, with English values added, so regeneration no longer drops them. No existing translation changed.
  • Consent events now record the language the notice was displayed in. submit-consent never carried a language, so a consent given in Dogri or Bodo was stored against the notice's default and surfaced as English in Consent Records. SubmitConsentEventParams takes an optional language (omitted from the payload when null, so the backend keeps its default), the notice widget passes toBcp47Code(selectedLanguage) on both accept and decline, and a new toBcp47Code maps the display names the notice serves — English plus the 22 languages in the 8th Schedule — to BCP-47, porting language-codes.ts from @redacto.io/consent-sdk-react.
  • Withdraw / regrant / renew in RedactoPrivacyCenter records the selected language too. PrivacyCenterApi.manageConsent takes an optional language and includes it in both the ledger partial submit-consent body and the legacy manage-consent body; the consent manager passes langParam, which is null for the default language so the field is omitted. Mirrors the same fix in @redacto.io/consent-sdk-react (#528).
  • A DECLINED purpose is re-grantable in the Privacy Center consent manager. Its Modify button was hard-disabled and the modify modal offered no action for that status, which left a declined record permanently stuck — untenable now that declines are actually written. It re-grants exactly like a withdrawal (a partial submit-consent re-selecting the purpose), so no backend change is involved.
  • Cases raised from the DSAR request form now carry a product anchor, so the case queue shows the product name instead of leaving it blank. The queue derives product_name entirely from the case's product_uuid (hydrate_product_names_on_cases: "cases without product_uuid get product_name=None"), and the form never sent one. FormPurpose now carries productUuid / productName / nominatorUuid through from user-consents, and UserDataRequest gained optional product_uuid and data_principal_uuid, both omitted from the payload rather than sent null so the backend still reads an unanchored case as org-level. Anchoring applies only to the product-scoped request types (access / erasure / correction), matching PRODUCT_SCOPED_REQUEST_TYPES in @redacto.io/consent-sdk-react; nomination and grievance stay org-level. Where React anchors to the group picked in its product-selection step, this form has none, so the anchor is derived from the selected purposes: purposes spanning two products, and purposes from Python's flat form/data (which carries no product), submit org-level rather than attributing the case to an arbitrary product.
  • The DSAR request form no longer throws ListTile background color or ink splashes may be invisible in debug builds. The request-details sections are built from CheckboxListTiles, which paint their ink splashes on the nearest Material ancestor; the opaque accordion and form-card Containers sat between the two, so the splashes rendered behind them. The section content is now wrapped in a MaterialType.transparency Material, which restores the splashes without altering the accordion's background.
  • The DSAR request form's request-details picker is now sourced from user-consents instead of Python's form/data, which stopped emitting purposes after the consent cutover — leaving the access/erasure/correction sections permanently empty ("no purposes available") once a ledger was configured. getUserConsents serves the same grouped payload from either backend, so the overlay works with or without a ledger. The form is left untouched when the read fails or yields nothing usable, so an empty result never overwrites purposes form/data did supply, and grievance/nomination (which do not depend on purposes) are unaffected. Mirrors withUserConsentPickerGroups in @redacto.io/consent-sdk-react, flattened because this form has no product-selection step. New formPurposesFromConsentGroups helper, and formPickerGroupLimit (100, matching the React constant).
  • Supporting-document upload on the DSAR form no longer fails with a 422 (organization_uuid, uuid, is_public, allow_ai_processingField required). The shared multipart helper sent {"metadata": null} for both upload endpoints, which is what the case-document endpoint accepts, but the privacy-center form endpoint validates a full payload. uploadFormDocument now sends organization_uuid, space, a generated uuid, is_public, allow_ai_processing and the privacy metadata block, matching the React reference; uploadCaseDocument is unchanged. uploadFormDocument takes a new required formUuid (the uuid from getFormData) which scopes the stored document.
  • Revoke/regrant/renew in RedactoPrivacyCenter no longer fails with notice_uuid is required to manage consent via the ledger. The ledger's user-consents response groups rows by product and carries notice_uuid on each nested purpose; UserConsent and PurposeItem both parsed it, but the two consent-manager group mappings in consent_manager_utils.dart rebuilt each row field-by-field and omitted it, so every ledger-served row reached the UI with noticeUuid: null and ledger-mode manage-consent rejected the request. Both mappings now thread it through, as the post-action optimistic row rebuild already did. @redacto.io/consent-sdk-react throws the same error from the same guard but never trips it, because it carries the raw row object rather than reconstructing it.

2.0.0-beta.1 #

  • Declining a notice does not record a consent event. The port of @redacto.io/consent-sdk-react CON-I1670 landed here ahead of the React change itself, so this SDK briefly wrote an explicit "no" while react, react-native and js did not. Reverted to a plain close so all four SDKs adopt the behaviour together when the React PR ships; the API layer's declined support is unchanged and still covered by tests.
  • New: the shared-contact profile picker, previously absent from this SDK. When a signed-in email or mobile maps to more than one data principal, RedactoPrivacyCenter now asks which profile to view instead of silently showing whichever one the server resolved. PrivacyCenterApi gains listIdentities, selectPrincipal and adoptTokens, with IdentityCandidate / SelectPrincipalResponse models; RedactoJwtPayload exposes orgUserId from the token's user_data. The gate resolves before any consent read, so nothing is ever fetched against a token not yet scoped to a principal, and it degrades to the normal view on any failure — a backend without the endpoint keeps working. Each row leads with org_user_id, the only value that distinguishes principals sharing a contact, falling back to email → mobile → uuid. A "switch profile" action appears in the navbar only when more than one profile exists. Ports SelectUserGate / SelectUser from @redacto.io/consent-sdk-react (CON-I1221 + #522); the session pin is held in widget state rather than sessionStorage, which has no Flutter equivalent, so a routine token refresh does not re-open the picker.
  • PrivacyCenterApi no longer re-submits a dead refresh token on every call. It had single-flight dedup but no memory of failure, so once a refresh token was expired or invalid, each authenticated call and each poller tick re-attempted it. A refresh that fails with 400/401/403/422 now trips a breaker keyed by the token value — one attempt, then no network call at all until a different token appears, so re-authentication always recovers. Transient failures (5xx/408/429, network, timeout) instead open a backoff window doubling from 30s to a 5m ceiling, leaving the token usable. isRefreshBlocked is exposed so pollers can skip doomed work; the notification bell and the case-messages poll both consult it. Ports the breaker added to @redacto.io/consent-sdk-react after the 2026-06-22 incident.
  • RedactoPrivacyCenter now has a terminal session-expired state. A refresh that fails terminally — or a missing refresh token — fires the new PrivacyCenterApi.onSessionExpired, which gates all fetching behind a dedicated "Your session has expired" screen instead of letting each widget 401 independently and render empty or stale content. Exit is a deliberate user action via the existing onBack prop; the React reference dropped its automatic redirect for the same reason. sessionExpiredTitle / sessionExpiredDescription were sourced from the React SDK's own locales, which carry all 23 languages.
  • New: the Notification Hub, previously absent from this SDK. PrivacyCenterApi gains getNotifications, getNotificationSummary, markNotificationRead, markAllNotificationsRead and acknowledgeNotification, with PrivacyNotification, NotificationCta, NotificationSummary and NotificationListResponse models. RedactoPrivacyCenter shows a bell with an unread badge in the navbar (polling every 30s, matching the React POLL_INTERVAL) and a new PrivacyCenterPage.notifications listing summary counts, category filter tabs (all / consent / requests / system), paginated rows and mark-all-read. Notification CTAs are honoured: an acknowledge CTA records the acknowledgement server-side, and a link CTA marks the notification read and opens a case-details URL in place. Ports NotificationHub from @redacto.io/consent-sdk-react; the bell opens the list page directly rather than a hover dropdown, which has no mobile equivalent.
  • Regenerated pc_translations.dart from the React Native locale sources, which the checked-in file had drifted from — every locale gains 84 keys (310 → 415 for English). English was missing the entire Notification Hub string set (notificationHub, unread, actionNeeded, markAllAsRead, justNow, minutesAgo, … 23 keys) that all 22 other locales already had, so the hub would have rendered untranslated for English users. Five keys the previous file carried but the RN source does not (paginationRange, noNotificationsYet, viewAllNotifications, loadingNotifications, refreshNotifications) moved into tool/pc_locale_supplement.json, with English values added, so regeneration no longer drops them. No existing translation changed.
  • Consent events now record the language the notice was displayed in. submit-consent never carried a language, so a consent given in Dogri or Bodo was stored against the notice's default and surfaced as English in Consent Records. SubmitConsentEventParams takes an optional language (omitted from the payload when null, so the backend keeps its default), the notice widget passes toBcp47Code(selectedLanguage) on both accept and decline, and a new toBcp47Code maps the display names the notice serves — English plus the 22 languages in the 8th Schedule — to BCP-47, porting language-codes.ts from @redacto.io/consent-sdk-react.
  • Withdraw / regrant / renew in RedactoPrivacyCenter records the selected language too. PrivacyCenterApi.manageConsent takes an optional language and includes it in both the ledger partial submit-consent body and the legacy manage-consent body; the consent manager passes langParam, which is null for the default language so the field is omitted. Mirrors the same fix in @redacto.io/consent-sdk-react (#528).
  • A DECLINED purpose is re-grantable in the Privacy Center consent manager. Its Modify button was hard-disabled and the modify modal offered no action for that status, which left a declined record permanently stuck — untenable now that declines are actually written. It re-grants exactly like a withdrawal (a partial submit-consent re-selecting the purpose), so no backend change is involved.
  • Cases raised from the DSAR request form now carry a product anchor, so the case queue shows the product name instead of leaving it blank. The queue derives product_name entirely from the case's product_uuid (hydrate_product_names_on_cases: "cases without product_uuid get product_name=None"), and the form never sent one. FormPurpose now carries productUuid / productName / nominatorUuid through from user-consents, and UserDataRequest gained optional product_uuid and data_principal_uuid, both omitted from the payload rather than sent null so the backend still reads an unanchored case as org-level. Anchoring applies only to the product-scoped request types (access / erasure / correction), matching PRODUCT_SCOPED_REQUEST_TYPES in @redacto.io/consent-sdk-react; nomination and grievance stay org-level. Where React anchors to the group picked in its product-selection step, this form has none, so the anchor is derived from the selected purposes: purposes spanning two products, and purposes from Python's flat form/data (which carries no product), submit org-level rather than attributing the case to an arbitrary product.
  • The DSAR request form no longer throws ListTile background color or ink splashes may be invisible in debug builds. The request-details sections are built from CheckboxListTiles, which paint their ink splashes on the nearest Material ancestor; the opaque accordion and form-card Containers sat between the two, so the splashes rendered behind them. The section content is now wrapped in a MaterialType.transparency Material, which restores the splashes without altering the accordion's background.
  • The DSAR request form's request-details picker is now sourced from user-consents instead of Python's form/data, which stopped emitting purposes after the consent cutover — leaving the access/erasure/correction sections permanently empty ("no purposes available") once a ledger was configured. getUserConsents serves the same grouped payload from either backend, so the overlay works with or without a ledger. The form is left untouched when the read fails or yields nothing usable, so an empty result never overwrites purposes form/data did supply, and grievance/nomination (which do not depend on purposes) are unaffected. Mirrors withUserConsentPickerGroups in @redacto.io/consent-sdk-react, flattened because this form has no product-selection step. New formPurposesFromConsentGroups helper, and formPickerGroupLimit (100, matching the React constant).
  • Supporting-document upload on the DSAR form no longer fails with a 422 (organization_uuid, uuid, is_public, allow_ai_processingField required). The shared multipart helper sent {"metadata": null} for both upload endpoints, which is what the case-document endpoint accepts, but the privacy-center form endpoint validates a full payload. uploadFormDocument now sends organization_uuid, space, a generated uuid, is_public, allow_ai_processing and the privacy metadata block, matching the React reference; uploadCaseDocument is unchanged. uploadFormDocument takes a new required formUuid (the uuid from getFormData) which scopes the stored document.
  • Revoke/regrant/renew in RedactoPrivacyCenter no longer fails with notice_uuid is required to manage consent via the ledger. The ledger's user-consents response groups rows by product and carries notice_uuid on each nested purpose; UserConsent and PurposeItem both parsed it, but the two consent-manager group mappings in consent_manager_utils.dart rebuilt each row field-by-field and omitted it, so every ledger-served row reached the UI with noticeUuid: null and ledger-mode manage-consent rejected the request. Both mappings now thread it through, as the post-action optimistic row rebuild already did. @redacto.io/consent-sdk-react throws the same error from the same guard but never trips it, because it carries the raw row object rather than reconstructing it.
  • The notice read is now served by the Go ledger whenever a ledgerBaseUrl is configured, in both RedactoNoticeConsent and RedactoNoticeConsentInline — mirroring @redacto.io/consent-sdk-react (CON-I1030), which had routed only its modal. Previously the read always went to baseUrl, so a deployment whose tokens are minted on the ledger (the demo backend does this whenever LEDGER_BASE_URL is set) got a 401 from the consent server, which does not accept ledger-issued JWTs — the notice modal then rendered with no content. FetchConsentContentParams and FetchInlineConsentContentParams gain an optional ledgerBaseUrl; resolution is ledgerBaseUrl ?? baseUrl ?? default with empty strings counting as unset, matching the || fallback in the JS/React/RN SDKs.
  • Routing lives in ConsentApi rather than at each call site, so every caller of the two reads gets it, and the exceptions are stated once: the magic-link flow (applicationId/specific_uuid) and sandbox sessions stay on the consent server, which the ledger read supports for neither, and the tokenless inline read stays there too because the ledger does not implement notices/get-notice/{uuid}. Guardian verification (guardian-info, guardian/initiate-verification, guardian/verify-status) has no ledger equivalent and is unchanged on the consent server. Omitting ledgerBaseUrl keeps every call on the legacy Python endpoints, as before.
  • ConsentApi.fetchConsentContent's response cache now keys on the resolved base URL, so a ledger read and a consent-server read for the same principal and notice can no longer be served from each other's entry.
  • Added sandbox mode to RedactoNoticeConsent and RedactoPrivacyCenter, so a full consent PoC — notice → Privacy Center → DSAR — runs with a pasted static token and no backend token minting. Sandbox is activated by the new token parameter and takes organisationUuid / workspaceUuid from parameters instead of decoding a JWT; the acting test identity is ucic > email > mobile. The token is sent as the single X-Consent-Token header (no Authorization: Bearer, no refresh, so a 401 fails fast), and the identity rides each request's own payload — query params (org_user_id / primary_email / primary_mobile) on reads, the JSON body on writes. The server records everything under environment=test, isolated from live records. Sandbox always talks to the consent server, so ledgerBaseUrl has no effect there. New public API: SandboxAuthParams, SandboxAuth, ResolvedRequestAuth. Additive — the JWT path is unchanged, and RedactoNoticeConsentInline has no sandbox mode (matching @redacto.io/consent-sdk-react).
  • The revoke confirmation dialog in RedactoPrivacyCenter now shows the admin-authored, per-purpose revoke_warning_message served on each user-consents row, falling back to the localized revokeConsentWarning copy when it is null, empty, or absent (older backends). UserConsent and PurposeItem gain a nullable revokeWarningMessage field, threaded through the consent-manager group mappings so it reaches the modal. Mirrors @redacto.io/consent-sdk-react; only the active/revoke branch is affected — regrant and renew warnings are unchanged.
  • RedactoNoticeConsentInline reads the notice from the authenticated notices/{notice_uuid} endpoint whenever an access token is available, instead of the tokenless notices/get-notice/{notice_uuid}. Only the consent server serves the tokenless path, so pointing baseUrl at the Go consent ledger failed with 404 Resource not found even though the notice existed there — and the path is compiled into the SDK, so no baseUrl change could fix it. notices/{notice_uuid} is the endpoint RedactoNoticeConsent has always used: both backends serve it, and it returns the caller's purpose_selections / reconsent_required overlay plus 409 CONSENT_ALREADY_PROVIDED. FetchInlineConsentContentParams takes a new optional accessToken (empty counts as unset); without one the tokenless path is unchanged.
  • RedactoNoticeConsentInline re-reads the notice when the host rebuilds it with an accessToken and the first read was tokenless, so a token that arrives after mount switches to the authenticated endpoint. Previously the widget only ever loaded in initState, leaving the unauthenticated content on screen. A later token change does not refetch, so in-progress selections are kept. The load is generation-guarded, so the superseded tokenless read cannot resolve last and overwrite the authenticated content or reset the selections; _hasAlreadyConsented is cleared at the start of each load.

2.0.0-beta.0 #

M3 beta, versioned alongside @redacto.io/consent-sdk-js 1.0.0-beta.0, @redacto.io/consent-sdk-react 10.0.0-beta.5 and @redacto.io/consent-sdk-react-native 5.0.0-beta.0. This release supersedes 1.1.0, which was prepared but never published to pub.dev; its notes are folded in below.

  • Removed the unsupported Bhojpuri (bho) locale.
  • Added ledgerBaseUrl support (Go consent ledger) across the SDK, mirroring consent-sdk-react:
    • RedactoNoticeConsent routes its consent write through the first non-empty of ledgerBaseUrl, baseUrl, default — empty strings count as unset, matching the || fallback in the JS/React/RN SDKs — and overlays prior-consent/reconsent state from the ledger's check-consent (Python's notice-validation overlay is empty after the consent cutover).
    • RedactoNoticeConsentInline proactively short-circuits already-consented principals via the ledger check and gates auto-submit until it settles — the ledger equivalent of the legacy Python 409 CONSENT_ALREADY_PROVIDED.
    • RedactoPrivacyCenter (and PrivacyCenterApi.configure) accept ledgerBaseUrl and route user-consents, receipts list and receipt PDF (/receipts/{uuid}/download) to the ledger; revoke/regrant/renew is expressed as a partial: true submit-consent on the ledger.
    • New public API: ConsentApi.checkNoticeConsentStatus, NoticeConsentStatusResponse, buildLedgerConsentOverlay.
  • Fully backward compatible: when ledgerBaseUrl is omitted, every call stays on the legacy Python endpoints and the reactive 409 path governs (pre-ledger behavior).

1.0.1 #

  • Docs: expand the package README to document the full feature set shipped in 1.0.0 — Privacy Center (widget, parameters, headless API), notice parameter tables, styling, localization, and troubleshooting. No functional or API changes.

1.0.0 #

First stable release.

Added #

  • Privacy Center: multi-page certified UI with a headless core (#258, #411).
  • "My Receipt" consent receipts support (#390).
  • Privacy Center "no data" empty state (#408).

Changed #

  • Aligned the Flutter SDK feature set and UI/UX with the iOS SDK (#251).
  • Aligned Consent Manager to the GET user-consents contract (#387).

Fixed #

  • Keep revoked-consent purposes raisable in Privacy Center DSAR forms (#381).

0.1.0 #

  • Initial Flutter SDK scaffold with modal and inline consent widgets.
0
likes
110
points
98
downloads

Documentation

API reference

Publisher

verified publisherredacto.ai

Weekly Downloads

Flutter SDK for integrating Redacto consent notices.

Repository (GitHub)

License

Apache-2.0 (license)

Dependencies

file_picker, flutter, flutter_svg, http, intl, just_audio, open_filex, path_provider, share_plus, url_launcher

More

Packages that depend on redacto_consent_sdk