72 min readAug 11, 2026by jakub

Changelog

Current version: 1.1.0

One section per suite version, newest first. Each module that shipped changes in a version has its own subsection, carried from that module's own changelog; modules without changes in a version are simply absent.

1.1.0 — 2026-07-26

GdprCore

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprAdmin

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprConsent

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprConsentHyva

Changed

  • Restructured the Tailwind sources: extracted tailwind-source.css into module.css + component partials and refreshed the tailwind.config.js safelist so the module's classes survive purge. Frontend Tailwind build only — no PHP or behavioural changes.
  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release (adds EU Right of Withdrawal, Directive (EU) 2023/2673).

GdprCookie

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprCookieHyva

Changed

  • Restructured the Tailwind sources: extracted tailwind-source.css into module.css + component partials and refreshed the tailwind.config.js safelist so the module's classes survive purge. Frontend Tailwind build only — no PHP or behavioural changes.
  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release (adds EU Right of Withdrawal, Directive (EU) 2023/2673).

GdprCookieTemplates

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprDataSubject

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprDataSubjectHyva

Changed

  • Updated the tailwind.config.js safelist for the GDPR Suite 1.1.0 build. Frontend Tailwind build only — no PHP or behavioural changes.
  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release (adds EU Right of Withdrawal, Directive (EU) 2023/2673).

GdprDemo

Changed

  • Updated the tailwind.config.js safelist for the GDPR Suite 1.1.0 build. Frontend Tailwind build only — no PHP or behavioural changes.
  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release (adds EU Right of Withdrawal, Directive (EU) 2023/2673).

GdprFrontend

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprFrontendHyva

Changed

  • Updated the tailwind.config.js safelist for the GDPR Suite 1.1.0 build. Frontend Tailwind build only — no PHP or behavioural changes.
  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release (adds EU Right of Withdrawal, Directive (EU) 2023/2673).

GdprGtm

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprPolicy

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprPolicyHyva

Changed

  • Updated the tailwind.config.js safelist for the GDPR Suite 1.1.0 build. Frontend Tailwind build only — no PHP or behavioural changes.
  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release (adds EU Right of Withdrawal, Directive (EU) 2023/2673).

GdprPrivacyCenter

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

GdprPrivacyCenterHyva

Changed

  • Restructured the Tailwind sources: extracted tailwind-source.css into module.css + component partials and refreshed the tailwind.config.js safelist so the module's classes survive purge. Frontend Tailwind build only — no PHP or behavioural changes.
  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release (adds EU Right of Withdrawal, Directive (EU) 2023/2673).

GdprWithdrawal

Initial release. Introduces the EU Right of Withdrawal for online sales contracts (Directive (EU) 2023/2673, amending Directive 2011/83/EU), which mandates a clearly visible online withdrawal function from 19 June 2026.

Added

  • Withdrawal lifecycle — customer & guest storefront withdrawal forms, an admin grid + detail view, and an observer-driven state machine (new → submitted → confirmed → processing → processed / rejected / expired) with illegal-transition guards.
  • Tamper-evident audit trail — every status transition is recorded with a hash-chained history for durable, verifiable proof.
  • Eligibility engine — configurable 14-day window with start_basis (delivery / last shipment / order date), delivery-date resolution, and statutory exclusions (Directive 2011/83/EU Art. 16).
  • Guarded order actions — cancel / credit-memo via OrderActionService, gated on a goods-returned check. The standard outbound-shipping refund (Art. 13) is applied on a full withdrawal and zeroed on a genuine partial, keyed on an is_full_request flag; refund via the same payment means.
  • Durable-medium acknowledgement — a confirmation email queued on every confirmation, plus request-received and admin-notification templates.
  • Art. 11a confirmation block — consumer name, order reference and confirmation email shown before the Confirm button; the authenticated path uses the account email, not the order snapshot.
  • Email queue admin surface (grid + status source) and a cron that auto-processes confirmed requests.
  • Multi-store aware configuration throughout — all scope reads are keyed to the order's store.
  • Quantity-aware over-withdrawal guard and reference generation hardened against concurrent inserts.
  • Setup\Patch\Data\BackfillIsFullRequest — backfills the is_full_request flag on pre-existing full rows.
  • Comprehensive unit + integration test coverage; merchant documentation under docs/withdrawal/.

Dependencies

  • qoliber/gdpr-core (^1.0), magento/module-customer, magento/module-sales
  • PHP 8.1 – 8.5

GdprWithdrawalGraphQl

Initial release. GraphQL API for Qoliber_GdprWithdrawal, shipped as part of the GDPR Suite 1.1.0 release that introduces the EU Right of Withdrawal (Directive (EU) 2023/2673).

Added

  • Queries/mutations to create a withdrawal, list a customer's withdrawable orders, and read withdrawal status — with authenticated-customer and guest (verify + rate-limited, generic-error) parity to the storefront.
  • Store-scoped eligibility resolved from the order's store; the authenticated create path persists and sends the durable acknowledgement to the account email.

Dependencies

  • qoliber/gdpr-withdrawal (^1.0), magento/module-graph-ql, magento/module-sales
  • PHP 8.1 – 8.5

GdprWithdrawalHyva

Initial release. Hyvä (strict-CSP) storefront companion for Qoliber_GdprWithdrawal, shipped as part of the GDPR Suite 1.1.0 release that introduces the EU Right of Withdrawal (Directive (EU) 2023/2673).

Added

  • Hyvä Tailwind/Alpine templates for the customer & guest withdrawal forms, guest lookup, and the order-view withdrawal button — including the Art. 11a confirmation block.
  • Strict-CSP-safe Alpine registration via an external withdrawal-form.js (no inline handlers), guarded against the Alpine init-timing race.
  • Store-scoped order-view button label/visibility (resolved from the order's store).
  • Tailwind config and i18n (en / de / pl).

Dependencies

  • qoliber/gdpr-withdrawal (^1.0), qoliber/hyva-module-registration
  • PHP 8.1 – 8.5

GdprYireoGtm

Changed

  • Version aligned to 1.1.0 for the GDPR Suite 1.1.0 release, which introduces the EU Right of Withdrawal (Directive (EU) 2023/2673 — mandatory online withdrawal function from 19 June 2026). No functional changes to this module.

1.0.5 — 2026-06-11

GdprConsent

Added

  • Configurable "Link Text" on consent definitions (REAC-7). New nullable link_text column + admin form field: the {link} placeholder in the checkbox label now renders the merchant's text instead of the hardcoded "Privacy Policy" (which remains the fallback when empty). Honoured by the text and CMS-page renderers and the checkout consent config.

GdprCookie

Fixed

  • Hyvä cookie banner showed categories with no cookies (REAC-10). ViewModel\CookieConsent::getCategoriesWithCookies() now drops categories that have no cookie details — there is nothing for the visitor to allow or deny. Luma's Knockout banner already filtered these client-side; the shared server-side filter makes both themes consistent.

GdprPolicy

Changed

  • The privacy-policy consent renderers (Luma + Hyvä) honour the consent definition's new "Link Text" (link_text, see Qoliber_GdprConsent 1.0.5) for the {link} placeholder, falling back to the policy title / "Privacy Policy".

1.0.4 — 2026-06-11

GdprConsentHyva

Fixed

  • Strict-CSP Hyvä Checkout froze on "Proceed to payment" (critical; missed in the 1.0.3 release sync). The checkout consent template appended an inline <script> after the Magewire component's root element; on every Magewire morphdom re-render the script is re-executed via eval(), which a strict checkout CSP (no unsafe-eval) blocks — the step transition rejected and checkout never advanced (plus a "Multiple root elements" Livewire warning). The gdprCheckoutConsents Alpine component is now registered in the static, CSP-hashed before.body.end block and the inline script is gone; the Magewire template ends at its single root element.

GdprDataSubject

Fixed

  • Luma delete-account confirmation was still case-sensitive. The 1.0.3 case-insensitive "type DELETE" fix shipped for Hyvä but this module's Luma template was missed in the release sync — lowercase delete still flagged the field red and failed valid() (re-triggering the all-fields-red wash). The Luma validator, submit guard and live-feedback handler now compare case-insensitively, matching Hyvä.

1.0.3 — 2026-06-11

GdprCore

Added

  • Api\TagTypeInterface and Model\TagType\TagTypePool (moved here from GdprFrontend, which keeps deprecated BC shims). Hosting the tag-type contract in the shared core module breaks the GdprCookie ⇄ GdprFrontend package dependency cycle; GdprFrontend/GdprGtm/GdprYireoGtm now wire their tag types into the GdprCore pool.

GdprAdmin — 2026-06-09

Fixed (marketplace-hardening review, 2026-06-10)

  • Packaging: composer now declares the module's real dependencies (gdpr-consent, gdpr-cookie, gdpr-data-subject, gdpr-policy) and the module sequence includes GdprCookie/GdprPolicy — the dashboards, readiness auditor and audit export query those modules' tables/classes, so a partial install produced fatal admin pages.

Fixed

  • "Data Subject Requests" overview grid actions 404'd. The GDPR Dashboard "View all requests" grid exposed Process/Reject/Delete mass actions, a "Create New Request" button and inline edit — none of which have controllers in this module (it has only Requests/Index), so every one 404'd. Removed them; the grid is now a read-only overview. Manage requests via GDPR → GDPR Requests.

GdprConsent

Fixed

  • Admin hardening: consent Delete/Save and all mass actions (Delete/Enable/Disable) are now HttpPost-only; Edit/Index/New declare HttpGet. The grid's row Delete action POSTs with a form key, and the edit form's Delete button was replaced with a DeleteButton block that POSTs via deleteConfirm(..., {"data": {}}) (the previous plain XML button emitted a GET, which the POST-only controller would reject).
  • Packaging: composer now declares the module's real dependencies (module-checkout, module-contact, module-newsletter, module-quote, module-store — plugin/extension-attribute targets that previously broke setup:di:compile on partial installs); removed the no-op Magento_Cookie sequence entry.

GdprConsentHyva — 2026-06-10

Fixed

  • setup:di:compile failed on Hyvä-theme-without-Hyvä-Checkout installs. The checkout consent Magewire component extends Magewire/Hyvä-Checkout classes that composer never required. Declared hyva-themes/magento2-hyva-checkout as a dependency; splitting the component into a dedicated GdprConsentHyvaCheckout module is scheduled for 1.1 (ROADMAP F18.3).
  • CSP cleanup: removed leftover hyva-csp-helper generator comments (no functional change).

GdprCookie — 2026-06-09

Fixed (review round 2, 2026-06-11)

  • Cookie-detail edit form's Delete button now POSTs with a form key (deleteConfirm(..., {"data": {}})) — the Delete controller is HttpPost-only since the previous round. DetectedCookie\MassDelete is now HttpPost-only too.
  • Package cycle with GdprFrontend broken: ViewModel\CookieConsent now consumes the TagType pool from GdprCore (see GdprCore 1.0.3); the qoliber/gdpr-frontend composer requirement is gone.

Fixed (marketplace-hardening review, 2026-06-10)

  • Admin hardening: cookie-category delete now requires POST (was GET), cookie-detail delete/save/edit/new/index and category save now declare granular ADMIN_RESOURCE ACL (previously any admin role could execute them; cookie-detail delete carried a dead isAllowed() override the framework never calls). Grid Delete actions now POST with a form key.
  • Packaging: declared the real qoliber/gdpr-frontend composer dependency (ViewModel\CookieConsent imports its TagType pool); a standalone install no longer breaks compilation. The proper decoupling is scheduled for 1.1 (ROADMAP F18.2).

Fixed

  • Luma cookie-consent theme/colours had no effect on the storefront. The banner's data-theme attribute was applied by a fragile one-shot JS that raced KnockoutJS rendering, so the [data-theme="…"] CSS variables/rules never matched the rendered element (Dark/Light/Custom all looked identical). The four KO banner templates (popup, bottom, sidebar-left, sidebar-right) now bind data-theme to settings.theme directly, so the theme and Custom colour palette apply reliably. (Hyvä already server-rendered data-theme and was unaffected.)

GdprCookieHyva — 2026-06-10

Fixed

  • CSP cleanup: removed leftover hyva-csp-helper generator comments from the Hyvä templates (per AGENTS.md; no functional change).

GdprCookieTemplates — 2026-06-10

Fixed

  • Admin hardening: the template-picker JSON controller now declares a granular ADMIN_RESOURCE (Qoliber_GdprAdmin::gdpr_cookies_manage); its previous isAllowed() override used a method name the framework never calls, so any admin role could query it.

GdprDataSubject — 2026-06-09

Fixed (review round 2, 2026-06-11)

  • Guest anonymization state machine was inconsistent. (a) Requesting anonymization now immediately moves the original fetch request to anonymization_requested, so the data link stops serving personal data while erasure is pending. (b) The guest view located the anonymization request by the original fetch token — which can never match the anonymize row's own token — so the pending/complete banner never rendered; it is now matched via original_request_id. (c) The terminal anonymization_completed/anonymization_failed statuses (new interface constants, also used by the cron) are accepted by the guest view/controller whitelists as status-only states, so the guest's link shows the erasure outcome instead of "invalid link" — without ever serving data again.
  • PII log hygiene (round 2): removed remaining raw subject emails from DSAR logs (anonymization request/cron, guest submit, restriction/objection crons, customer lookup) — request IDs are the correlator.

Fixed (marketplace-hardening review, 2026-06-10)

  • Guest data-ready links were dead on arrival. Cron\ProcessDataFetchRequests marked a request completed right after emailing the download link, but the download/view gates only accept notified/accessed — so every emailed link was rejected. The cron now sets notified (matching ProcessDataAccessNotifications); completion follows access/expiry.
  • Admin hardening: request Block/Unblock/Mark-Reviewed are now POST-only (grid actions and the detail-page buttons submit with a form key; previously plain GET links).
  • PII log hygiene: DSAR/export paths no longer write raw subject emails or full stack traces to application logs — request IDs or truncated email hashes are used as correlators, exceptions log class @ file:line.

Fixed

  • Admin request "Process" / "Delete" actions 404'd. The request grid's row actions (perform/resend/export/archive) and mass "Delete", and the detail page's "Process/Approve" buttons, all pointed at controllers that never existed (gdpr/request/{perform,resend,export,archive,massDelete}). Removed them. Request fulfilment is performed automatically by the per-type cron once a request is pending — honouring the right to erasure/access without undue delay — so admin approval is not a gate; the admin's controls are View, Notes, Block/Unblock (legal hold) and Review.
  • A denied request left the customer account locked out permanently. The account is locked when a deletion/anonymization request is submitted, but nothing released the lock on denial. Added Service\CustomerLookupService::unlockCustomerAccount() and call it from DenyDelete / DenyAnonymize, so a denied request re-enables the customer's login.

GdprDataSubjectHyva — 2026-06-09

Fixed (review round 2, 2026-06-11)

  • Guest invalid-link branch rendered malformed Alpine markup — it opened <div x-data="gdprGuestViewData"> (a component only registered in the data branch) and returned without closing the wrapper. The error box is now static, complete markup. The anonymization branches also key on the new terminal statuses, with a status belt that never renders data while erasure is pending/failed.

Fixed (marketplace-hardening review, 2026-06-10)

  • CSP cleanup: removed leftover hyva-csp-helper generator comments from the Hyvä templates (per AGENTS.md; no functional change).

Fixed

  • Delete-account form was confusing and could not be submitted with valid data. The "type DELETE" confirmation is now case-insensitive (lowercase delete is accepted; the uppercased display no longer mismatches a case-sensitive check), live validation uses @input instead of @change, and the acknowledgement checkbox now reads .checked instead of the string "on". A fully and validly filled form now enables the submit button instead of staying disabled/red.

GdprFrontend — 2026-06-10

Changed (review round 2, 2026-06-11)

  • Api\TagTypeInterface and Model\TagType\TagTypePool moved to GdprCore (deprecated BC shims remain); di.xml tag-type wiring now targets the GdprCore pool. This breaks the GdprCookie ⇄ GdprFrontend package cycle: the dependency is now one-way (GdprFrontend → GdprCookie).
  • Removed the unused Qoliber_GdprConsent/Qoliber_GdprDataSubject soft sequence entries (no code, layout or config references); sequence now declares the real dependencies (GdprCookie, Magento_GoogleGtag).

Fixed

  • Packaging: declared the module's real composer dependencies — qoliber/gdpr-cookie (the storefront ViewModel\CookieConsent, instantiated on every page, extends GdprCookie's view model: a standalone install fataled the whole storefront) and magento/module-google-gtag (di.xml plugs Magento\GoogleGtag\Block\Ga). The structural decoupling is scheduled for 1.1 (ROADMAP F18.2).

GdprGtm

Changed

  • Tag type now implements the GdprCore TagTypeInterface and registers in the GdprCore TagTypePool (moved from GdprFrontend).
  • Packaging: declared the real qoliber/gdpr-cookie dependency (the frontend layout instantiates its CookieConsent view model); removed the no-op Magento_GoogleGtag sequence entry (no code, layout or block interaction).

GdprPolicy — 2026-06-09

Fixed (marketplace-hardening review, 2026-06-10)

  • REST policy-consent endpoints could never authorize. etc/webapi.xml referenced the ACL resource policy_consent_view, but acl.xml defines policy_consents_view — every token was rejected. Fixed the reference.
  • Undeclared hard dependency on Qoliber_GdprCookie. Data patches inject GdprCookie repositories and di.xml plugs its CookieConsent view model, so a partial install fataled setup:upgrade/di:compile. Declared the dependency (composer + module sequence) and pointed both cookie-seeding patches' getDependencies() at InstallDefaultCookies so patch ordering can no longer silently skip seeding.

Fixed

  • "Privacy Policy" consent link 404'd (e.g. on the registration form). Block\Consent\Renderer\PrivacyPolicy::getPolicyUrl() fell back to a gdpr/policy/view route that does not exist. Repointed it to the real gdpr/policy/render endpoint so the consent link / policy modal never resolves to a 404.

GdprPolicyHyva — 2026-06-10

Fixed

  • CSP cleanup (per AGENTS.md): the privacy-policy modal now binds x-data directly to the canonical QoliberGdprPrivacyPolicy component; removed the redundant generated gdprPrivacyPolicy alias wrapper script and leftover hyva-csp-helper generator comments.

GdprYireoGtm

Changed

  • Tag type now implements the GdprCore TagTypeInterface and registers in the GdprCore TagTypePool (moved from GdprFrontend).

1.0.2 — 2026-06-07

GdprAdmin

Fixed

  • "Data Subject Requests" details page led to a 404. The requests grid action column (Ui\Component\Listing\Column\RequestActions) built the View link as qoliber_gdpr/request/view, but Qoliber_GdprAdmin has no such controller — the data-subject request detail view is owned by Qoliber_GdprDataSubject on the gdpr admin route. Reachable from the GDPR Dashboard's "View All Requests" button, clicking a row's View therefore hit a non-existent route and 404'd. Repointed the link to the real controller gdpr/request/view (same id parameter). Covered by a unit test.

GdprConsent — 2026-06-06

Fixed

  • Guest checkout failed with a TypeError (critical). PaymentInformationManagementPlugin was bound to both the logged-in Magento\Checkout\Model\PaymentInformationManagement and the guest Magento\Checkout\Model\GuestPaymentInformationManagement, but the guest interface inserts $email as the second argument — so on every guest order the $email string was passed into the PaymentInterface $paymentMethod parameter and threw a TypeError, blocking the order. Additionally saveConsentData(int $cartId, …) type-hinted the cart id as int, which a masked-string guest cart id also broke. Split the logic into a dedicated Plugin\Checkout\Model\GuestPaymentInformationManagementPlugin with the correct guest signature, kept PaymentInformationManagementPlugin for the logged-in flow, moved the shared consent extraction into Service\Checkout\PaymentConsentSaver, and dropped the unused/incorrectly-typed $cartId. Covered by unit tests.
  • Privacy-policy consent link stale on installs upgraded from 1.0.0-RC. In 1.0.0 the privacy_policy consent's routing changed (display_type cms_page_linkprivacy_policy_link, link_url /privacy-policy-cookie-restriction-modegdpr/policy/render), but InstallDefaultConsents is run-once and insert-only, so RC-upgraded stores kept the stale values and the consent's policy link routed to the CMS renderer (which has no page id) and failed. Added an idempotent Setup/Patch/Data/ReconcilePrivacyPolicyConsentLink that corrects the row only when it is still at the exact RC defaults (fresh installs and merchant-customised rows are left untouched).

Removed

  • Dead, redundant quote-based checkout consent path. Observer\CheckoutSubmitAllAfter (read consent off the quote) was never registered in any events.xml, so the ShippingInformationManagementPlugin that wrote consent to the quote on every checkout shipping step fed nothing — a wasted quote save and a latent double-recording landmine (had the observer ever been registered, ConsentTracker has no per-order dedup, so every Luma order would have logged its consents twice). Consent is captured via the payment/Magewire → checkout-session path and persisted by the unified Observer\PersistCheckoutConsents (see Changed). Removed the orphaned observer, Plugin\Checkout\Model\ShippingInformationManagementPlugin and its two di bindings, and the shipping-save-processor JS mixin. The CartInterface/ShippingInformationInterface consent extension attributes are now unused and will be removed in a future minor.

Changed

  • Unified checkout consent capture across Luma and Hyvä. The two storefronts stashed checkout consent under different checkout-session keys (qoliber_gdpr_consent vs qoliber_gdpr_consents), each consumed by its own observer on overlapping events — a divergence that risked silent misses and, if ever naively aligned, double-recording (ConsentTracker has no per-order dedup). Introduced a single shared key, Model\Checkout\ConsentSession::KEY, used by both writers, and one base-module observer Observer\PersistCheckoutConsents on the universal checkout_submit_all_after event that records consent for every storefront (accepting both the serialized-string and raw-array payload shapes). Removed the Luma-only Observer\CheckoutOnepageSuccess; the redundant Qoliber_GdprConsentHyva observer is removed too (see its changelog).

GdprConsentHyva

Changed

  • Unified checkout consent capture with the Luma stack. The Hyvä consent Magewire component now stashes consent under the shared Qoliber\GdprConsent\Model\Checkout\ConsentSession::KEY instead of its own private session key, and recording is handled by the single base-module observer Qoliber\GdprConsent\Observer\PersistCheckoutConsents (on checkout_submit_all_after). Removed this module's now-redundant Observer\CheckoutSubmitAllAfterObserver and its etc/events.xml. No behavioural change for Hyvä checkout — consent is still recorded once per order; the two storefronts simply no longer use divergent session keys/observers. See Qoliber_GdprConsent 1.0.2.

GdprCookie — 2026-06-06

Fixed

  • "Cookie Type" select rendered blank for some cookies. The Cookie Detail form and listing offered only HTTP / local_storage / session_storage, but the seed data stores persistent (×13) and session (×1) too. With no matching option, Magento_Ui/js/form/element/select resolved the value to undefined, so admins saw a blank Type and re-saving could silently clear it. Added a canonical Model\Source\CookieType source (covering all five values) used by the form; the listing column carries the matching inline option set (grid select columns need an inline array, not a source object). Covered by a unit test.

Added

  • Setup/Patch/Data/ReconcileFunctionalityCookies — idempotent patch that moves product_data_storage and section_data_ids to the Functionality category on stores upgraded from 1.0.0-RC. The 1.0.0 InstallDefaultCookies reclassified these two cookies (Essential → Functionality) but, being run-once and insert-only, never moved them on existing installs, leaving them wrongly flagged as required/essential. No-op on fresh installs where they are already correct.

GdprPolicy — 2026-06-06

Fixed

  • "Cookie Consent Mode Text" was ignored when Privacy Policy Type = CMS Page. Plugin\ViewModel\CookieConsentPlugin rendered the merchant-configured consent text only for the version-based policy type; in CMS-page mode it emitted a hardcoded, untranslatable English sentence ("For more information about how we handle your data…") and ignored the configured text. The configured text is now authoritative for both policy types, with the hardcoded link kept only as a fallback when no consent text is set. Covered by an e2e test.
  • Hardened the privacy-policy render path against opaque "Error loading privacy policy". Controller\Policy\Render and both renderers (VersionBasedRenderer, CmsPageRenderer) now catch \Throwable (not just \Exception) and log the exception class + file:line, so a PHP Error returns clean JSON and a diagnosable log line instead of a 500 HTML page that the storefront surfaced as a generic failure. The effective-date placeholder replacement now degrades to today's date on a malformed stored date instead of failing the whole policy load. Covered by an e2e test.

1.0.1 — 2026-06-02

GdprAdmin

Fixed

  • GDPR Consent Logs admin grid failed to load — it showed "0 records found" with an "Something went wrong with processing the default view and we have restored the default view" error and a Something went wrong modal. etc/di.xml registered the qoliber_gdpr_consent_log_listing_data_source collection a second time (virtualType QoliberGdprConsentSearchResult → table qoliber_gdpr_consent_log), overriding the correct binding declared in Qoliber_GdprConsent (→ qoliber_gdpr_consent_customer_log). Because Qoliber_GdprAdmin is <sequence>d after Qoliber_GdprConsent, its di.xml merged last and the wrong mapping won. The grid's listing XML targets the qoliber_gdpr_consent_customer_log schema (PK log_id, columns consent_code, form_location, is_accepted, accepted_at), none of which exist in qoliber_gdpr_consent_log — so the first render threw SQLSTATE Unknown column 'log_id'. Removed the stray binding and the now-orphaned QoliberGdprConsentGridDataProvider / QoliberGdprConsentSearchResult virtualTypes so the correct Qoliber_GdprConsent data source takes effect. Verified by resolving the live grid collection: it now queries qoliber_gdpr_consent_customer_log and returns rows without error.

GdprCookie

Fixed

  • Cookie Detail form "Cookie Category" dropdown could hide categoriesUi/Component/Form/Element/CategoryOptions only listed categories with is_enabled = 1, while the cookie listing grid shows all categories. A cookie saved against a category that was later disabled lost its value on edit, because a <select> cannot render an option that is not in its option list (this matches the "category doesn't appear on edit" report). Removed the is_enabled filter so the form lists every category, consistent with the listing grid. Note: an entirely empty dropdown on a fresh install means no cookie categories have been seeded — run bin/magento setup:upgrade to apply the InstallDefaultCookies / InstallGoogleConsentCategory data patches.

1.0.0 — 2026-05-22

GdprCore

Added

  • Initial release of the shared GDPR domain kernel module.
  • Qoliber\GdprCore\Model\Enum\LawfulBasis — GDPR Art. 6 lawful-basis backed string enum (Consent, Contract, Legal Obligation, Legitimate Interests).
  • Qoliber\GdprCore\Model\Source\LawfulBasisSourceOptionSourceInterface adapter for admin forms/grids.
  • Qoliber\GdprCore\Service\AgeGateService — GDPR Art. 8 age-of-digital-consent helper. Computes age from DOB, exposes canGiveConsent() / canGiveConsentStrict() / requiresParentalConsent(). Threshold configurable (13–18, default 16) under qoliber_gdpr/age_gate/threshold; gate toggle at qoliber_gdpr/age_gate/enabled (disabled by default).
  • Domain enums (PHP 8.1 modernisation, WS5):
    • RequestStatus (backed string, 13 cases) with isTerminal() / isActive() helpers.
    • RequestType (backed string, 10 cases) with articleReference() mapping each right to its GDPR Art. 15–21 citation.
    • PolicyStatus (backed int, 4 cases — draft/active/published/archived) with isPublic() / isEditable() helpers.
    • ConsentAction (backed string, 2 cases — granted/revoked) with isPositive().
    • Legacy class-constants in consuming modules remain for back-compat; new code should prefer the enums.

GdprAdmin

Added (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • Setup/Patch/Data/SeedDefaultRopa — idempotent data patch that seeds six baseline Art. 30 processing activities (Order Fulfilment, Customer Account Management, Marketing Communications, Website Analytics, Customer Support, Fraud Prevention & Security Monitoring) on a fresh install. Lawful basis values use the Qoliber\GdprCore\Model\Enum\LawfulBasis backing strings so the Readiness Auditor's "all activities have a lawful basis" check recognises them. Seed-only-when-empty: a merchant who edited or deleted rows does not see them revived on the next setup:upgrade.
  • Service/ReadinessAuditor/Check/EmailQueueScrubbedCheck — new auditor check that FAILs when any qoliber_gdpr_email_queue row is status = sent but still carries template_vars (which holds the verification URL with the plaintext bearer token). SEC-4 Item 1 extension. Wired into etc/di.xml under email_queue_scrubbed.

Added

  • GDPR compliance dashboard with compliance score
  • Request statistics, consent overview, compliance checklist
  • Missing RequestActions UI column class for request grid
  • 4 dashboard block classes (Stats, RecentRequests, ConsentOverview, ComplianceStatus) with templates
  • Audit export controller for regulator-ready CSV export of DSR requests + consent logs + policy consents
  • Missing ACL resources for cookie management (gdpr_cookies_manage, gdpr_cookie_details)
  • GDPR Art. 6 lawful-basis integration (2026-04-20):
    • lawful_basis varchar(50) nullable column + btree index on qoliber_gdpr_processing_activities.
    • legal_basis column relaxed to nullable and marked DEPRECATED (removed in the next minor release).
    • RenameLegalBasisToLawfulBasis data patch normalises free-text legal_basis values (e.g. "Consent", "Legitimate Interests", "Art. 6(1)(a)") into the LawfulBasis enum backing strings; unknown values stay NULL and are logged for manual reclassification.
    • "Lawful Basis Review" dashboard widget counts unreviewed consent definitions and cookie categories with deep-links to filtered admin listings.
    • Audit export extended with three configuration sections (CONSENT DEFINITIONS, COOKIE CATEGORIES, PROCESSING ACTIVITIES) each carrying lawful-basis + review-stamp columns; the POLICY CONSENT LOG section also gains a Lawful Basis column.
    • Module now depends on Qoliber_GdprCore (via <sequence> in module.xml + composer).
  • Processing Activities admin CRUD (2026-04-20):
    • Full admin CRUD: listing grid (qoliber_gdpr/processingactivity/index), edit/new form, delete action.
    • ProcessingActivityInterface + model/resource/collection/repository wired through UI component DataProvider.
    • Per-row Edit/Delete actions via ProcessingActivityActions column class.
    • Menu entry under GDPR → Processing Activities; ACL: gdpr_processing (view), gdpr_processing_save, gdpr_processing_delete.
  • GDPR Readiness Auditor (2026-04-22):
    • New admin dashboard at GDPR → Readiness Auditor (qoliber_gdpr/readiness/index) showing pass / warn / fail for each compliance surface with deep-links to fix pages.
    • Service\ReadinessAuditor orchestrates checks via DI (di.xmlReadinessAuditor.checks) so other modules can register their own checks without touching GdprAdmin.
    • Five checks shipped: DpoConfiguredCheck (Art. 37–39), ConsentDefinitionsCheck (Art. 7(1)), CookieCategoriesCheck (ePrivacy Art. 5(3)), ProcessingActivitiesCheck (Art. 30 ROPA), TokenHashingHealthyCheck (SEC-4 health).
    • ACL: Qoliber_GdprAdmin::gdpr_readiness.
    • ReadinessAuditorTest (5 tests) covers aggregation, isGreen() semantics, broken-check resilience, non-Check ignored entries.

Deprecated

  • legal_basis column on qoliber_gdpr_processing_activities — kept for one release; removed in the next minor. Use lawful_basis (enum-backed) instead.

Fixed

  • DataRequestInterface namespace in RequestStatus/RequestType source models (was referencing GdprAdmin, now GdprDataSubject)
  • Module dependencies on Qoliber_GdprDataSubject and Qoliber_GdprConsent

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

GdprConsent

Fixed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • Plugin/Newsletter/Controller/Manage/SavePlugin — newsletter "Manage" Save plugin was registered against the wrong type and never executed; now correctly fires aroundExecute so the consent checkbox state on /newsletter/manage/ actually persists.
  • Block/Consent/ConsentList + view/frontend/templates/newsletter/account/manage.phtml — consent checkbox on newsletter-preferences page now pre-ticks based on the customer's existing consent record AND can be un-ticked (revocation flow). Previously the checkbox was always rendered unchecked and toggling it off had no observable effect.
  • Block/Customer/ConsentHistory + view/frontend/templates/customer/consent-history.phtml — consent-history rows now render the actual {link} placeholder via the real ConsentRendererPool (instead of the bogus literal "1.0" version string), and the "details" expander now displays the exact text the customer accepted at the time of acceptance.
  • Block/Customer/ConsentHistory::getFormLocationLabel — casts Phrasestring so the fallback branch no longer fatals the customer consent-history page.
  • Customer-account guest fatal: Controller/Consent/Save and Controller/Customer/Index (now deleted, see below) no longer 500 for guests; they consistently 302 to login. Companion fix in Qoliber_GdprDataSubject controllers.

Removed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • Controller/Customer/Index.php, view/frontend/layout/gdpr_consent_customer_index.xml, view/frontend/templates/customer/consent-history.phtml, Block/Customer/ConsentHistory.php, and the matching unit test were retired in favour of the canonical /customer/consent/preferences surface (see Qoliber_GdprPrivacyCenter). No redirect — the route is gone and the customer-journey spec asserts a 404.

Added

  • CsrfAwareActionInterface on LogConsent AJAX controller
  • SerializerInterface injected in ConsentDefinition constructor (replaces ObjectManager)
  • Age-gate plugin (Art. 8, 2026-04-20):
    • BlockMinorConsent before-plugin on ConsentTracker::trackConsents strips non-essential consent entries (marketing/analytics/etc.) for logged-in customers who (a) have a DOB below the configured threshold AND (b) lack a gdpr_parental_consent_verified customer attribute. Essentials (privacy_policy, terms_conditions) remain because they're contract/legal basis, not consent basis. Guests and customers with no DOB pass through unchanged; merchants opt in via qoliber_gdpr/age_gate/enabled.
    • 6 unit tests cover passthroughs (disabled, guest, adult, load-failure) and minor-with/without parental verification.
  • GDPR Art. 6 lawful-basis integration (2026-04-20):
    • lawful_basis, lawful_basis_reviewed_at, lawful_basis_reviewed_by columns on qoliber_gdpr_consent_definition (+ btree index on lawful_basis).
    • Three field constants and six accessor methods on ConsentDefinitionInterface / ConsentDefinition.
    • BackfillLawfulBasis data patch classifies existing consent definitions by code (privacy_policy / terms_conditions → CONTRACT, everything else → CONSENT pending admin review).
    • StampLawfulBasisReview save-before observer records reviewed_at + reviewed_by when an admin sets or changes the basis (idempotent: does not re-stamp unchanged rows).
    • Event prefix qoliber_gdpr_consent_definition registered on the model so save events fire.
    • Admin form exposes a "GDPR Lawful Basis (Art. 6)" required-entry select backed by Qoliber\GdprCore\Model\Source\LawfulBasisSource; listing grid gains "Lawful Basis" + "Basis Reviewed" columns.
    • Module now depends on Qoliber_GdprCore (via <sequence> in module.xml) for the shared enum.

Fixed

  • Guest email fallback removed -- returns null instead of fake '[email protected]'
  • Newsletter consent save -- plugin uses getPostValue() instead of getPost()->get()
  • User agent string no longer collected in consent logs (data minimization)
  • Block/Adminhtml/Customer/Tab/Consents.php: injected StoreManagerInterface, SerializerInterface and LoggerInterface; added getStoreName() and getConsentSnapshotData() helpers so the admin template no longer reaches for ObjectManager::getInstance() or raw json_decode()
  • view/adminhtml/templates/customer/tab/consents.phtml: store name + snapshot decoding delegated to the Block — removes final ObjectManager::getInstance() usage and last raw json_decode() in the admin consent history UI
  • Block/Adminhtml/Order/View/ConsentInfo.php: consent snapshot now decoded via injected SerializerInterface instead of raw json_decode(); runs on every admin order view
  • Observer/CheckoutSubmitAllAfter.php: quote consent payload now decoded via SerializerInterface (was raw json_decode()); runs on every order placement
  • Observer/CheckoutOnepageSuccess.php: session consent payload now decoded via SerializerInterface (was raw json_decode()); runs on every checkout success
  • Ui/Component/Listing/Column/FormLocations.php: admin grid column now decodes form_locations via SerializerInterface (was raw json_decode())

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

GdprConsentHyva

Fixed (strict CSP — review finding #2, QLB_GDPR_V2.1, 2026-05-20)

  • Strict-CSP safety: customer/consent/preferences/hyva_current-status.phtml + checkout/gdpr-consents.phtml converted via Hyvä's hyva-csp-helper tool. One PHP-conditional inline :class="{...}" (the required-consent error ring) the tool couldn't auto-reach was hand-converted to a CSP-safe method (...ErrorRing reading data-consent-error-id). Fixes review finding #2. Verified under the Hyva/default-csp theme.

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0
  • PHP 8.4 support added
  • All localStorage keys unified to qoliber_gdpr_* prefix
  • Dependency on qoliber/gdpr-consent bumped to stable ^1.0

Fixed

  • Magewire consent component aligned with base module server-side consent tracking
  • Alpine.js modal visibility regression when toggling checkout consents
  • Required-consent validation error state cleared correctly on successful acceptance
  • Added @theme block to view/frontend/tailwind/tailwind-source.css declaring custom color tokens (--color-gdpr-primary, --color-gdpr-primary-dark, --color-gdpr-error, --color-privacy-primary, --color-privacy-success, --color-privacy-accent) — required for Tailwind v4 / Hyvä 1.4+ builds, which no longer carry tailwind.config.js theme.extend.colors
  • Removed unused ObjectManager::getInstance() fallback for ViewModelRegistry in view/frontend/templates/checkout/gdpr-consents.phtml — Hyvä auto-injects $viewModels into every template, the fallback was dead code

GdprCookie

Added (US privacy laws — QLB_GDPR_V2.1, 2026-05-20)

  • US state-law (CCPA/CPRA + VA/CO/CT) opt-out support, layered on the existing GDPR opt-in model:
    • ViewModel/ComplianceMode + Service/GpcSignal — resolve the active compliance model and detect the Global Privacy Control opt-out signal (Sec-GPC header server-side; navigator.globalPrivacyControl client-side, which is authoritative since it is not full-page-cached).
    • CookieConsent view model now publishes a compliance block into both the Hyvä config and Luma settings JSON.
    • view/frontend/web/js/model/cookie-manager.js — in us_optout mode non-essential cookies default to allowed; a GPC signal auto-records an opt-out (keep essentials, purge sale/sharing cookies) without a click; new optOut() method.
    • view/frontend/web/js/view/do-not-sell-link.js + templates/do-not-sell-link.phtml — "Do Not Sell or Share My Personal Information" footer link (US opt-out mode only) that records an opt-out and lets the consent-updated event flip Google Consent Mode ad_* signals to denied.
    • templates/compliance-config.phtml — publishes window.qoliberGdprCompliance for both Luma and Hyvä.
    • Tests: Test/Unit/ViewModel/ComplianceModeTest (8) + Test/Unit/Service/GpcSignalTest (6 cases) + Playwright frontend/us-compliance.spec.ts (5 E2E: opt-in vs opt-out config, default-allow, GPC auto-opt-out, Do Not Sell opt-out).
    • Merchant guide: docs/US-PRIVACY-LAWS.md.

Fixed (theming — QLB_GDPR_V2.1, 2026-05-20)

  • Full-page-cache staleness on cookie config save (pre-existing, affected texts / display style / theme alike): added Qoliber\GdprFrontend\Observer\FlushPageCacheOnConfigChange, wired to admin_system_config_changed_section_qoliber_gdpr_cookie. A system-config save only invalidates the config cache type, not full_page, so the cookie banner — baked into every cached page — kept rendering the old text/theme until a manual flush. The observer cleanType()s the page cache on save, so admin changes show on the storefront immediately. Verified end-to-end: cache HIT → config change → cache MISS → next request reflects the new palette with no manual flush. (Lives in Qoliber_GdprFrontend since that module owns the qoliber_gdpr_cookie config section; see its CHANGELOG.)

Added (theming — QLB_GDPR_V2.1, 2026-04-29)

  • ViewModel/Theme — new view model that resolves the active colour scheme (light / dark / custom) into a CSS-variable map. Custom values overlay on top of the Light preset, so a partially-configured Custom theme is never visually broken.
  • view/frontend/templates/luma/theme-vars.phtml — emits an inline <style> block of CSS custom properties scoped to .gdpr-cookie-consent[data-theme="custom"]. No-op for light/dark (the static _light.less / _dark.less files already handle those).
  • view/frontend/layout/default.xml — wires the new theme-vars block after the cookie banner, gated by qoliber_gdpr_cookie/consent/enabled.
  • view/frontend/web/js/view/privacy-preferences.js::applyTheme — fix: stamp data-theme on .qoliber-gdpr-cookie-consent (the actual KO-rendered element) in addition to the legacy .gdpr-cookie-consent selector, so the variable scope is hit on the rendered banner. Without this the existing _light/_dark.less selectors silently no-op.
  • view/frontend/web/css/source/components/_privacy-preferences.less.action.primary button background + hover + border now go through var(--gdpr-btn-primary-bg, …) / var(--gdpr-btn-primary-hover, …) (was hardcoded @color-blue1 + darken(@color-blue1, 10%)). Same for __privacy-link colour + hover. Category-toggle ON state now uses var(--gdpr-toggle-on, @color-blue1). LESS-computed values stay as the compile-time fallback so Light/Dark presets that don't define the variable still render correctly. The Custom theme palette now flows end-to-end through all primary buttons and links.
  • Test/Unit/ViewModel/ThemeTest — 8 cases / 52 assertions covering scheme resolution (light / dark / custom / unknown), Custom overrides with admin-set + partial + whitespace values falling back to Light, and CSS-property rendering (underscores translated to dashes).

Added (release prep — QLB_GDPR_V2.1, 2026-04-29)

  • Plugin/Response/Http — server-side cookie suppression registered against Magento\Framework\App\Response\Http::sendResponse. On every storefront response the plugin:
    • Reads the visitor's gdpr_consent cookie (categories list)
    • Queries every cookie registered under a non-consented, non-required category in admin
    • Emits Set-Cookie: name=; expires=Thu, 01 Jan 1970 headers via CookieManagerInterface::deleteCookie() for every match present on the request
    • Honours a hard-coded NEVER_DELETE allow-list (mirrors the JS allow-list in cookie-manager.js) so an admin misconfig cannot strip session essentials
    • Closes the HttpOnly cookie gap that the JS-side interceptor in cookie-manager.js structurally cannot reach — JS cannot see HttpOnly cookies via document.cookie, but the server controls the Set-Cookie header so the browser deletes them anyway.
    • Layered on top of the JS interceptor for belt-and-suspenders coverage: JS prevents writes synchronously; this plugin cleans up one response later, including HttpOnly and server-set cookies.
  • Test/Unit/Plugin/Response/HttpTest — 8 cases, 15 assertions covering: no-consent / malformed-consent / consent-without-categories no-ops, required category never contributing to the rejection set, non-consented cookies deleted when present, NEVER_DELETE overrides admin misconfig, cookies absent from the request not redundantly deleted, consent to all categories produces no deletions.

Fixed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • view/frontend/web/js/view/cookie-settings-link.js — module now returns a constructor (function (config, element) {...}) instead of a plain object literal { initialize: ... }. Under Magento_Ui/js/core/app the new Constr(config, element) instantiation threw Constr is not a constructor and wedged knockout bindings for the rest of the page (privacy-policy KO component never bound, etc.).
  • view/frontend/templates/luma/cookie-settings-link.phtml — footer-link initialisation switched from Magento_Ui/js/core/app to a plain text/x-magento-init mapping ({"#qoliber-gdpr-footer-link": {"Qoliber_GdprCookie/js/view/cookie-settings-link": {}}}). The new init pattern matches the JS module's signature and avoids the constructor-cast issue altogether. Net effect: clicking the footer "Cookie Settings" link reliably reopens the consent banner on every page.

Added

  • 3 mass action controllers for CookieDetail (MassDelete, MassEnable, MassDisable)
  • GDPR Art. 6 lawful-basis integration (2026-04-20):
    • lawful_basis, lawful_basis_reviewed_at, lawful_basis_reviewed_by columns on qoliber_gdpr_cookie_categories (+ btree index on lawful_basis).
    • Three field constants and six accessor methods on CookieCategoryInterface / CookieCategory.
    • BackfillLawfulBasis data patch maps existing categories by is_required (essential → LEGAL_OBLIGATION, others → CONSENT pending admin review).
    • StampLawfulBasisReview save-before observer records reviewed_at + reviewed_by (idempotent: does not re-stamp unchanged rows).
    • Event prefix qoliber_gdpr_cookie_category registered on the model.
    • Admin form exposes a required-entry "GDPR Lawful Basis (Art. 6)" select backed by Qoliber\GdprCore\Model\Source\LawfulBasisSource; listing grid gains "Lawful Basis" + "Basis Reviewed" columns.
    • Module now depends on Qoliber_GdprCore (via <sequence> in module.xml).

Fixed

  • DataPersistor key mismatch in CookieCategory DataProvider
  • ObjectManager replaced with DI in CategoryOptions.php
  • Redundant acl.xml removed (ACL managed by GdprAdmin)
  • Close button (X) now calls decline() instead of closeWithoutSaving() in all templates
  • Clicking entire category row toggles the switch (not just toggle element)
  • Empty categories without cookies are hidden from consent banner
  • Allow Selection button now visible on all tabs including About
  • Cookie consent banner ifconfig path corrected to qoliber_gdpr_cookie/consent/enabled
  • Unknown cookies always blocked (removed permissive mode branch)
  • checkConsentStatus() reads consent cookie properly (was always showing banner)
  • toggleScripts() implements deny-by-default script activation

Changed

  • All localStorage keys unified to qoliber_gdpr_* prefix
  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

GdprCookieHyva

  • Category toggles never turned green when on. view/frontend/templates/hyva/theme-vars.phtml styled the "on" track with .peer-checked\:bg-green-600:has(:checked), but the track <span> does not contain the checkbox (it is a sibling), so :has(:checked) never matched — while .bg-gray-300 { … !important } forced the track to the off colour unconditionally. Corrected the selector to the peer-sibling form .peer:checked ~ .peer-checked\:bg-green-600. Also fixed the Details-tab track markup (peer-checked peer-disabledpeer-checked:bg-green-600 peer-disabled:bg-gray-400) in cookie-consent.phtml.
  • Banner animation under strict-CSP. x-transition keyframes used inline ternary expressions, which the Alpine CSP build cannot evaluate (and which it applies as literal class names), so the popup never animated. Replaced with static opacity-fade keyframes; the layout position class is now emitted server-side (from getDisplayStyle()) instead of via :class, because binding :class on the same element as x-transition lets the reactive update clobber the transition.
  • Backdrop blur popped in after the popup. The backdrop-blur overlay lived inside the popup wrapper, whose animating opacity forms a "backdrop root" — so the nested backdrop-filter could not blur the page until the wrapper settled. Moved the backdrop to a sibling of the popup (direct child of the non-animating root) with its own opacity fade matched to the popup; the wrapper is pointer-events-none and the content pointer-events-auto so click-outside-to-close still reaches the backdrop. Blur now fades in/out in lockstep with the popup.
  • view/frontend/tailwind/tailwind.config.jssafelist for the toggle peer-state classes, fade keyframes, and the backdrop layering/click-through utilities so they are always emitted.

Added (US privacy laws — QLB_GDPR_V2.1, 2026-05-20)

  • view/frontend/layout/hyva_default.xml — wires two new Hyvä blocks for US state-law support: compliance-config.phtml (publishes window.qoliberGdprCompliance so the Alpine/JS layer knows the opt-in vs opt-out model + GPC state) and the "Do Not Sell or Share" link block (US opt-out mode only, placed in before.body.end for theme-agnostic safety — relocatable to a footer container via theme override). Runtime + ViewModels live in Qoliber_GdprCookie; see docs/US-PRIVACY-LAWS.md.

Added (theming — QLB_GDPR_V2.1, 2026-04-29)

  • view/frontend/templates/hyva/theme-vars.phtml — emits an inline <style> block of CSS custom properties under #qoliber-gdpr-cookie-consent[data-theme="..."] for all three schemes (Hyvä has no .less of its own, so this is the only output path). The same block layers specificity-tied overrides on top of Tailwind colour utilities used inside the cookie banner template, so the existing markup is re-skinned without touching it.
  • view/frontend/layout/hyva_default.xml — wires the new theme-vars block after the cookie banner block.
  • view/frontend/templates/hyva/cookie-consent.phtml — adds id="qoliber-gdpr-cookie-consent" and data-theme="<scheme>" to the outer Alpine wrapper so the theme-vars selector matches. The Theme ViewModel resolves the scheme.

Fixed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • view/frontend/templates/hyva/privacy/cookie-card.phtml — "Manage Cookies" button on the Hyvä Privacy Center now actually reopens the cookie banner. Replaced the broken inline onclick (CSP-incompatible, used a malformed [ x-data="..." *=gdprCookieConsent] selector that matched nothing) with a proper Alpine x-on:click that dispatches gdpr-reopen-settings. The cookie-consent component already listens for that event, so the existing reopenSettings() flow runs end-to-end.
  • view/frontend/templates/hyva/cookie-consent.phtml — inline policy modal now fetches /gdpr/policy/render (the real JSON endpoint) instead of /gdpr/policy/view (404). The fetch is escaped via $block->getUrl(...) so it picks up the correct frontName and store base URL.

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0
  • PHP 8.4 support added
  • Dependency on qoliber/gdpr-cookie bumped to stable ^1.0
  • All localStorage keys unified to qoliber_gdpr_* prefix

Fixed

  • Close button (X) triggers decline flow instead of closing without saving
  • Clicking full category row now toggles the switch (not just the toggle element)
  • Empty categories (no cookies) are hidden from the consent banner
  • "Allow Selection" button visible on all tabs including About
  • Unknown cookies always blocked (permissive mode branch removed)
  • Consent cookie state restored correctly on subsequent page loads
  • Template name validated against whitelist to prevent template injection
  • TypeError: Cannot read properties of undefined (reading 'classList') in view/frontend/templates/hyva/cookie-consent.phtml — replaced this.el.classList.add(...) with el.classList.add(...) in the Alpine $nextTick callbacks that style .gdpr-policy strong / .gdpr-policy a elements inside the consent banner
  • Google Consent Mode v2 bypass (High): view/frontend/layout/hyva_default.xml removed the block registration for hyva/google-consent-init.phtml, which was loading gtag.js / gtm.js unconditionally regardless of consent state. The correct, lazy-loading path in qoliber/gdpr-frontend-hyva (consent/google-tag.phtml) now handles Google Consent Mode v2 on Hyvä — scripts load only after the user grants analytics_storage or ad_storage.

GdprCookieTemplates

Fixed

  • Namespace corrected from Qoliber\CookieDetailsTemplates to Qoliber\GdprCookieTemplates in controller

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

GdprDataSubject

Fixed (review findings — QLB_GDPR_V2.1, 2026-05-20)

  • Guest DSAR postback broken after SEC-4 token hardening. The guest data-view templates submitted $dataRequest->getToken() for export / anonymization POSTs, but the plaintext token column is scrubbed post-notification (SEC-4), so those posts sent an empty token and failed. They now submit $token — the bearer token from the URL the guest actually arrived with (the page already loads/validates against it). Fixed in view/frontend/templates/guest/view-data.phtml and GdprDataSubjectHyva .../hyva/datasubject/guest/view-data.phtml.
  • Stale plaintext-token assumption in anonymization cron. Cron/ProcessAnonymizationRequests passed $request->getToken() (now empty) into the original fetch-data request's response_data as anonymization_token, and Controller/Guest/ViewData redirected using it. Both are stale and an at-rest leak risk if a legacy plaintext token ever reappears. Removed the token from response_data entirely; ViewData no longer stitches one request's bearer token into another's URL — it renders the current page (already authenticated by the guest's valid URL token) with an anonymization_completed flag instead.
  • Cron/ProcessEmailQueue — after a successful send, the cron now nulls out template_vars on the qoliber_gdpr_email_queue row. That blob holds the verification URL with the plaintext bearer token, so leaving it on disk after the email has been delivered violates SEC-4 ("zero plaintext bearer token at rest").
  • Setup/Patch/Data/ScrubSentEmailTemplateVars — one-shot data patch for existing rows: UPDATE qoliber_gdpr_email_queue SET template_vars = NULL WHERE status = 'sent' AND template_vars IS NOT NULL. Runs once on setup:upgrade, idempotent on re-run.
  • Test/Unit/Regression/TokenLeakRegressionTest::testEmailQueueProcessorScrubsTemplateVarsAfterSend — greps the cron source for the literal setTemplateVars(null) call so a future refactor that drops the scrub fails this test rather than silently regrowing the at-rest leak.

Removed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • Controller/Request/Index.php and the matching view/frontend/layout/gdprds_request_index.xml — the /gdprds/request/index route was a duplicate of the Privacy Center surface (/customer/account/privacy) and shipped with its own (drift-prone) UI. Retired with no redirect; the customer-journey spec asserts a 404 response so a future re-add fails CI.
  • Controller/Customer/{Anonymize,Delete,Rectification}* standalone controllers (the mutating endpoints *Post are kept; only the standalone GET render controllers were removed). All flows now live inside the Privacy Center page.

Fixed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • Customer-account guest 500: Controller/Account/Privacy, Controller/Customer/AnonymizePost, Controller/Customer/DeletePost, Controller/Customer/Objection, Controller/Customer/RectificationPost, Controller/Customer/Restriction now consistently 302 to login for guests instead of fataling. The fix uses Magento's Customer\Controller\Plugin\Account aroundExecute pattern.

Added

  • GDPR Art. 18 / Art. 21 DSAR integration + status-transition audit log (2026-04-20):
    • New table qoliber_gdpr_request_history records every DSAR status transition (from/to status, changed_by, change_source, note, timestamp); CASCADE FK to qoliber_gdpr_requests.
    • New table qoliber_gdpr_marketing_suppression (unique on email+scope) holds Art. 21 / Art. 18 suppression entries; MarketingSuppressionService exposes isSuppressed() + add().
    • StageStatusTransition + PersistStatusTransition observer pair on qoliber_gdpr_request_save_before / _save_after captures every status change (admin / cron / api / customer source inferred).
    • Event prefix qoliber_gdpr_request registered on the model so save events fire.
    • ProcessRestrictionRequests cron (every 15 min) processes Art. 18 DSARs: adds suppression scope=all (marketing freeze; transactional processing remains permitted per Art. 18(2)); transitions DSAR to completed.
    • ProcessObjectionRequests cron (every 15 min) processes Art. 21 DSARs: adds suppression scope=marketing; transitions DSAR to completed.
    • Block/Adminhtml/Request/View/History now renders real history rows (repo query, newest-first); admin template updated to show from/to status, source, admin user, note.
  • SEC-4 at-rest token hashing (2026-04-20):
    • New token_hash varchar(64) column + index on qoliber_gdpr_requests; plaintext token retained for one transition release.
    • TokenHasher service (HMAC-SHA256 keyed on env.php crypt.key; encryptor fallback) — never logs the plaintext.
    • BackfillTokenHash data patch hashes every pre-existing token in chunks of 2000 rows (idempotent, NULL-guarded).
    • StampTokenHash observer (model_save_before) stamps the hash whenever the plaintext token is set or changed, so all write paths are covered.
    • DataRequestRepository::getByToken() looks up by hash first, falls back to plaintext only while the transition column exists.
  • SEC-4 hardening (2026-04-21):
    • DataRequestRepository::getByToken() is now hash-only — the plaintext fallback is gone.
    • Every guest-flow call site (Anonymization/Request, Anonymization/Confirm, Anonymization/Status, Export/Download, Guest/ViewData, GuestDataViewModel, AnonymizationStatusViewModel) switched from direct addFieldToFilter('token', ...) / load($model, $token, 'token') to repository->getByToken(), so plaintext reads on the token column no longer occur at runtime.
    • Removed original_token / parent_token keys from serialized request_data / response_data JSON — these turned the hashed column into a plaintext leak via audit trail. Replaced with original_request_id / parent_request_id.
    • Removed the setToken($token . '_download_' . time()) mutation hack in Export/Download; the audit row now records the download event with stable integer linkage only.
    • Single-use verification. Request/Verify rotates the token on successful verification (UUID v4) — any replay of the verification URL hashes to a value no row carries and lands in the "invalid" branch.
    • Guest/ViewData now enforces status-whitelist (CONFIRMED / PROCESSING / NOTIFIED / ACCESSED / ANONYMIZATION_REQUESTED) and a non-null future expires_at; previously a pending_confirmation row with a valid token could render personal data.
    • New tests: VerifyRotatesTokenTest (3), ViewDataValidationTest (5), CleanupExpiredRequestsNestedTest (2), TokenLeakRegressionTest (3). Full suite 176/176 green.
  • SEC-4 closure push (2026-04-21):
    • Fail-closed on missing expiry everywhere. Verify, Anonymization/Confirm, Anonymization/Status, and DataRequestViewModel::assertViewable() now reject rows with expires_at = NULL the same as already-expired rows. NULL is treated as misconfiguration, never "valid forever".
    • Plaintext token scrubbed post-notification. Both notification crons (ProcessDataFetchRequests, ProcessDataAccessNotifications) now blank the plaintext token column after the email is sent. token_hash stays intact so the recipient's click still resolves.
    • Observer semantics updated. StampTokenHash no longer clears token_hash when the plaintext is cleared — caller (typically the cron scrub path) drives that now. Full hash-reset requires both columns to be nulled explicitly.
    • Export path hardened (Finding 1). ProcessDataFetchRequests::generateDataFiles() now derives the on-disk export directory + filename from the stable integer request_id, not the bearer token. The token remains the encryption key but never appears in response_data['data_files'][*]['file_path'].
    • Historical scrub. New ScrubPostNotificationTokens data patch blanks plaintext for every existing row already past the notification stage (NOTIFIED / ACCESSED / COMPLETED / EXPIRED). Idempotent; depends on BackfillTokenHash.
    • New tests: DataRequestViewModelExpiryTest (4), CronWipesPlaintextTokenTest (2), DsarLifecycleScenarioTest (1 end-to-end scenario), TokenLeakRegressionTest expanded by 1. Full suite 184/184 green.
  • Logger/Handler.php and Logger/Logger.php classes
  • queueVerificationEmail() method in EmailService
  • Verification email template registration
  • Tax retention period config (7 years default) to prevent anonymization of recent financial records
  • Legal hold constants in DataRequestInterface (STATUS_LEGAL_HOLD, block reason types)
  • Article 15 metadata in DataFetcherService for GDPR-compliant exports
  • Data retention admin config group (consent_log_days, verification_token_hours, export_file_hours, expired_request_days)
  • Legal hold documentation section in admin config
  • Production readiness validator -- blocks enablement without DPO email/name and notification template

Fixed

  • Removed legacy DataAccessRequest model, resource model, and collection (wrong table name)
  • Rewritten Submit, GuestSubmit, Verify controllers on DataRequestRepository
  • Cron wired to ProcessDataFetchRequests (was ProcessDataAccessNotifications)
  • Cron fetches confirmed requests (was filtering for pending)
  • Store ID type mismatch in fetch cron (scalar to array)
  • QuoteDataAnonymizer config path (was checking creditmemo config)
  • ProcessAnonymizationRequests status overwrite + DatarequestInterface typo
  • DataAnonymizationService record totaling
  • Customer account locked after anonymization (is_active=0, failures_num=999)
  • AccountManagementPlugin checks both is_active and failures_num for login blocking
  • Export writes temporary files instead of storing payloads in response_data
  • Download marks request as ACCESSED status

Removed

  • DataAccessRequest legacy model and collection
  • Privacy.php.bak file
  • PDF from default export formats (txt,csv,json only)
  • PDF translation entries from all i18n files
  • Placeholder DPO defaults ([email protected], John Doe, +1-555-123-4567)
  • Non-existent Cron\ProcessDataRequests reference from di.xml

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

GdprDataSubjectHyva

Fixed (strict CSP — review finding #2, QLB_GDPR_V2.1, 2026-05-20)

  • Strict-CSP (Alpine CSP build) safety: all Hyvä templates converted via Hyvä's hyva-csp-helper migration tool — inline x-data object literals, x-model, x-init, x-effect, @change/@click/x-on:submit handlers, and :class object/ternary expressions extracted into registered Alpine.data components + $hyvaCsp->registerInlineScript(). Fixes review finding #2 (export form, data-request, guest view-data, customer anonymize/delete/rectification, quick-actions). Verified: guest data-request page renders under the Hyva/default-csp theme with 0 console errors.

Fixed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • view/frontend/templates/customer/privacy/cards/export.phtml — "Export Now" button on the Hyvä Privacy Center now scrolls to the actual export form. The button targeted #export-section (legacy id from the Luma layout) but the real anchor on the Hyvä page is #export-form, so the click resolved to no element and did nothing. Both the href and the @click.prevent scrollIntoView call now use #export-form.

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0
  • PHP 8.4 support added
  • Dependency on qoliber/gdpr-data-subject bumped to stable ^1.0
  • Terminology aligned with base module: "deletion" → "account closure & anonymization"

Fixed

  • Privacy dashboard quick-action card labels match base module naming
  • Guest data request form correctly submits via Hyvä's Alpine.js AJAX helpers
  • Data export download link opens fresh request against rate-limited endpoint

Hyvä 1.4 / Tailwind v4 compatibility

  • Verified against Hyvä theme ^1.4 with Tailwind v4 JIT build
  • No code changes required — module uses only core Tailwind utilities present in the default theme

GdprDemo

Fixed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • ViewModel/DemoLinks::getCustomerRequestUrl — "Request My Data" demo link now points at the canonical Privacy Center surface (customer/account/privacy) instead of the retired gdprds/request/index route. The old route was deleted in this release (see Qoliber_GdprDataSubject CHANGELOG); the demo bar would have surfaced a 404 otherwise.

Added

  • Production-mode gate (2026-04-21): the demo bar is automatically hidden when Magento runs in production mode (bin/magento deploy:mode:show == production). Merchants can override per-store via qoliber_gdpr_demo/settings/force_enabled (default: 0) for demo/staging instances that deliberately run in production mode. DemoLinks::isEnabled() is the single source of truth, exercised by both Luma and Hyvä templates.
  • Initial release — storefront demo helper bar
  • Top-of-page ribbon with a DEMO badge and quick links to every public GDPR flow:
    • Guest Data Request (gdprds/guest/datarequest)
    • Privacy Center (customer/account/privacy, login required)
    • Request My Data (gdprds/request/index, login required)
    • Consent History (gdpr-consent/customer/index, login required)
    • Privacy Policy (gdpr/policy/render)
    • Cookie Preferences — re-opens the cookie consent banner by clearing stored consent + reloading
  • Two styled variants:
    • Luma: purple/indigo gradient + Less stylesheet (view/frontend/web/css/source/_module.less)
    • Hyvä: Tailwind v4 utilities with Alpine.js cookie-reopen handler and Hyvä CSP registration
  • ViewModel\DemoLinks supplies all URLs + a isCustomerLoggedIn() helper so links that require authentication are flagged with a "(login required)" hint

Non-goals

  • Not intended for production merchants. The bar is meant to help demo visitors (and partners evaluating the suite) discover every GDPR flow without hunting for URLs.
  • Module sequences after all core Qoliber GDPR modules so its layout handles apply last.

Requirements

  • PHP 8.1, 8.2, 8.3, or 8.4
  • qoliber/gdpr-data-subject: ^1.0
  • qoliber/gdpr-privacy-center: ^1.0
  • qoliber/gdpr-policy: ^1.0
  • qoliber/gdpr-cookie: ^1.0

GdprFrontend

  • etc/config.xml — the custom-theme colour group seeded only 6 of the 32 admin colour fields, so the other 26 pickers rendered empty even though Qoliber\GdprCookie\ViewModel\Theme::LIGHT_DEFAULTS defines the full palette. Seeded all 32 fields from LIGHT_DEFAULTS so every colour picker is pre-filled out of the box.
  • Model/Config/Backend/ConsentEnabledValidator — the "cannot enable Cookie Consent" DPO errors pointed to a non-existent section ("Stores > Config > Data Subject Requests > DPO"). Corrected to the real path: "Stores > Config > GDPR Compliance > Data Subject Rights > Data Protection Officer".

Added (US privacy laws — QLB_GDPR_V2.1, 2026-05-20)

  • Model/Config/Source/ComplianceMode + etc/adminhtml/system.xml compliance group: a store-view-scoped Compliance Mode (gdpr_optin default / us_optout), plus "Honour GPC", "Show Do Not Sell link", and link-text fields. etc/config.xml seeds the defaults. Lets a merchant run EU store views opt-in and US store views opt-out (CCPA/CPRA, Virginia, Colorado, Connecticut, …).
  • See Qoliber_GdprCookie for the runtime (GPC detection, opt-out cookie behaviour, Do Not Sell link) and docs/US-PRIVACY-LAWS.md for the merchant guide.

Added (theming — QLB_GDPR_V2.1, 2026-05-20)

  • Model/Config/Source/ConsentThemeCustom (admin-defined colours) option added alongside Light / Dark.
  • etc/adminhtml/system.xml — new theme_custom group with 6 "basics" colour pickers + ~24 "advanced" fields, gated by <depends> on consent/theme = custom.
  • etc/config.xmltheme_custom defaults (the six basics) seeded from the Light preset.
  • Block/Adminhtml/System/Config/Field/Color — HTML5 colour-picker field renderer paired with a hex text input (so rgba() / box-shadow strings can be pasted for the advanced fields).
  • Observer/FlushPageCacheOnConfigChange + etc/adminhtml/events.xml — purges the full-page cache when the qoliber_gdpr_cookie config section is saved (event admin_system_config_changed_section_qoliber_gdpr_cookie). Fixes pre-existing FPC staleness affecting the cookie banner texts / display style / theme — admin changes now show on the storefront immediately, no manual flush. 1 unit test (Test/Unit/Observer/FlushPageCacheOnConfigChangeTest).

Added

  • acl.xml for Qoliber_GdprFrontend::config ACL resource
  • Production readiness validator -- blocks cookie consent enablement without DPO + privacy policy

Fixed

  • Google Tag script loads dynamically only after consent (deny-by-default)
  • Missing strict_types declarations

Removed

  • Hard Hyva dependency from composer.json

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

GdprFrontendHyva

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0
  • PHP 8.4 support added
  • Dependency on qoliber/gdpr-frontend bumped to stable ^1.0

Fixed

  • GTM noscript tag now respects consent state (only rendered when analytics/marketing consent granted)
  • Google Consent Mode v2 default-state handling aligned with base module
  • Hyvä CSP registration applied to all inline consent scripts

Hyvä 1.4 / Tailwind v4 compatibility

  • Verified against Hyvä theme ^1.4 with Tailwind v4 JIT build
  • No code changes required — module uses only core Tailwind utilities present in the default theme

GdprGtm

Fixed

  • Empty google-tag-manager-noscript.phtml populated with GTM noscript iframe fallback

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

GdprPolicy

Security (review findings — QLB_GDPR_V2.1, 2026-05-20)

  • Removed the anonymous POST /V1/gdpr/policy/consent/log REST route. It exposed PolicyConsentRepository::logConsent() — which accepts a caller-supplied customerId — to unauthenticated callers, letting anyone forge policy-consent evidence against arbitrary customer IDs. All legitimate consent logging goes through the session-aware frontend controllers (Controller/Consent/Log, Controller/Policy/Accept), which derive customerId from the customer session and never trust client input; the storefront JS posts to those, not this route. The authenticated read routes (self with forced %customer_id%, ACL-gated views) are unchanged.

Added

  • PolicySection model, resource model, and collection classes
  • CsrfAwareActionInterface on Consent/Log controller
  • Policy re-consent wiring (2026-04-20):
    • ReconsentChecker service determines whether a customer must re-accept the active policy: returns true on version bump, false on contract/legal-obligation basis (compulsory acceptances don't re-prompt), true on legitimate-interests basis (allows objection prompt).
    • Reconsent storefront ViewModel — templates call needsReconsent(); guests short-circuit to false, logged-in customers get a server-side check against hasAcceptedCurrentVersion + lawful-basis gate.
    • Fully unit-tested (8 tests covering version match, version change, all four bases, invalid inputs, repo-exception handling).
  • GDPR Art. 6 lawful-basis integration (2026-04-20):
    • lawful_basis varchar(50) nullable column + btree index on qoliber_gdpr_policy_consent.
    • PolicyConsentInterface::LAWFUL_BASIS constant, getLawfulBasis() / setLawfulBasis() accessors on interface and PolicyConsent model.
    • PolicyConsentRepository::save() stamps LawfulBasis::CONSENT on every new row that arrives without a basis — every policy acceptance is Art. 6(1)(a) CONSENT by definition; stamping at write time keeps evidence travelling with the row.
    • BackfillPolicyConsentLawfulBasis chunked data patch (5000 rows/pass) classifies historical rows as CONSENT; idempotent.
    • Module now depends on Qoliber_GdprCore (via <sequence> in module.xml + composer).
  • Server-side policy acceptance evidence in Accept.php via policyConsentRepository->logConsent()
  • Server-side evidence in privacy-policy.js modal flow
  • Server-side evidence in privacy-policy-manager.js setAcceptance() -- ALL acceptance paths now log to DB
  • Server-side evidence in Hyva privacy-policy.phtml
  • needsReconsent() method in PrivacyPolicy ViewModel

Fixed

  • Removed extra $policyType parameter from logConsent() call
  • Removed undefined $policyType variable in PolicyConsentRepository
  • Guarded getCmsPageId() with method_exists check
  • Effective date "Today" replaced with actual formatted date
  • h2 headers now bold in privacy policy content
  • Effective date text color contrast improved
  • Privacy policy consent link uses gdpr/policy/render route instead of generic Magento URL
  • Default consent display_type changed to privacy_policy_link

Changed

  • All localStorage keys unified to qoliber_gdpr_* prefix
  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

GdprPolicyHyva

Fixed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • view/frontend/templates/hyva/privacy/policy-card.phtml — "View Policy" card on the Hyvä Privacy Center now renders a self-contained Alpine modal that fetches /gdpr/policy/render and displays the policy content inline. Previously, when display_location was anything other than modal / cookie_consent, the card linked directly to /gdpr/policy/render — which is a JSON endpoint, so customers landed on a raw JSON page instead of formatted policy text. The new modal works regardless of admin display-location config.

Added

  • Initial stable release of Hyvä theme compatibility for Qoliber GDPR Policy
  • Hyvä-native privacy policy rendering templates using Tailwind CSS and Alpine.js
  • CookieConsentPlugin for Hyvä-specific integration with cookie consent flow
  • Hyvä layout integration via etc/frontend configuration
  • Server-side policy acceptance evidence logged through the base GdprPolicy repository

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0
  • PHP 8.4 support added

Hyvä 1.4 / Tailwind v4 compatibility

  • Verified against Hyvä theme ^1.4 with Tailwind v4 JIT build
  • No code changes required — module uses only core Tailwind utilities present in the default theme

Requirements

  • PHP 8.1, 8.2, 8.3, or 8.4
  • hyva-themes/magento2-theme-module: ^1.3.11
  • qoliber/gdpr-policy: ^1.0
  • Magento Framework

GdprPrivacyCenter

Changed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • view/frontend/layout/customer_account.xml — sub-navigation entry under Privacy Center renamed from "My Consent History" to "Consent Preferences" (URL customer/consent/preferences is unchanged). The page actually lets the customer accept / reject each consent AND shows the history of those decisions; the old label implied a read-only view.
  • Removed the duplicate Privacy Center sidebar entry that Qoliber_GdprDataSubject was registering (its view/frontend/layout/customer_account.xml was deleted). Two modules adding the same nav link is a real bug: the customer-journey spec now asserts toHaveCount(1) so a future re-introduction fails CI.

Fixed (release prep — QLB_GDPR_V2.1, 2026-04-27 → 2026-04-28)

  • Controller/Center/Index — guest visits to /customer/account/privacy now consistently 302 to login instead of fataling. The fix uses the standard Magento Customer\Controller\Plugin\Account aroundExecute pattern.

Fixed

  • Removed non-existent Qoliber_Core dependency from module.xml
  • Controller/Center/Index.php missing parent::__construct() call
  • Privacy Center nav link path (customer/account/privacy)
  • Consent History nav link path (gdpr-consent/customer/index)

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

GdprPrivacyCenterHyva

Added

  • Initial stable release of Hyvä theme compatibility for Qoliber GDPR Privacy Center
  • Hyvä-native customer account privacy dashboard templates
  • Quick action cards for data export, rectification, anonymization, and account closure
  • Tailwind CSS styling consistent with Hyvä design system
  • Responsive mobile-first layout for privacy center pages
  • Customer account navigation integration in Hyvä layouts

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0
  • PHP 8.4 support added

Fixed

  • EOF normalization in view/frontend/tailwind/tailwind-source.css (trailing newline) applied by Hyvä source scanner during Tailwind v4 build — confirms the file is picked up by npx hyva-sources

Requirements

  • PHP 8.1, 8.2, 8.3, or 8.4
  • hyva-themes/magento2-theme-module: any version
  • qoliber/gdpr-privacy-center: any version
  • Magento Framework

GdprYireoGtm

Changed

  • Version bump from 1.0.0-rc1 to 1.0.0, PHP 8.4 support added

1.0.0-rc1 — 2025-08-27

GdprAdmin

Added

  • Created administrative GDPR dashboard with compliance score calculation based on active policies, cookie categories, processing activities, and pending requests
  • Implemented unified admin menu structure for centralized GDPR management
  • Added Data Processing Activities tracking system with legal basis documentation (GDPR Article 30 record of processing activities)
  • Developed processing activities database schema with support for activity name, description, legal basis, data categories, retention periods, and recipients
  • Created admin grid for viewing and managing GDPR data subject requests across all modules
  • Implemented RequestsDataProvider for UI component listing with filtering and sorting capabilities
  • Added Dashboard block with real-time statistics including request counts by status, recent consent logs, and consent statistics by type and action
  • Developed compliance score metric that evaluates: active privacy policies (25%), configured cookie categories (25%), documented processing activities (25%), and timely request handling (25%)
  • Created ACL resources for role-based access control to GDPR administrative functions
  • Implemented admin routing configuration for dashboard and requests management pages
  • Added admin layout XML files for dashboard and requests listing views
  • Created UI component XML configuration for GDPR requests listing grid with custom columns
  • Implemented source models for request types (fetch_data, anonymize, delete, rectification, objection, restriction) and request statuses (pending, processing, completed, failed, expired)
  • Added ProcessingActivity model, resource model, and collection for ROPA (Record of Processing Activities) management
  • Developed database indexes for efficient querying of processing activities
  • Created system configuration section for GDPR admin settings under Stores > Configuration
  • Implemented admin menu items under Privacy & GDPR section with access to Dashboard and Data Subject Requests
  • Added support for tracking customer consent history and GDPR request lifecycle
  • Created comprehensive database schema with timestamped audit trails for all processing activities

Technical Details

  • Database table: qoliber_gdpr_processing_activities with fields for activity tracking, legal basis, data categories, retention periods, and recipients
  • Admin controllers for dashboard display and request management interface
  • Integration with Magento Backend, UI components, and admin routing system
  • Support for multi-store environments with store-scoped configurations

GdprConsent

Added

  • Created comprehensive consent management system with support for explicit user consent tracking
  • Implemented ConsentDefinition entity for managing different types of consent (marketing, analytics, terms, privacy policy)
  • Developed ConsentTracker service for recording consent acceptance with IP address and user agent logging
  • Added consent snapshot functionality to preserve exact consent text version at time of acceptance (GDPR Article 7 proof of consent)
  • Created multi-store consent label support with store-view-specific translations
  • Implemented consent log database schema with customer consent history tracking including order association
  • Developed ConsentDefinitionRepository and ConsentLogRepository for consent data management
  • Added form location tracking for consents across registration, checkout, contact, and newsletter forms
  • Created renderer pool system with Text and CMS Page renderers for flexible consent display
  • Implemented consent checkbox integration for customer registration forms
  • Added consent collection during checkout process with PaymentInformationManagement and ShippingInformationManagement plugins
  • Developed newsletter subscription consent tracking with dedicated plugins
  • Created contact form consent integration with PostPlugin
  • Implemented customer account consent history view with revocation capability
  • Added admin consent management interface with create, edit, delete, and mass operations
  • Developed consent log viewer in admin with customer email lookup and filtering
  • Created consent information display in admin order view showing accepted consents per order
  • Implemented customer consent tab in admin customer edit page
  • Added ConsentConfigProvider for checkout page consent rendering via Knockout.js
  • Developed consent preferences page for customers to view and manage their consent choices
  • Created consent link service for generating privacy policy and terms links
  • Implemented consent validation rules system with JSON-based configuration
  • Added support for required vs optional consents with frontend validation
  • Developed consent display types: text, CMS page link, external URL with configurable link targets (_self, _blank, modal)
  • Created InstallDefaultConsents data patch installing pre-configured consent definitions for terms, privacy policy, marketing, and newsletter
  • Implemented UpdateConsentTextLinks data patch for consent link management
  • Added console command for listing all configured consents (gdpr:consent:list)
  • Developed ConsentList block for frontend consent display with renderer support
  • Created checkout GdprConsents block for consent collection during order placement
  • Implemented customer consent history block showing granted/revoked consent timeline
  • Added order view consent information block for admin
  • Developed Ajax consent logging endpoint for asynchronous consent tracking
  • Created consent save controller for customer preference updates
  • Implemented mass enable/disable operations for admin consent management
  • Added ACL resources for granular consent management permissions
  • Developed admin routing for consent CRUD operations and consent log viewing
  • Created UI components for consent listing and form editing with custom columns
  • Implemented consent status column renderer for admin grids
  • Added customer email column renderer with customer account linking
  • Created form locations multi-select column renderer
  • Developed event observers for checkout success, customer registration, and order placement
  • Implemented frontend events configuration for consent tracking on key customer actions
  • Added WebAPI configuration for REST endpoint exposure
  • Created extension attributes for order consent data attachment
  • Implemented system configuration for consent module settings
  • Added frontend routes for consent preferences and customer consent management
  • Developed consent snapshot serialization with full consent text preservation
  • Created IP address and user agent tracking for consent audit trail
  • Implemented guest email consent tracking separate from customer consent
  • Added consent revocation timestamp tracking
  • Developed additional data field for consent-specific metadata storage
  • Created database indexes for efficient consent lookup by customer ID, email, consent code, and acceptance date
  • Implemented foreign key constraints for data integrity across consent tables
  • Added store ID tracking for multi-store consent management
  • Developed order entity association for checkout consent linking

Technical Details

  • Database tables: qoliber_gdpr_consent_definition, qoliber_gdpr_consent_store_label, qoliber_gdpr_consent_customer_log, qoliber_gdpr_consent_log
  • ConsentTracker service captures consent with IP, user agent, store context, and full consent snapshot
  • Consent snapshot stored as JSON with consent ID, code, title, description, checkbox text, required flag, timestamp, and store ID
  • Support for multiple form locations: registration, contact, newsletter, checkout, custom
  • Renderer pool architecture allows extensible consent display formats
  • Plugin-based integration ensures consent collection across Magento checkout flow
  • Multi-language support via store-specific consent labels
  • Granular ACL permissions for consent administration
  • API interfaces for programmatic consent management
  • Frontend layout integration across customer account, checkout, registration, contact, and newsletter pages
  • Observer pattern for automated consent logging on customer lifecycle events

GdprConsentHyva — 2024

Added

  • Initial Hyva theme compatibility module for Qoliber GDPR Consent
  • Magewire Component Integration: Implemented GdprConsents Magewire component for Hyva Checkout integration
    • Real-time consent state management using Magewire reactive properties
    • Implements EvaluationInterface for Hyva Checkout validation workflow
    • Live consent synchronization with checkout session
    • Component lifecycle methods (mount, acceptAll, rejectAll, clearConsents)
    • Protected methods from frontend calls via uncallables configuration
    • Full-screen loading indicators for consent actions
  • Alpine.js Component: Created qoliberGdprConsent Alpine.js component following Hyva patterns
    • Boolean object pattern for modal visibility management
    • Error state handling with visual feedback (red text on invalid required consents)
    • Real-time error message updates via custom events
    • Integration with Hyva's createBooleanObject helper
  • Hyva Checkout Templates: Purpose-built templates for Hyva Checkout
    • Magewire-powered checkout consents template with wire:model bindings
    • Modal slide-out panel for consent details with Tailwind transitions
    • Accept All / Required Only action buttons
    • Responsive design with mobile-first approach
    • Heroicons Solid integration for UI consistency
  • Layout Integration: Comprehensive Hyva layout support
    • hyva_checkout_components.xml: Magewire component registration in checkout flow
    • hyva_default.xml: Global Hyva theme integration
    • hyva_contact_index_index.xml: Contact form consent integration
    • hyva_customer_account_create.xml: Registration form consents
    • hyva_newsletter_manage_index.xml: Newsletter subscription consents
    • hyva_customer_account_privacy.xml: Privacy dashboard integration
    • hyva_customer_consent_preferences.xml: Consent preference management
    • default_hyva.xml: Fallback layout for Hyva detection
  • Customer Privacy Dashboard: Hyva-styled templates for consent management
    • hyva_hero.phtml: Hero section with gradient backgrounds
    • hyva_history.phtml: Consent history timeline view
    • hyva_current-status.phtml: Current consent status cards
    • Privacy center card integration with Tailwind styling
  • Newsletter Integration: Enhanced newsletter subscription with consent handling
    • Subscribe template with inline consent checkboxes
    • Proper consent validation before subscription
  • Consent Rendering System: ConsentRendererPool integration
    • Dynamic checkbox text rendering with privacy policy links
    • HTML content support with proper escaping
    • Fallback mechanisms for renderer failures
  • Event Handling: Observer pattern for checkout workflow
    • CheckoutSubmitAllAfterObserver: Persists consents after order placement
    • Event-driven architecture for consent state changes
  • Dependency Injection: Proper DI configuration
    • Frontend DI configuration for Hyva-specific services
    • Plugin system integration
  • Tailwind CSS Configuration: Custom Tailwind config for GDPR styling
    • GDPR-specific color palette (primary: #006bb4, error: #ef4444)
    • Template scanning configuration for JIT compilation
  • CSP Compliance: Content Security Policy support via Hyva CSP helper
    • Inline script registration for CSP compatibility
    • Proper nonce handling for Alpine.js components

Technical Details

  • Magewire Features:
    • Component state persistence in checkout session (qoliber_gdpr_consents session key)
    • Checksum-safe data structures (simplified IDs to prevent encoding issues)
    • Limited to 5 consents for performance (configurable page size)
    • Event emission for consent updates (gdpr-consents-updated)
    • Payment method integration via event emitting
  • Validation System:
    • Required consent validation in evaluateCompletion method
    • Custom error events with consent details (gdpr-consents:details:error)
    • Success events for completed validation
    • User-friendly error messages with missing consent titles
  • Alpine.js Architecture:
    • Error tracking per consent item via dataset attributes
    • Dynamic error class binding (text-red-600 on error)
    • Modal visibility management with transitions
    • Event-driven error state updates
  • Template Features:
    • Wire model bindings for real-time updates (wire:model="consent.{id}")
    • Conditional rendering based on consent requirements
    • Slide-out modal with backdrop overlay
    • Accessible markup with ARIA attributes
    • Heroicons integration for consistent iconography

Dependencies

  • PHP 8.1, 8.2, or 8.3
  • Magento Framework
  • qoliber/gdpr-consent: 1.0.0-rc1 || ^1.0
  • hyva-themes/magento2-theme-module: ^1.3.11
  • qoliber/hyva-module-registration

Compatibility

  • Magento 2.4.x
  • Hyva Theme 1.3.11+
  • Hyva Checkout (Magewire-based)

GdprCookie

Added

  • Created comprehensive cookie management system for GDPR compliance with cookie categorization
  • Implemented CookieCategory entity with support for essential, marketing, and analytics cookie types
  • Developed CookieDetail entity for individual cookie documentation with provider information
  • Added cookie category translation system supporting multi-language cookie descriptions per store view
  • Created cookie detail translation tables for localized cookie explanations
  • Implemented cookie provider registry with IAB TCF (Transparency and Consent Framework) vendor support
  • Developed detected cookies tracking system for automatic cookie discovery and classification
  • Added cookie scanner detection with first/last detected timestamps and detection count
  • Created regex pattern matching for cookie names supporting wildcard cookie detection (e.g., ga, cto_)
  • Implemented cookie duration tracking with session/persistent/days format
  • Added cookie type classification: HTTP cookies, Local Storage, Session Storage
  • Developed cookie domain and path tracking for cross-domain cookie management
  • Created InstallDefaultCookies data patch with pre-configured essential, marketing, and analytics categories
  • Implemented essential cookies setup including Magento session, form_key, and security cookies
  • Added marketing cookies configuration for advertising and tracking services
  • Developed analytics cookies setup for Google Analytics and user behavior tracking
  • Created InstallGoogleConsentCategory data patch for Google Consent Mode v2 compliance
  • Implemented MigrateGoogleCookiesToNewCategory data patch for cookie recategorization
  • Added cookie category admin interface with create, edit, delete, and mass operations
  • Developed cookie detail admin management with import functionality
  • Created cookie category repository with search capabilities
  • Implemented cookie detail repository with filtering and sorting
  • Added CookieDetailDataProvider for admin UI component forms
  • Developed category options UI component for category selection dropdowns
  • Created cookie category name column renderer for admin grids
  • Implemented cookie detail actions column with edit/delete operations
  • Added cookie category actions column with admin action buttons
  • Developed cookie category options component for filtering
  • Created cookie consent ViewModel for frontend cookie banner integration
  • Implemented admin routing for cookie category and detail management
  • Added ACL resources for cookie management permissions
  • Developed UI component XML for cookie detail listing grid with provider, type, duration, and category columns
  • Created UI component forms for cookie category editing with translation support
  • Implemented cookie detail form with category assignment, provider URL, and technical specifications
  • Added cookie provider management with privacy policy URL tracking
  • Developed IAB vendor integration with vendor ID and purposes JSON storage
  • Created detected cookies table for unclassified cookie tracking with classification workflow
  • Implemented cookie classification linking between detected and categorized cookies
  • Added frontend layout integration for customer privacy center cookie preferences
  • Developed default layout integration for cookie consent banner display
  • Created cookie import functionality for bulk cookie addition from templates
  • Implemented save and continue button for cookie detail editing
  • Added delete button with confirmation for cookie removal
  • Developed back button for admin navigation consistency
  • Created generic button base class for admin form actions
  • Implemented cookie detail save controller with validation
  • Added cookie category save controller with translation support
  • Developed mass delete operation for cookie categories
  • Created mass enable/disable operations for bulk cookie category management
  • Implemented cookie category edit controller with form data loading
  • Added new action controllers for cookie category and detail creation
  • Developed cookie category index controller for listing view
  • Created admin menu items under Privacy & GDPR > Cookie Management section
  • Implemented system configuration support for cookie management settings
  • Added database indexes for efficient cookie lookup by name, provider, and classification status
  • Developed foreign key constraints ensuring referential integrity across cookie tables
  • Created unique constraints for cookie category codes and provider names
  • Implemented timestamp tracking for cookie creation and updates
  • Added sort order support for cookie category display ordering
  • Developed is_active flag for cookie detail enabling/disabling
  • Created is_required flag for essential vs optional cookie categorization
  • Implemented is_enabled flag for cookie category activation
  • Added is_regex flag for pattern-based cookie matching
  • Developed is_classified flag for detected cookie processing status
  • Created is_iab_vendor flag for IAB TCF vendor identification

Technical Details

  • Database tables: qoliber_gdpr_cookie_categories, qoliber_gdpr_cookie_categories_translation, qoliber_gdpr_cookie_details, qoliber_gdpr_cookie_details_translation, qoliber_gdpr_cookie_providers, qoliber_gdpr_detected_cookies
  • Cookie categories support multi-language descriptions via translation table with locale and store ID
  • Cookie details include technical specifications: name, provider, type, duration, domain, description
  • Regex pattern matching enables wildcard cookie detection for dynamic cookie names
  • Detected cookies table tracks unclassified cookies with automatic detection counting
  • IAB TCF vendor support enables Transparency and Consent Framework compliance
  • Cookie providers table maintains centralized provider information with privacy policy URLs
  • Translation tables use unique constraints on (entity_id, store_id, locale) for data integrity
  • Admin UI components use DataProvider pattern for form population
  • Frontend ViewModel pattern for cookie consent banner data exposure
  • Repository pattern for cookie CRUD operations with search criteria support
  • Mass action support for bulk cookie category operations
  • Import functionality enables quick cookie setup from predefined templates

GdprCookieHyva — 2024

Added

  • Initial Hyva theme compatibility module for Qoliber GDPR Cookie
  • Advanced Cookie Consent Modal: Full-featured Alpine.js-powered cookie consent interface
    • Multi-layout support: center popup, left sidebar, right sidebar, bottom banner
    • Responsive design with mobile-first approach and adaptive layouts
    • Three-tab interface: Consent, Details, About
    • Smooth transitions and animations using Tailwind CSS
    • Backdrop blur and overlay effects for center popup mode
  • Category-Based Cookie Management: Granular cookie control system
    • Dynamic category loading from backend configuration
    • Toggle switches for optional cookie categories
    • Always-enabled essential/necessary cookies
    • Visual distinction for required vs optional categories (disabled state styling)
    • Cookie count display per category
  • Detailed Cookie Information Display: Expandable accordion interface
    • Individual cookie details (name, description, provider, duration, type)
    • Collapsible category sections with smooth transitions
    • Provider and technical metadata display
    • Search-friendly cookie documentation
  • Multiple Consent Actions: Flexible consent management
    • Accept All: Enable all cookie categories
    • Deny All: Keep only essential/necessary cookies
    • Allow Selection: Save custom category preferences
    • Cookie Settings: Expand full configuration interface
  • Privacy Policy Integration: Inline privacy policy modal
    • AJAX-loaded privacy policy content via /gdpr/policy/view
    • Loading and error states with visual feedback
    • Modal-within-modal architecture
    • Clickable privacy policy links with custom styling
    • Title and content dynamic loading
  • Google Consent Mode v2 Integration: Advanced Google consent management
    • Default consent state configuration (granted/denied)
    • Dynamic consent updates based on user preferences
    • Category mapping: marketing → ad_storage/ad_personalization, analytics → analytics_storage
    • Always-granted categories: functionality_storage, security_storage
    • URL passthrough support for ad click tracking
    • Ads data redaction when consent denied
    • Wait for update configuration (default 500ms)
    • Debug mode with console logging
    • Consent state persistence in localStorage (qoliber_google_consent)
  • Hyva Cookie System Integration: Seamless Hyva theme compatibility
    • window.cookie_consent_groups integration
    • window.cookie_consent_config mapping
    • Essential/necessary category synchronization (dual mapping for compatibility)
    • Critical Magento cookie protection (PHPSESSID, form_key, etc.)
    • Event-driven cookie consent updates (user-allowed-save-cookie)
    • Custom event emission (qoliber-gdpr-consent-updated)
    • Cookie restriction mode enablement
    • Temporary cookie storage handling
  • Local Storage Persistence: Client-side consent management
    • Consent data structure: accepted, categories, timestamp, version
    • Cookie lifetime configuration (default 365 days)
    • Dual persistence: localStorage + Hyva cookie system
    • Consent restoration on page load
  • Reopener Button: Persistent consent management access
    • Floating action button (bottom-left)
    • Appears after initial consent given
    • Hover effects and scale animations
    • Restores saved selections when reopened
    • Z-index management for proper layering
  • Tab Navigation System: Organized information architecture
    • Active tab highlighting with bottom border
    • Smooth content transitions
    • Default consent tab on open
    • Persistent tab state during modal interactions
  • Theme Configuration: Customizable Hyva theme integration
    • Theme config template for backend-driven styling
    • Display style detection and class management
    • Computed properties for layout adaptation
    • Responsive height constraints per layout
  • Privacy Center Integration: Customer account privacy dashboard
    • Cookie management card in privacy center
    • Reopen settings from privacy dashboard
    • Global event listener for settings reopening (gdpr-reopen-settings)
  • CSP (Content Security Policy) Support: Security-compliant inline scripts
    • Hyva CSP helper integration
    • Proper script registration for CSP nonce support
    • Generated obfuscated function names for CSP compatibility
    • Data attribute-based translations for CSP-safe text injection
  • Checkout Integration: Cookie consent in checkout flow
    • Dedicated checkout layout (hyva_checkout_index_index.xml)
    • Non-blocking consent collection during checkout
  • Tailwind CSS Configuration: Custom Tailwind config for cookie consent
    • Template scanning for JIT compilation
    • Prose styling for policy content
    • Transition utilities configuration

Technical Details

  • Alpine.js Architecture:
    • Main component: gdprCookieConsent() with reactive properties
    • CSP-safe wrapper: qoliberGdprCookieHyvaHyvaCookieConsent() with obfuscated methods
    • Computed properties: displayStyle, categories, texts, googleConsent
    • Layout-specific class getters: getContainerClass(), getContentClass()
  • State Management:
    • isVisible: Modal visibility control
    • showSettings: Expanded settings view toggle
    • showReopener: Floating button visibility
    • activeTab: Current tab selection (consent/details/about)
    • selectedCategories: User-selected cookie categories array
    • expandedCategories: Accordion expansion state object
    • showPrivacyModal: Privacy policy modal visibility
  • Cookie Mapping System:
    • Backend-driven cookie-to-category mapping
    • Pattern-based cookie matching support
    • Magento critical cookie automatic inclusion
    • Essential/necessary dual-category mapping for Hyva compatibility
    • Cookie consent groups initialization from saved data
  • Event System:
    • qoliber-gdpr-consent-updated: Fired on consent changes with category details
    • user-allowed-save-cookie: Hyva integration event
    • gdpr-reopen-settings: External reopen trigger
    • qoliberGoogleConsentUpdated: Google consent update notification (debug mode)
  • Google Consent Configuration:
    • ad_storage: Marketing consent mapping
    • ad_user_data: Marketing consent mapping
    • ad_personalization: Marketing consent mapping
    • analytics_storage: Analytics consent mapping
    • functionality_storage: Always granted
    • personalization_storage: Marketing consent mapping
    • security_storage: Always granted
  • Layout Variations:
    • Center: Full-screen overlay with centered modal (max-w-4xl)
    • Bottom: Banner at bottom with horizontal layout option
    • Left: Sidebar from left edge (max-w-md)
    • Right: Sidebar from right edge (max-w-md)
  • Responsive Behavior:
    • Mobile-first design with md: breakpoint adaptations
    • Flexible header layout in bottom mode
    • Adaptive height constraints per display style
    • Touch-friendly toggle switches and buttons

Dependencies

  • Magento Framework
  • hyva-themes/magento2-theme-module: ^1.3
  • qoliber/gdpr-cookie
  • qoliber/hyva-module-registration

Compatibility

  • Magento 2.4.x
  • Hyva Theme 1.3+
  • Google Tag Manager (optional, for Consent Mode v2)
  • Alpine.js 3.x (included in Hyva)
  • Tailwind CSS 3.x (Hyva default)

GdprCookieTemplates

Added

  • Created pre-configured cookie template library for common third-party services
  • Implemented CookieTemplateService providing standardized cookie definitions for popular platforms
  • Added Google Analytics cookie templates including _ga, _gid, _gat, and ga* pattern cookies with accurate durations
  • Developed Facebook Pixel cookie templates for _fbp, _fbc, and fr cookies with Meta privacy policy links
  • Created Criteo advertising cookie templates with cto_* pattern and criteo cookies
  • Implemented PayPal payment cookie templates including paypal, PYPF, and ts security cookies
  • Added Hotjar analytics cookie templates for _hjid, hjSessionUser*, and _hjIncludedInSessionSample
  • Developed Mailchimp email marketing cookie templates for landing site and user email tracking
  • Created Klaviyo marketing automation cookie templates including __kla_id and klaviyo cookies
  • Implemented Trustpilot review widget cookie templates with trustpilot and tp_* patterns
  • Added Yotpo reviews and loyalty cookie templates with yotpo_* pattern and yotpo_site_uid
  • Developed Bing Ads conversion tracking cookie templates for _uetmsclkid and uetmsclkid* patterns
  • Created template structure with cookie name, description, type (HTTP/Local Storage/Session), duration, provider, and privacy URL
  • Implemented regex pattern support in templates for wildcard cookie matching (ga, cto_, tp_, yotpo_, etc.)
  • Added getTemplate() method for retrieving individual service templates by key
  • Developed getTemplateNames() method returning dropdown-formatted template list for admin UI
  • Created comprehensive provider privacy policy URL mappings for GDPR transparency requirements
  • Implemented accurate cookie duration specifications (session, minutes, hours, days, months, years)
  • Added cookie type classification (HTTP, Local Storage, Session Storage) for each template entry
  • Developed template keys: google_analytics, facebook_pixel, criteo, paypal, hotjar, mailchimp, klaviyo, trustpilot, yotpo, bing_ads
  • Created detailed cookie descriptions explaining purpose and data collection for user transparency
  • Implemented admin template index controller for template browsing interface
  • Added admin routing configuration for cookie template management
  • Developed integration with Qoliber_GdprAdmin for centralized GDPR administration
Google Analytics (4 cookies)
  • _ga: 2-year user identification cookie
  • _gid: 24-hour user distinction cookie
  • _gat: 1-minute rate throttling cookie
  • ga* (regex): 2-year session state persistence
Facebook Pixel (3 cookies)
  • _fbp: 3-month advertisement delivery cookie
  • _fbc: 2-year conversion tracking cookie
  • fr: 3-month advertisement products cookie
Criteo (2 cookies)
  • cto_* (regex): 13-month advertising and retargeting
  • criteo: 13-month retargeting cookie
PayPal (3 cookies)
  • paypal: Session payment processing cookie
  • PYPF: 2-year fraud prevention cookie
  • ts: 3-year security and fraud prevention
Hotjar (3 cookies)
  • _hjid: 1-year user identification cookie
  • hjSessionUser* (regex): 1-year session tracking
  • _hjIncludedInSessionSample: 2-minute session sampling
Mailchimp (2 cookies)
  • mailchimp_landing_site: 1-month landing page tracking
  • mailchimp_user_email: 1-year user identification
Klaviyo (2 cookies)
  • __kla_id: 2-year email marketing identification
  • klaviyo: 2-year behavior tracking cookie
Trustpilot (2 cookies)
  • trustpilot: 1-year review widget tracking
  • tp_* (regex): 1-year functionality tracking
Yotpo (2 cookies)
  • yotpo_* (regex): 1-year reviews and loyalty
  • yotpo_site_uid: 1-year user identification
Bing Ads (2 cookies)
  • _uetmsclkid: 1-year conversion tracking
  • uetmsclkid* (regex): 1-year tracking and analytics

Technical Details

  • CookieTemplateService returns structured arrays with name, description, type, duration, provider, provider_url, and is_regex flag
  • Templates designed for one-click import into GdprCookie module
  • Privacy policy URLs reference official provider documentation
  • Regex patterns enable flexible cookie name matching for dynamic cookies
  • Template structure compatible with CookieDetail entity model
  • Service methods support both bulk template retrieval and individual template access
  • Dropdown formatting for seamless admin UI integration

GdprDataSubject

Added

  • Created comprehensive data subject rights management system implementing GDPR Articles 15-21
  • Implemented DataRequest entity supporting fetch_data, anonymize, delete, rectification, objection, and restriction request types
  • Developed unified GDPR requests database schema tracking customer ID, email, request type, status, source, and audit trail
  • Added request status workflow: pending, processing, confirmed, completed, rejected, failed, expired, partially_completed
  • Created request source tracking: customer, guest, admin for accountability
  • Implemented token-based verification system for guest data access and email confirmation
  • Developed request blocking mechanism with admin controls for reason, timestamp, and blocking user
  • Added DataAnonymizationService orchestrating anonymization across multiple data anonymizers
  • Created modular anonymizer architecture with interfaces: CustomerDataAnonymizer, OrderDataAnonymizer, QuoteDataAnonymizer, InvoiceDataAnonymizer, ShipmentDataAnonymizer, CreditMemoDataAnonymizer, NewsletterDataAnonymizer, DataRequestAnonymizer
  • Implemented AbstractDataAnonymizer base class with faker integration for realistic fake data generation
  • Developed CustomerDataAnonymizer replacing customer names, emails, phone numbers, addresses with anonymized values
  • Created OrderDataAnonymizer for sales order data anonymization with configurable order status filtering
  • Implemented QuoteDataAnonymizer for cart and quote data erasure
  • Added InvoiceDataAnonymizer for invoice billing/shipping address anonymization
  • Developed ShipmentDataAnonymizer for shipment address data replacement
  • Created CreditMemoDataAnonymizer for credit memo address anonymization
  • Implemented NewsletterDataAnonymizer for newsletter subscription data removal
  • Added DataRequestAnonymizer for GDPR request history anonymization
  • Developed data fetcher system with interfaces for extracting customer data across entities
  • Created CustomerDataFetcher extracting customer profile, addresses, and account information
  • Implemented OrderDataFetcher gathering order history with items, addresses, and payment data
  • Added QuoteDataFetcher for active cart data retrieval
  • Developed InvoiceDataFetcher for invoice records extraction
  • Created ShipmentDataFetcher for shipment history compilation
  • Implemented CreditMemoDataFetcher for credit memo data export
  • Added NewsletterDataFetcher for subscription status extraction
  • Developed CustomerAddressDataFetcher for address book data collection
  • Created DataFetcherService orchestrating all fetchers for complete customer data export
  • Implemented DataConversionService supporting CSV, JSON, and TXT export formats
  • Developed CsvConverter generating CSV files from customer data arrays
  • Created JsonConverter producing formatted JSON exports
  • Implemented TxtConverter generating human-readable text file exports
  • Added DynamicExportFormat source model with pluggable converter architecture
  • Developed cron job ProcessAnonymizationRequests executing every 15 minutes with batch processing (250 requests per run)
  • Created cron job ProcessDeletionRequests for automated customer account deletion
  • Implemented cron job ProcessDataFetchRequests for data export generation
  • Added cron job ProcessDataAccessNotifications for email notification delivery
  • Developed cron job CleanupExpiredRequests removing expired tokens daily at 2 AM
  • Created ProcessEmailQueue cron job for asynchronous email delivery with retry logic
  • Implemented email queue system with pending, processing, sent, failed statuses and retry counting
  • Added DataRequestRepository with search capabilities and status filtering
  • Developed request notes system with internal, customer, system, and compliance note types
  • Created admin request view interface with details, history, and notes tabs
  • Implemented admin request management with approve, deny, block, unblock, mark reviewed actions
  • Added customer privacy center interface for data access, rectification, deletion, and objection requests
  • Developed guest request submission system with email verification
  • Created view data controller for guest access to exported data via secure token
  • Implemented data request verification with token validation and expiration checking
  • Added customer account privacy page with request history and status tracking
  • Developed customer deletion confirmation workflow with email verification
  • Created anonymization request submission with preservation options
  • Implemented rectification request interface for data correction
  • Added objection and restriction request types for marketing and processing objections
  • Developed admin view for request details with comprehensive request information display
  • Created request history tracking with created_at, updated_at, completed_at, verified_at, reviewed_at, accessed_at timestamps
  • Implemented IP address and user agent logging for request audit trail
  • Added store ID tracking for multi-store request management
  • Developed admin user tracking for admin-initiated actions
  • Created request data and response data JSON fields for flexible metadata storage
  • Implemented expires_at timestamp for automatic request expiration
  • Added email_sent_at tracking for notification delivery confirmation
  • Developed blocked_at, blocked_by, blocked_reason fields for request blocking workflow
  • Created reviewed_at, reviewed_by fields for admin review tracking
  • Implemented FakerInterface for generating realistic anonymized data
  • Added partial email anonymization (j***@example.com format) for privacy
  • Developed DataSubjectConfigInterface for configuration management
  • Created Config source models for OrderStatus, ExportFormat, DynamicExportFormat
  • Implemented RequestType, RequestSource, RequestStatus source models for admin UI
  • Added email templates for verification, confirmation, completion, and notifications
  • Developed ViewData block for guest data access interface
  • Created GuestForm block for guest request submission
  • Implemented admin View block with request details, notes, and history
  • Added Notes block for admin request note management
  • Developed Details block displaying comprehensive request information
  • Created History block showing request lifecycle events
  • Implemented frontend controllers for guest data request, verification, and access
  • Added export download controller with secure token validation
  • Developed customer privacy controller integrating all data subject rights
  • Created customer deletion, anonymization, rectification, objection, restriction controllers
  • Implemented admin controllers for request view, approve, deny, block, unblock, add notes, mark reviewed
  • Added anonymization status tracking with confirm endpoint
  • Developed anonymization request creation linking to original fetch_data request
  • Created frontend routes for gdpr/request, gdpr/guest, gdpr/export, gdpr/account/privacy
  • Implemented admin routes for request management under qoliber_gdpr namespace
  • Added ACL resources for data subject request management permissions
  • Developed admin menu items under Privacy & GDPR > Data Subject Requests
  • Created system configuration section for data subject settings
  • Implemented configurable allowed order statuses for anonymization (complete, closed, canceled)
  • Added configurable request expiration periods
  • Developed configurable export format selection
  • Created email queue with scheduled_at, sent_at timestamps and error tracking
  • Implemented retry mechanism with retry_count and error_message logging
  • Added foreign key from email queue to requests table with cascade delete
  • Developed indexes for efficient request lookup by customer_id, email, type, status, token, dates
  • Created indexes for email queue status and scheduled_at for cron optimization
  • Implemented request notes indexes by request_id, note_type, created_at
  • Added ramsey/uuid dependency for secure token generation
  • Developed comprehensive logging throughout anonymization and data fetching processes
  • Created area emulation for admin context execution in cron jobs
  • Implemented preserveEmail option allowing email retention during anonymization
  • Added original_request_id linking for anonymization request tracking
  • Developed anonymization_status updates on original fetch_data requests
  • Created website store ID aggregation for multi-store data processing
  • Implemented batch processing limits preventing timeout on large datasets
  • Added error handling with partial completion support
  • Developed anonymization result tracking with total_anonymized count
  • Created success/failure status reporting with detailed error arrays

GDPR Rights Implemented

Right to Access (Article 15)
  • Complete customer data export in CSV, JSON, or TXT format
  • Fetchers extract data from customers, orders, quotes, invoices, shipments, credit memos, newsletters, addresses
  • Secure token-based guest access to exported data
  • Email notification with download link
  • Configurable data retention and expiration
Right to Rectification (Article 16)
  • Customer-initiated data correction requests
  • Admin review and approval workflow
  • Request tracking with status updates
Right to Erasure / Right to be Forgotten (Article 17)
  • Automated customer account deletion with data removal
  • Configurable order status filtering (only delete when orders complete/closed/canceled)
  • Multi-store data removal across website stores
  • Admin approval workflow for deletion requests
  • Preservation options for legal/financial record retention
Right to Data Portability (Article 20)
  • Machine-readable data export (JSON, CSV)
  • Structured data format for transfer to other services
  • Complete data extraction across all customer touchpoints
Right to Object (Article 21)
  • Marketing objection request type
  • Processing objection tracking
  • Customer-initiated objection submission
Right to Restriction of Processing (Article 21)
  • Processing restriction request type
  • Temporary data processing suspension tracking

Data Anonymization Features

  • Multi-entity anonymization: customers, orders, quotes, invoices, shipments, credit memos, newsletters, GDPR requests
  • Faker-generated realistic replacement data maintaining data format integrity
  • Configurable anonymization scope with entity-specific anonymizers
  • Order status filtering preventing premature order data anonymization
  • Email preservation option for legal compliance scenarios
  • Comprehensive anonymization logging with success/failure tracking
  • Partial completion support for error resilience
  • Website-wide store aggregation ensuring complete multi-store anonymization

Cron Job Schedule

  • ProcessDataAccessNotifications: Every 15 minutes
  • ProcessAnonymizationRequests: Every 15 minutes (250 batch limit)
  • ProcessDeletionRequests: Every 15 minutes
  • CleanupExpiredRequests: Daily at 2:00 AM
  • Email queue processing with retry logic

Technical Details

  • Database tables: qoliber_gdpr_requests, qoliber_gdpr_request_notes, qoliber_gdpr_email_queue
  • Request token generation using ramsey/uuid for cryptographic security
  • Email queue system with status tracking, retry counting, and error logging
  • Modular anonymizer architecture via dependency injection
  • DataFetcherService aggregates all fetchers via DI array
  • DataConversionService supports pluggable format converters
  • Cron jobs use area emulation for proper admin context
  • Foreign key constraints ensure referential integrity
  • Comprehensive indexes optimize query performance for high-volume request handling
  • Request lifecycle tracking with multiple timestamp fields for complete audit trail
  • Multi-store support via store ID tracking and website store aggregation
  • Guest verification via secure token with expiration
  • Admin blocking mechanism for fraud prevention
  • Request notes system for compliance documentation
  • Configurable export formats via system configuration
  • Batch processing prevents timeout on large anonymization operations

GdprDataSubjectHyva — 2024

Added

  • Initial Hyva theme compatibility module for Qoliber GDPR Data Subject Rights
  • Privacy Dashboard Templates: Comprehensive Hyva-styled privacy center
    • Hero section with gradient backgrounds and modern card design
    • GDPR rights overview with icon-based navigation
    • Data types information display
    • DPO (Data Protection Officer) contact information
    • Quick actions section with action cards
  • Quick Actions Cards: Modern card-based UI for GDPR rights
    • Export Your Data: Purple gradient card with download icon
    • Rectify Your Data: Cyan gradient card with edit icon
    • Anonymize Your Data: Pink gradient card with lock icon (conditionally displayed)
    • Delete Your Account: Red gradient card with trash icon (conditionally displayed)
    • Hover effects: shadow elevation, border highlighting, vertical translation
    • Smooth scroll navigation to export form via Alpine.js click handler
    • Responsive grid layout (1 column mobile, 2 tablet, 3 desktop)
  • Data Export Interface: Hyva-styled data export functionality
    • Guest data export form with modern styling
    • Format selection interface
    • Export form template integration
  • Guest User Templates: Dedicated templates for non-authenticated users
    • Guest data request form (hyva/datasubject/guest/data-request.phtml)
    • View data interface (hyva/datasubject/guest/view-data.phtml)
    • Anonymization confirmation (hyva/datasubject/guest/anonymization-confirm.phtml)
  • Customer Account Templates: Authenticated user data subject rights
    • Account deletion request form (hyva/datasubject/customer/delete.phtml)
    • Anonymization request form (hyva/datasubject/customer/anonymize.phtml)
    • Rectification request form (hyva/datasubject/customer/rectification.phtml)
  • Anonymization Workflow: Multi-step anonymization process
    • Status tracking interface (hyva/anonymization/status.phtml)
    • Confirmation step template
    • Status-based UI updates
  • Privacy Center Integration: Seamless integration with GDPR Privacy Center
    • Privacy dashboard template (hyva/datasubject/privacy-dashboard.phtml)
    • Rights overview cards
    • Data types information display
    • DPO contact integration
    • Quick actions grid with conditional rendering
  • Privacy Account Cards: Modular privacy action cards
    • Delete card (customer/privacy/cards/delete.phtml)
    • Export card (customer/privacy/cards/export.phtml)
    • Rectify card (customer/privacy/cards/rectify.phtml)
    • Anonymize card (customer/privacy/cards/anonymize.phtml)
  • Layout Integration: Comprehensive Hyva layout support
    • hyva_gdprds_guest_viewdata.xml: Guest data view layout
    • hyva_gdprds_customer_delete.xml: Customer deletion layout
    • hyva_customer_account_privacy.xml: Privacy center layout
    • hyva_gdprds_guest_datarequest.xml: Guest data request layout
    • hyva_gdprds_customer_anonymize.xml: Anonymization request layout
    • hyva_gdprds_anonymization_status.xml: Anonymization status layout
    • hyva_gdprds_anonymization_confirm.xml: Confirmation layout
    • hyva_gdprds_customer_rectification.xml: Rectification layout
  • Conditional Feature Display: Backend configuration-driven UI
    • Anonymization card shown only if enabled via $configViewModel->isAnonymizationEnabled()
    • Deletion card shown only if enabled via $configViewModel->isDeletionEnabled()
    • Dynamic grid adaptation based on enabled features
  • ViewModel Integration: Proper data layer separation
    • Privacy ViewModel integration (Qoliber\GdprDataSubject\ViewModel\Privacy)
    • Config ViewModel integration (Qoliber\GdprDataSubject\ViewModel\Config)
    • Template-level data access via view models
  • Tailwind CSS Styling: Modern, responsive design system
    • Gradient backgrounds (purple-to-indigo, cyan-to-blue, pink-to-rose, red-to-orange)
    • Shadow utilities (shadow-lg, shadow-xl, shadow-2xl)
    • Transition effects (duration-300, ease-in-out)
    • Hover states with transform utilities
    • Border utilities with hover effects
    • Responsive spacing and typography
  • Icon System: SVG-based iconography
    • Download icon for data export
    • Edit/pencil icon for rectification
    • Lock icon for anonymization
    • Trash icon for deletion
    • Arrow icons for navigation
    • Consistent sizing (w-8 h-8 for card icons, w-4 h-4 for inline)
  • Smooth Scroll Navigation: Enhanced UX for in-page navigation
    • Alpine.js @click.prevent handlers
    • ScrollIntoView with smooth behavior
    • Anchor-based navigation with scroll offset
  • Tailwind Configuration: Custom Tailwind config for data subject features
    • Template scanning configuration
    • JIT compilation support

Technical Details

  • Card Component Architecture:
    • Base card: bg-white rounded-xl p-8 shadow-lg hover:shadow-xl
    • Hover transformation: hover:-translate-y-1
    • Border animation: border-2 border-transparent hover:border-{color}-500
    • Icon container: w-14 h-14 bg-gradient-to-br rounded-xl flex items-center justify-center
  • Gradient Color Palette:
    • Export: from-purple-500 to-indigo-600
    • Rectify: from-cyan-500 to-blue-600
    • Anonymize: from-pink-500 to-rose-600
    • Delete: from-red-500 to-orange-600
  • Responsive Grid System:
    • Mobile: grid-cols-1 (single column)
    • Tablet: md:grid-cols-2 (two columns)
    • Desktop: lg:grid-cols-3 (three columns)
    • Gap: gap-6 (1.5rem spacing)
  • Typography Hierarchy:
    • Section headings: text-2xl font-bold text-gray-800
    • Card titles: text-xl font-semibold text-gray-800
    • Card descriptions: text-gray-600
    • Links: font-semibold with color-specific classes
  • Alpine.js Integration:
    • Smooth scroll handler: @click.prevent="document.getElementById('export-form').scrollIntoView({ behavior: 'smooth', block: 'start' })"
    • Event-driven navigation
    • Progressive enhancement approach
  • Conditional Rendering Logic:
    • PHP-based: <?php if ($configViewModel && $configViewModel->isAnonymizationEnabled()): ?>
    • Backend-driven feature flags
    • Clean template architecture
  • Action URLs:
    • Rectification: /gdprds/customer/rectification
    • Anonymization: /gdprds/customer/anonymize
    • Deletion: /gdprds/customer/delete
    • Export: In-page anchor #export-form

Dependencies

  • Magento Framework
  • hyva-themes/magento2-theme-module
  • qoliber/gdpr-data-subject
  • qoliber/hyva-module-registration

Compatibility

  • Magento 2.4.x
  • Hyva Theme 1.3+
  • Alpine.js 3.x (included in Hyva)
  • Tailwind CSS 3.x (Hyva default)

User Experience Enhancements

  • Visual Hierarchy: Clear distinction between action types via color-coded gradients
  • Interactive Feedback: Hover states provide immediate visual feedback
  • Accessibility: Semantic HTML with proper heading structure
  • Mobile Optimization: Touch-friendly card sizes and responsive layouts
  • Progressive Disclosure: Smooth scroll to detailed forms from quick actions
  • Information Architecture: Logical grouping of related privacy functions

GdprFrontend — 2024

Added

  • Cookie Consent UI Framework: Comprehensive frontend cookie consent banner implementation with customizable display styles (popup, banner, overlay) and visual themes
  • Google Consent Mode v2 Integration: Full support for Google Consent Mode v2 API with configurable consent states (granted/denied) for analytics_storage, ad_storage, ad_user_data, and ad_personalization
  • Tag Type System: Extensible tag type architecture via TagTypeInterface allowing multiple tracking implementations:
    • GoogleTag implementation for native Google Analytics 4 (GA4) with G-XXXXXXXXXX ID format validation
    • TagTypePool for managing multiple tag type providers
  • Plugin System: DisableNativeGoogleGtagPlugin to prevent conflicts by disabling Magento's native Magento_GoogleGtag module when Google Consent Mode is enabled
  • Advanced Consent Configuration:
    • Default consent state configuration (granted/denied)
    • URL passthrough for ad click information when cookies are denied
    • Ads data redaction when ad_storage is denied
    • Configurable wait time for consent updates (0-10000ms)
    • Debug mode for console logging of consent events
  • Consent Popup Customization:
    • Multiple display styles: popup, banner, overlay
    • Theme selection for visual appearance
    • Configurable to show on first visit
    • Cookie settings reopener options (icon, link, both)
    • Customizable icon position (bottom-left, bottom-right, top-left, top-right)
  • Comprehensive Content Management:
    • WYSIWYG editor support for consent message and policy content
    • Configurable consent title and message
    • "About Cookie Policy" section with custom title and HTML content
    • "What Are Cookies" educational section
    • "How We Use Cookies" explanation section
  • Translation Support: Translation helper for multi-language cookie consent interfaces
  • ViewModel Architecture: CookieConsent ViewModel extending base GdprCookie functionality for frontend-specific implementations
  • Template System:
    • google-consent-head.phtml for injecting Google Consent Mode v2 script in document head
    • consent/google-tag.phtml for Google Tag (GA4) implementation
  • Hyva Theme Compatibility: Built-in support for Hyva themes (requires hyva-themes/magento2-theme-module ^1.3.11)
  • Admin Configuration: Comprehensive system.xml with organized sections:
    • Cookie Consent Settings (qoliber_gdpr_cookie/consent)
    • Cookie Content Settings (qoliber_gdpr_cookie/texts)
    • Google Consent Mode v2 (qoliber_gdpr_cookie/google_consent)

Dependencies

  • Requires Qoliber_GdprConsent module for core consent management functionality
  • Requires Qoliber_GdprDataSubject module for data subject rights handling
  • Requires Magento_GoogleGtag module (can be disabled via configuration)
  • PHP 8.1, 8.2, or 8.3 compatibility

Technical Implementation

  • Frontend layout integration via default.xml and default_head_blocks.xml
  • ACL resources for admin configuration access under Qoliber_GdprFrontend::config
  • Tag ID validation with regex patterns (G-[A-Z0-9]{10} for Google Tag)
  • Strict typing and modern PHP 8.1+ features throughout codebase

GdprFrontendHyva — 2024

Added

  • Initial Hyva theme compatibility module for Qoliber GDPR Frontend
  • Google Consent Mode v2 Implementation: Advanced Google Tag Manager integration
    • Pre-initialization consent defaults before GTM script loads
    • Default consent state configuration (granted/denied per category)
    • Wait for update mechanism (configurable delay, default 500ms)
    • Post-load consent restoration from localStorage
    • Dynamic consent updates via gtag API
  • Google Tag Manager Integration: Proper GTM initialization sequence
    • Async GTM script loading after consent defaults set
    • gtag.js initialization with proper timing
    • dataLayer initialization and gtag function declaration
    • GTM tag configuration with merchant-specific Tag ID
  • Consent State Management: Comprehensive consent tracking
    • Default consent state for 7 consent types:
      • ad_user_data: User data for advertising
      • ad_personalization: Personalized advertising
      • ad_storage: Advertising cookies
      • analytics_storage: Analytics cookies
      • functionality_storage: Always granted for necessary functionality
      • personalization_storage: Personalization cookies
      • security_storage: Always granted for security
    • localStorage persistence (qoliber_google_consent)
    • Automatic consent restoration on page load
    • JSON-encoded consent state with proper escaping
  • URL Passthrough Support: Ad click tracking preservation
    • Optional URL passthrough for ad click information
    • gtag 'url_passthrough' configuration
    • Backend-controlled enablement
  • Ads Data Redaction: Privacy-enhanced advertising
    • Optional ads data redaction when consent denied
    • gtag 'ads_data_redaction' configuration
    • PII protection for denied consent states
  • Debug Mode: Development and troubleshooting support
    • Console logging of consent state changes
    • Consent restoration logging
    • Custom event logging (qoliberGoogleConsentUpdated)
    • Conditional debug output based on backend configuration
  • CSP (Content Security Policy) Support: Security-compliant script injection
    • Hyva CSP helper integration ($hyvaCsp->registerInlineScript())
    • Proper inline script registration for CSP nonce support
    • Separated script blocks for CSP compliance
  • ViewModel Integration: Clean data layer architecture
    • CookieConsent ViewModel integration
    • Configuration array access via getCookieConsentConfigArray()
    • Google Consent config extraction from main config
    • Conditional rendering based on feature enablement
  • Configuration-Driven Behavior: Backend-controlled features
    • Enable/disable toggle via $googleConsent['enabled']
    • GTM Tag ID validation (must not be empty)
    • Default state configuration (granted/denied)
    • Wait for update timing configuration
    • URL passthrough toggle
    • Ads data redaction toggle
    • Debug mode toggle
  • Google Consent Head Template: Proper head section integration
    • google-consent-head.phtml: Head section consent initialization
    • Placement before GTM script load
    • Critical consent defaults set early in page lifecycle
  • Layout Integration: Hyva theme layout support
    • hyva_default.xml: Global Hyva theme integration
    • Head section script injection
    • Before body end script placement
  • Consent Tag Template: Google Tag implementation
    • consent/google-tag.phtml: Main GTM integration template
    • Conditional rendering based on feature flags
    • Proper script ordering and timing
    • Event listener for consent updates
  • JSON Encoding Security: XSS prevention
    • JSON_HEX_TAG flag for script tag escaping
    • JSON_HEX_APOS flag for apostrophe escaping
    • JSON_HEX_QUOT flag for quote escaping
    • JSON_HEX_AMP flag for ampersand escaping
    • Proper JSON encoding in script contexts
  • Event-Driven Architecture: Custom event system
    • qoliberGoogleConsentUpdated custom event
    • Event detail with consent state payload
    • Window-level event dispatching
    • Event listener registration in debug mode
  • Immediate Consent Check: Fast consent restoration
    • IIFE (Immediately Invoked Function Expression) for consent restoration
    • Try-catch for localStorage access failures
    • Silent failure handling for localStorage unavailable
    • JSON parsing with error handling
  • Tailwind Configuration: Hyva theme styling support
    • Custom Tailwind config for frontend templates
    • Template scanning configuration
    • JIT compilation support

Technical Details

  • GTM Initialization Sequence:
    1. Initialize dataLayer array
    2. Declare gtag function
    3. Set default consent state
    4. Configure URL passthrough (if enabled)
    5. Configure ads data redaction (if enabled)
    6. Load GTM script asynchronously
    7. Configure GTM with Tag ID
    8. Restore saved consent from localStorage
  • Consent Restoration Logic:
    javascript
    (function() {
        try {
            var storedConsent = localStorage.getItem('qoliber_google_consent');
            if (storedConsent) {
                var consent = JSON.parse(storedConsent);
                gtag('consent', 'update', consent);
            }
        } catch (e) {
            // Silent failure
        }
    })();
  • Default Consent Configuration:
    • All consent types default to backend-configured state (granted/denied)
    • Functionality and security storage always granted
    • Wait for update prevents premature tag firing
  • Debug Logging:
    • Restoration log: [Qoliber GDPR] Restored consent from storage: {consent}
    • Update log: [Qoliber GDPR] Google Consent Updated: {detail}
    • Conditional output based on debugMode configuration
  • Configuration Array Structure:
    PHP
    $googleConsent = [
        'enabled' => bool,
        'gtagId' => string,
        'defaultState' => 'granted'|'denied',
        'waitForUpdate' => int (milliseconds),
        'urlPassthrough' => bool,
        'adsDataRedaction' => bool,
        'debugMode' => bool
    ]
  • GTM Script Loading:
    • Async attribute for non-blocking load
    • Source: https://www.googletagmanager.com/gtag/js?id={TAG_ID}
    • Loaded after consent defaults set
  • CSP Script Blocks:
    • Three separate script blocks for proper CSP handling
    • Each block registered with Hyva CSP helper
    • Nonce support for inline scripts

Dependencies

  • PHP 8.1, 8.2, or 8.3
  • Magento Framework
  • Magento Theme module
  • Magento CMS module
  • hyva-themes/magento2-theme-module: ^1.3.11
  • qoliber/gdpr-frontend: ^1.0
  • qoliber/hyva-module-registration

Compatibility

  • Magento 2.4.x
  • Hyva Theme 1.3.11+
  • Google Tag Manager
  • Google Consent Mode v2 API
  • Modern browsers with localStorage support

Integration Points

  • Works with GdprCookieHyva for consent updates
  • Listens for consent change events from cookie module
  • Updates Google Consent Mode dynamically based on user preferences
  • Integrates with Hyva CSP system for security compliance

Performance Considerations

  • Async GTM script loading prevents blocking
  • Minimal JavaScript footprint
  • localStorage caching reduces consent API calls
  • Wait for update mechanism prevents premature tag firing
  • Efficient IIFE for consent restoration

GdprGtm

Added

  • Initial release candidate with Google Tag Manager GDPR integration

GdprPolicy — 2024

Added

  • Privacy Policy Management System: Comprehensive privacy policy creation, versioning, and publishing system with full CRUD operations
  • Policy Versioning: Advanced version control for privacy policies with semantic versioning support
    • Track policy versions (e.g., 1.0.0, 1.1.0, 2.0.0)
    • Effective date tracking for each policy version
    • Archive historical policy versions
    • Automatic version management on policy updates
  • Policy Status Management: Four-state workflow system:
    • Draft (0): Policies in development
    • Active (1): Currently in effect but not requiring new consent
    • Archived (2): Historical policies for record-keeping
    • Published (3): Active policies requiring user consent
  • Consent Tracking System: Complete audit trail of policy consent:
    • PolicyConsent model with comprehensive consent metadata
    • Customer ID and email tracking (registered users)
    • Guest email tracking (anonymous visitors)
    • IP address recording for legal compliance
    • Country code from geolocation
    • User agent string for device tracking
    • Session ID for consent attribution
    • Context field for consent scenario tracking
    • Consent method tracking (popup, checkbox, modal, etc.)
    • Store ID for multi-store consent management
    • Acceptance/rejection flag with timestamps
    • Consent timestamp (consented_at)
    • Withdrawal timestamp (withdrawn_at) for consent revocation
    • Additional data JSON field for extensibility
  • Database Schema: Robust database structure with three main tables:
    • qoliber_gdpr_privacy_policy: Privacy policy storage
    • qoliber_gdpr_policy_version: Version history tracking
    • qoliber_gdpr_policy_consent: Consent logs
  • Admin Interface:
    • Privacy policy grid listing (Controller/Adminhtml/PrivacyPolicy/Index.php)
    • Policy creation form (Controller/Adminhtml/PrivacyPolicy/NewAction.php)
    • Policy editing interface (Controller/Adminhtml/PrivacyPolicy/Edit.php)
    • Policy save action with validation (Controller/Adminhtml/PrivacyPolicy/Save.php)
    • Policy deletion (Controller/Adminhtml/PrivacyPolicy/Delete.php)
    • Policy publishing workflow (Controller/Adminhtml/PrivacyPolicy/Publish.php)
    • Consent log viewer (Controller/Adminhtml/Consent/Index.php)
    • UI components with action column (Ui/Component/Listing/Column/PrivacyPolicyActions.php)
    • Status label rendering (Ui/Component/Listing/Column/StatusLabel.php)
    • Generic button architecture for form actions
  • Frontend Controllers:
    • Policy acceptance endpoint (Controller/Policy/Accept.php) - AJAX-based consent recording
    • Policy rendering endpoint (Controller/Policy/Render.php) - Dynamic policy display
    • Consent logging endpoint (Controller/Consent/Log.php) - Privacy-first consent tracking
  • Rendering System:
    • CmsPageRenderer: Render policies from CMS pages
    • VersionBasedRenderer: Render version-specific policy content
    • PrivacyPolicyRenderer API interface for extensible rendering
  • Configuration System:
    • Policy source selection (CMS page vs. version-based)
    • Display mode options (modal, inline, popup)
    • Display location configuration (checkout, registration, newsletter)
    • Link style customization
    • Opening mode (new tab, same window, modal)
    • Policy status configuration
  • Cookie Integration:
    • Cookie helper for privacy policy acceptance tracking
    • AddPrivacyPolicyCookie data patch - Registers privacy policy cookie
    • AddPolicyVersionCookie data patch - Tracks accepted policy version
    • Cookie-based consent state management
    • Integration with Magento's cookie restriction system
  • Default Content: InstallDefaultPrivacyPolicy data patch providing:
    • Comprehensive 9-section privacy policy template
    • GDPR-compliant policy content covering:
      1. Information We Collect (Personal and Non-Personal)
      2. How We Use Your Information
      3. How We Share Your Information
      4. Your Choices and Rights
      5. Security measures
      6. Children's Privacy
      7. International Transfers
      8. Third-Party Websites
      9. Changes to Privacy Policy
    • HTML-formatted content with proper structure
    • Automatic installation only if no published policy exists
    • Version 1.0.0 baseline
    • Default consent text: "I have read and agree to the Privacy Policy"
  • Repository Pattern: Full repository implementation with SearchResults
    • PrivacyPolicyRepository: CRUD operations with search criteria support
    • PrivacyPolicySearchResults: Collection results with pagination
    • PolicyConsentRepository: Consent log management
    • Clean API layer separation from models
  • ViewModel Architecture:
    • PrivacyPolicy ViewModel for frontend policy display
    • Configuration access methods
    • Policy version retrieval
    • Enable/disable state management
  • Plugin System:
    • CookieConsentPlugin: Integrates privacy policy with cookie consent
    • LinkTargetPlugin: Controls policy link opening behavior
  • Multi-Store Support:
    • Store-specific privacy policies
    • Language code tracking for localization
    • Store ID in consent records for multi-tenant compliance
  • ACL Resources: Admin permission system for policy management
  • System Configuration: Modal notice for admin guidance

Technical Implementation

  • API Contracts: Comprehensive interface definitions:
    • PrivacyPolicyInterface: Policy entity contract
    • PrivacyPolicyRepositoryInterface: Repository contract
    • PrivacyPolicySearchResultsInterface: Search results contract
    • PolicyConsentInterface: Consent entity contract
    • PolicyConsentSearchResultsInterface: Consent search results
    • ConfigInterface: Configuration contract
    • PrivacyPolicyRendererInterface: Renderer contract
  • Resource Models: Optimized database operations
    • ResourceModel/PrivacyPolicy with collection support
    • ResourceModel/PolicyVersion with collection support
    • ResourceModel/PolicyConsent with collection support
  • Data Providers: Admin form data population
    • PrivacyPolicy/DataProvider for UI forms
  • Cache Integration: IdentityInterface implementation for policy caching
  • Event System: Event prefix and object for observers
  • Frontend Integration:
    • Layout XML for policy display
    • Block architecture for policy rendering
    • JavaScript for AJAX consent submission
    • Template system for various display modes

GDPR Compliance Features

  • Article 13/14 Transparency: Complete privacy notice system
  • Article 7 Consent Conditions: Valid consent recording with audit trail
  • Article 12 Accessibility: Clear, intelligible policy presentation
  • Right to Information: Version tracking for transparency
  • Accountability (Article 5): Comprehensive consent audit logs
  • Consent Withdrawal: Timestamp tracking for consent revocation
  • Data Minimization: Only essential consent metadata collected
  • Lawfulness of Processing: Documented legal basis via consent

Dependencies

  • Requires Qoliber_GdprFrontend for cookie consent integration
  • Requires Qoliber_GdprConsent for consent framework
  • Requires Magento_Cms for CMS page rendering
  • Requires Magento_Cookie for cookie management
  • PHP 8.1, 8.2, or 8.3 compatibility

Database Fields

qoliber_gdpr_privacy_policy table:

  • policy_id, title, content, version, status, consent_text, requires_consent, effective_date, store_id, language_code, created_at, updated_at

qoliber_gdpr_policy_consent table:

  • consent_id, customer_id, customer_email, guest_email, policy_id, policy_version, policy_type, ip_address, country_code, user_agent, session_id, context, consent_method, store_id, is_accepted, consented_at, withdrawn_at, additional_data

Admin Routes

  • qoliber_gdpr_policy/privacypolicy/index - Policy grid
  • qoliber_gdpr_policy/privacypolicy/new - Create policy
  • qoliber_gdpr_policy/privacypolicy/edit - Edit policy
  • qoliber_gdpr_policy/privacypolicy/save - Save policy
  • qoliber_gdpr_policy/privacypolicy/delete - Delete policy
  • qoliber_gdpr_policy/privacypolicy/publish - Publish policy
  • qoliber_gdpr_policy/consent/index - View consent logs

Frontend Routes

  • qoliber_gdpr/policy/accept - Accept/decline policy (POST)
  • qoliber_gdpr/policy/render - Render policy content
  • qoliber_gdpr/consent/log - Log consent event

GdprPolicyHyva — 2024

Added

  • Initial Hyvä compatibility module for Qoliber GDPR Policy
  • Hyvä privacy policy display templates with Tailwind CSS styling
  • Modal and inline display modes for privacy policy
  • Server-side policy consent logging integration
  • Policy version tracking and re-consent flow
  • Accept/decline flow compatible with Hyvä's Alpine.js patterns

Technical Details

  • Hyvä theme module registration via registration.php
  • Layout XML for Hyvä storefront integration
  • Plugin configuration for cookie consent coordination

GdprPrivacyCenter

Added

  • Initial release candidate with Privacy Center customer account integration

GdprPrivacyCenterHyva — 2024

Added

  • Initial Hyvä compatibility module for Qoliber GDPR Privacy Center
  • Customer account privacy dashboard using Hyvä's Alpine.js + Tailwind stack
  • Action card grid with four primary rights flows:
    • Export My Data
    • Update My Data (rectification)
    • Anonymize Data
    • Delete Account
  • Hyvä layout XML for customer account privacy integration
  • Navigation menu integration under customer account area

Technical Details

  • Hyvä theme module registration via registration.php
  • Layout XML for Hyvä storefront integration
  • No controllers or models required — purely presentational overlay on base module

GdprYireoGtm — 2024

Added

  • Yireo GTM Integration: Specialized integration module for Yireo's Google Tag Manager extension with GDPR cookie consent
  • TagType Implementation: YireoGtm class implementing TagTypeInterface for seamless integration with GdprFrontend tag system
  • Dynamic Module Detection: Automatic availability detection based on Yireo_GoogleTagManager2 module status
    • Uses ModuleManager to check if Yireo GTM is installed and enabled
    • Only appears in tag type selection when Yireo module is active
    • Prevents configuration errors when Yireo GTM is not available
  • Configuration Reuse: Leverages existing Yireo GTM configuration
    • No duplicate Container ID entry required
    • Reads container ID from Yireo's configuration path
    • Reduces configuration complexity
    • Eliminates sync issues between configurations
  • Template System: consent/yireo-gtm.phtml template for rendering Yireo GTM with consent awareness
  • Admin Guidance: Informational notice field explaining:
    • Yireo GoogleTagManager2 module requirement
    • Configuration location (Stores > Configuration > Yireo > GoogleTagManager)
    • Container ID source from Yireo's settings
  • Validation Bypass: Smart validation that skips tag ID format checking since Yireo manages its own configuration
  • Help Documentation: Context-aware help text explaining configuration-free setup

Technical Implementation

  • Implements Qoliber\GdprFrontend\Api\TagTypeInterface for tag type system integration
  • Code identifier: yireo_gtm
  • Label: "Yireo Google Tag Manager"
  • Conditional availability via isAvailable() method checking module status
  • Constructor dependency injection of ModuleManager for module detection
  • PHP 8.1, 8.2, and 8.3 compatibility with strict typing

Yireo GTM Version Support

  • Compatible with Yireo GoogleTagManager2 version 3.0 and 4.0
  • Requires yireo/magento2-googletagmanager2: ^3.0||^4.0
  • Forward-compatible version constraint for future updates

Dependencies

  • Requires Qoliber_GdprFrontend for base cookie consent and tag type framework
  • Requires Yireo_GoogleTagManager2 module (v3.0 or v4.0)
  • PHP 8.1, 8.2, or 8.3 compatibility

Integration Benefits

  • No Duplicate Configuration: Uses Yireo's existing GTM container ID
  • Seamless Integration: Works with Yireo's advanced GTM features
  • Consent Compliance: Adds cookie consent layer to Yireo GTM
  • Automatic Detection: Only shows when Yireo GTM is installed
  • DataLayer Compatibility: Preserves Yireo's dataLayer structure and events

Use Cases

  • Sites already using Yireo GTM wanting to add GDPR cookie consent
  • E-commerce stores with Yireo's enhanced e-commerce tracking
  • Businesses requiring advanced GTM features with consent compliance
  • Multi-store setups leveraging Yireo's GTM configuration

Configuration

  • No tag ID field required (uses Yireo's configuration)
  • Automatically integrates with Yireo's GTM settings
  • Tag type selection available in qoliber_gdpr_cookie/google_consent/tag_type
  • Only visible when both GdprFrontend and Yireo GTM are enabled

Notes

  • This is a bridge module between Qoliber GDPR and Yireo GTM
  • Does not replace Yireo GTM, but enhances it with consent management
  • Maintains compatibility with Yireo's future updates via version constraint
  • Listed as suggested (not required) in GdprMetapackage

1.0.0-beta2 — 2024

GdprFrontend

Changed

  • Enhanced stability and bug fixes for beta release

GdprPolicy

Changed

  • Enhanced stability and bug fixes for beta release

1.0.0-beta1 — 2024

GdprFrontend

Added

  • Initial beta release with core cookie consent functionality

GdprPolicy

Added

  • Initial beta release with core privacy policy management
Changelog — GDPR Compliance Suite — Compliance & Legal — Extensions | qoliber Docs