Bump version to 0.18.1
This commit is contained in:
@@ -4,6 +4,63 @@ 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/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||||
|
|
||||||
|
## [0.18.1] - 2026-09-16
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `Modules\Core\Payment\Privacy\PaymentDataProvider` — `lunar_transactions` (`card_type`/
|
||||||
|
`last_four`) and `stripe_payment_intents` were previously uncovered by any Privacy provider.
|
||||||
|
Pseudonymizes card metadata on erasure (same tax/accounting retention reasoning as
|
||||||
|
`OrderDataProvider`); deletes the Stripe correlation rows outright, since their only purpose
|
||||||
|
(resolving an async webhook callback) has already been served by the time an erasure request
|
||||||
|
runs. No Stripe Customer object exists anywhere in this app to also request deletion of — see
|
||||||
|
`docs/payments.md` "Reconciliation".
|
||||||
|
- `Modules\Core\Auth\Privacy\UserSessionDataProvider` — `user_sessions` (`ip_address`,
|
||||||
|
`user_agent`) was previously uncovered. User-scope only; deleted outright on erasure, no legal
|
||||||
|
retention argument applies to login-session metadata.
|
||||||
|
- `Modules\Core\Logging\Privacy\ActivityLogDataProvider` — Spatie's `activity_log` table
|
||||||
|
(`Modules\Core\Logging\ActivityLogService`, plus several Lunar models' native `LogsActivity`)
|
||||||
|
durably retained full PII snapshots in `properties` even after the real row was erased
|
||||||
|
elsewhere. Redacts `properties` by subject (`Customer`/`Address`/`CartAddress`/`OrderAddress`/
|
||||||
|
`Transaction`) on erasure; deliberately never touches `causer_id`, which is an actor reference,
|
||||||
|
not PII content. Must run before `AddressDataProvider` in `config('core.privacy.providers')` —
|
||||||
|
see the class's own docblock.
|
||||||
|
- `ErasureOutcome::Failed` — a provider throwing an exception is now a genuine, distinct outcome
|
||||||
|
from `Skipped` (a deliberate no-op), surfaced in the erasure report rather than silently
|
||||||
|
aborting the request.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- `PrivacyService::completeErasure()` and `ExportDataSubjectJob::handle()` ran every registered
|
||||||
|
provider through a plain `array_map()` with no per-provider error handling — one provider
|
||||||
|
throwing aborted the entire request, discarding every other provider's already-computed
|
||||||
|
result and leaving the request stuck `Pending`/`Failed` with no report at all. Both now catch
|
||||||
|
per-provider (`PrivacyService::safeErase()`, `ExportDataSubjectJob::safeExport()`), logging the
|
||||||
|
exception and recording `ErasureOutcome::Failed`/`ProviderExportResult::$error` for that one
|
||||||
|
provider while every other provider's result is still recorded normally. Verified live:
|
||||||
|
simulating a throwing provider mid-erasure now correctly completes the request with a mixed
|
||||||
|
`erased`/`failed`/`erased` report instead of leaving it `Pending` forever.
|
||||||
|
- `CartDataProvider`/`OrderDataProvider` never covered PII-adjacent keys living in `Cart.meta`/
|
||||||
|
`Order.meta`/`OrderAddress.meta` — `recovery_consent*`, `payment_method`, `checkout_fingerprint`
|
||||||
|
(Cart), `terms_accepted*` (Order), and `box_now_locker` (OrderAddress) all survived an erasure
|
||||||
|
request untouched. Both providers now clear these keys alongside their existing address/
|
||||||
|
free-text field erasure.
|
||||||
|
- `CustomerDataProvider::eraseForUser()` left `otp_code`/`otp_expires_at`/`otp_attempts` on an
|
||||||
|
otherwise-erased `User` row. Now cleared alongside name/email.
|
||||||
|
- `Modules\Core\Privacy\Filament\Resources\DataErasureRequestResource`'s "Outcome" section
|
||||||
|
referenced `docs/privacy.md` directly in staff-facing UI text (meaningless to a user with no
|
||||||
|
repo access) and rendered the per-provider report as raw JSON strings via a `KeyValueEntry`
|
||||||
|
(the wrong component for a list of structured rows). Replaced with a plain-language
|
||||||
|
description and a proper `RepeatableEntry` table (Data category / Outcome badge / Reason).
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- The 5 existing Privacy providers (`CustomerDataProvider`, `AddressDataProvider`,
|
||||||
|
`OrderDataProvider`, `CartDataProvider`, `ReviewDataProvider`) moved out of
|
||||||
|
`Modules\Core\Privacy\Providers` into their owning domain module's own `Privacy/` subdirectory
|
||||||
|
(e.g. `Modules\Core\Order\Privacy\OrderDataProvider`) — `Modules\Core\Privacy` now owns only
|
||||||
|
the shared contract, request lifecycle, and DTOs/enums. Matters concretely if a module is ever
|
||||||
|
extracted into its own composer package: the provider that knows how to erase that module's
|
||||||
|
data now travels with it, rather than being stranded in `Privacy` depending on a package that
|
||||||
|
no longer ships in this repo. See `docs/privacy.md` for the full reasoning.
|
||||||
|
|
||||||
## [0.18.0] - 2026-09-16
|
## [0.18.0] - 2026-09-16
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"name": "boboko/core",
|
"name": "boboko/core",
|
||||||
"description": "Core module — authentication and shared panel behaviour",
|
"description": "Core module — authentication and shared panel behaviour",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"version": "0.18.0",
|
"version": "0.18.1",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Modules\\Core\\": "src/"
|
"Modules\\Core\\": "src/"
|
||||||
|
|||||||
@@ -202,6 +202,19 @@ purely a recovery aid for the case where our own write never happened at all.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## GDPR erasure/export
|
||||||
|
|
||||||
|
`Modules\Core\Payment\Privacy\PaymentDataProvider` covers `lunar_transactions`
|
||||||
|
(`card_type`/`last_four`) and `stripe_payment_intents` — see `docs/privacy.md` for the full
|
||||||
|
right-of-erasure/right-of-access design. Pseudonymizes card metadata on erasure (same
|
||||||
|
tax/accounting retention reasoning `Order`'s own provider uses) and deletes the Stripe
|
||||||
|
correlation rows outright, since their only purpose — resolving an async webhook callback, see
|
||||||
|
"Async resolution" above — has already been served by the time an erasure request runs. No
|
||||||
|
Stripe Customer object exists anywhere in this app (see "Reconciliation" above) for this
|
||||||
|
provider to also request deletion of.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Explicitly out of scope for this pass
|
## Explicitly out of scope for this pass
|
||||||
|
|
||||||
- **`Checkout`/`Order` wiring** — how `Checkout` calls into `Payment`, how `Order`/`Checkout`
|
- **`Checkout`/`Order` wiring** — how `Checkout` calls into `Payment`, how `Order`/`Checkout`
|
||||||
|
|||||||
Reference in New Issue
Block a user