From 359e1e262e6ab38fed99f25a0271c2d3b15ab999 Mon Sep 17 00:00:00 2001 From: Konstantinos Arvanitakis Date: Wed, 9 Sep 2026 01:19:31 +0300 Subject: [PATCH] Bump Version to 0.16.0 --- CHANGELOG.md | 38 ++++++++++++++++++++++++++++++++++++++ composer.json | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f48ffca..080cb57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,44 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [0.16.0] - 2026-09-08 + +### Added +- `Modules\Core\Checkout\Services\CheckoutService::setRecoveryConsent(bool $consent): Cart` — the + shopper's promotional/abandoned-cart-recovery opt-in, given once during guest checkout and + deliberately independent of `setShippingAddress()`/`setBillingAddress()`: consent is a + cart-level decision, not tied to any one `CartAddress` — changing which address is on the cart + later never resets or re-asks for it. Only an explicit call to this method (the checkbox itself + being submitted) ever changes it; calling it again with `false` is how a later opt-out is + recorded, per the legal requirement that consent be provable and withdrawable. Stored on + `Cart::meta` (interim, per the design this implements — a real column/consent record is the + eventual target, tracked as follow-up) as `recovery_consent` (bool), `recovery_consent_at` + (ISO 8601, `null` when `false`), and `recovery_consent_policy_version` + (`config('legal.privacy_policy_version')` at the moment of consent, so a later dispute is + answered from what was actually agreed to). Dispatches new + `Modules\Core\Checkout\Events\RecoveryConsentSet`. Newsletter opt-in is explicitly a separate + scope — never merged into this flag. +- `Modules\Core\Checkout\Services\CheckoutService::initiatePayment()` now requires `bool + $termsAccepted` and `string $policyVersion` as mandatory parameters (not optional data a caller + might omit) — throws the new `Modules\Core\Checkout\Exceptions\TermsNotAcceptedException` + *before* `Cart::createOrder()` is ever called if `$termsAccepted` is `false`, so an order can + never exist without a recorded acceptance (refused, not created-then-flagged). On success, + writes `terms_accepted` (`true`), `terms_accepted_at` (ISO 8601), and + `terms_accepted_policy_version` onto the created `Order`'s own `meta` — the durable, + order-level audit trail for a consumer-contract acceptance dispute, written directly (not via + an event/listener) since the `Order` row doesn't exist until `createOrder()` returns. +- `Modules\Core\Cart\Commands\DetectAbandonedCarts` — both its `CartAbandoned` and + `CheckoutAbandoned` detection queries now require `meta->recovery_consent = true`. A + non-consenting cart's abandonment is never dispatched at all (not merely filtered later at + whatever future recovery-email send step reads it) — the correct enforcement point per the + legal requirement that recovery/marketing sends only ever reach carts that opted in. +- `config/legal.php` (merged by a new `Modules\Core\Providers\CheckoutServiceProvider`) — + `privacy_policy_version`/`terms_version`, plain `env()`-backed strings bumped by whoever edits + the corresponding legal page. Recorded alongside every consent/acceptance rather than read live + at dispute time, so what a shopper actually agreed to is answered from the cart/order itself. + `CheckoutServiceProvider` itself is new — `Checkout` previously had no dedicated service + provider at all (its service/events were resolved/dispatched without one). + ## [0.15.0] - 2026-09-07 ### Changed diff --git a/composer.json b/composer.json index 2458e06..c07ff96 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "boboko/core", "description": "Core module — authentication and shared panel behaviour", "type": "library", - "version": "0.15.0", + "version": "0.16.0", "autoload": { "psr-4": { "Modules\\Core\\": "src/"