@@ -327,3 +327,218 @@ and replaced with the following headers:
327327
328328The ` Patchlevel\EventSourcing\Schema\DoctrineSchemaSubscriber ` has been removed.
329329use the ` Patchlevel\EventSourcing\Schema\DoctrineSchemaListener ` instead.
330+
331+ ## Serializer
332+
333+ The library now uses ` patchlevel/hydrator ` 2.0. The ` Patchlevel\Hydrator\MetadataHydrator `
334+ has been removed. Build a hydrator with the ` StackHydratorBuilder ` and the ` CoreExtension ` instead.
335+ Upcasting and crypto-shredding are no longer wired through the serializer factories,
336+ you register them on the hydrator as middleware or extension.
337+
338+ before:
339+
340+ ``` php
341+ use Patchlevel\Hydrator\Hydrator;
342+ use Patchlevel\Hydrator\MetadataHydrator;
343+
344+ $hydrator = new MetadataHydrator();
345+ ```
346+ after:
347+
348+ ``` php
349+ use Patchlevel\Hydrator\CoreExtension;
350+ use Patchlevel\Hydrator\Hydrator;
351+ use Patchlevel\Hydrator\StackHydratorBuilder;
352+
353+ $hydrator = (new StackHydratorBuilder())
354+ ->useExtension(new CoreExtension())
355+ ->build();
356+ ```
357+
358+ ### DefaultEventSerializer
359+
360+ ` createFromPaths() ` no longer accepts an ` $upcaster ` or a ` $cryptographer ` argument.
361+ The second argument is now an optional ` Hydrator ` , a default one is built when it is ` null ` .
362+ Register upcasting via ` UpcastMiddleware ` and crypto-shredding via the ` CryptographyExtension `
363+ on the hydrator you pass in.
364+
365+ before:
366+
367+ ``` php
368+ use Patchlevel\EventSourcing\Serializer\DefaultEventSerializer;
369+ use Patchlevel\EventSourcing\Serializer\Upcast\Upcaster;
370+ use Patchlevel\Hydrator\Cryptography\PayloadCryptographer;
371+
372+ /**
373+ * @var Upcaster $upcaster
374+ * @var PayloadCryptographer $cryptographer
375+ */
376+ $serializer = DefaultEventSerializer::createFromPaths(
377+ [__DIR__ . '/Events'],
378+ $upcaster,
379+ $cryptographer,
380+ );
381+ ```
382+ after:
383+
384+ ``` php
385+ use Patchlevel\EventSourcing\Serializer\DefaultEventSerializer;
386+ use Patchlevel\EventSourcing\Serializer\Upcast\UpcastMiddleware;
387+ use Patchlevel\EventSourcing\Serializer\Upcast\Upcaster;
388+ use Patchlevel\Hydrator\CoreExtension;
389+ use Patchlevel\Hydrator\Extension\Cryptography\BaseCryptographer;
390+ use Patchlevel\Hydrator\Extension\Cryptography\CryptographyExtension;
391+ use Patchlevel\Hydrator\Extension\Cryptography\Store\CipherKeyStore;
392+ use Patchlevel\Hydrator\StackHydratorBuilder;
393+
394+ /**
395+ * @var Upcaster $upcaster
396+ * @var CipherKeyStore $cipherKeyStore
397+ */
398+ $hydrator = (new StackHydratorBuilder())
399+ ->useExtension(new CoreExtension())
400+ ->useExtension(new CryptographyExtension(BaseCryptographer::createWithOpenssl($cipherKeyStore)))
401+ ->addMiddleware(new UpcastMiddleware($upcaster))
402+ ->build();
403+
404+ $serializer = DefaultEventSerializer::createFromPaths(
405+ [__DIR__ . '/Events'],
406+ $hydrator,
407+ );
408+ ```
409+
410+ ### DefaultHeadersSerializer
411+
412+ The ` $hydrator ` argument of the constructor, ` createFromPaths() ` and ` createDefault() `
413+ is now an optional ` Hydrator ` defaulting to ` null ` . The ` MetadataHydrator ` default has been removed.
414+
415+ ## Snapshots
416+
417+ ### DefaultSnapshotStore
418+
419+ The constructor no longer accepts an array of adapters as its first argument,
420+ it now requires an ` AdapterRepository ` . Pass adapters as an array through ` createDefault() ` instead.
421+
422+ before:
423+
424+ ``` php
425+ use Patchlevel\EventSourcing\Snapshot\DefaultSnapshotStore;
426+
427+ $snapshotStore = new DefaultSnapshotStore(['default' => $adapter]);
428+ ```
429+ after:
430+
431+ ``` php
432+ use Patchlevel\EventSourcing\Snapshot\DefaultSnapshotStore;
433+
434+ $snapshotStore = DefaultSnapshotStore::createDefault(['default' => $adapter]);
435+ ```
436+
437+ The ` $cryptographer ` argument of ` createDefault() ` has been replaced by an optional ` Hydrator ` .
438+ Build the hydrator with the ` CryptographyExtension ` like for the event serializer.
439+
440+ before:
441+
442+ ``` php
443+ use Patchlevel\EventSourcing\Snapshot\DefaultSnapshotStore;
444+ use Patchlevel\Hydrator\Cryptography\PayloadCryptographer;
445+
446+ /** @var PayloadCryptographer $cryptographer */
447+ $snapshotStore = DefaultSnapshotStore::createDefault(
448+ ['default' => $adapter],
449+ $cryptographer,
450+ );
451+ ```
452+ after:
453+
454+ ``` php
455+ use Patchlevel\EventSourcing\Snapshot\DefaultSnapshotStore;
456+ use Patchlevel\Hydrator\Hydrator;
457+
458+ /** @var Hydrator $hydrator */
459+ $snapshotStore = DefaultSnapshotStore::createDefault(
460+ ['default' => $adapter],
461+ $hydrator,
462+ );
463+ ```
464+
465+ ## Sensitive Data
466+
467+ The crypto-shredding stack moved to the cryptography extension of ` patchlevel/hydrator ` 2.0.
468+
469+ ### Attributes
470+
471+ The attributes moved namespace and ` PersonalData ` was renamed to ` SensitiveData ` :
472+
473+ * ` Patchlevel\Hydrator\Attribute\DataSubjectId ` -> ` Patchlevel\Hydrator\Extension\Cryptography\Attribute\DataSubjectId `
474+ * ` Patchlevel\Hydrator\Attribute\PersonalData ` -> ` Patchlevel\Hydrator\Extension\Cryptography\Attribute\SensitiveData `
475+
476+ before:
477+
478+ ``` php
479+ use Patchlevel\EventSourcing\Identifier\Uuid;
480+ use Patchlevel\Hydrator\Attribute\DataSubjectId;
481+ use Patchlevel\Hydrator\Attribute\PersonalData;
482+
483+ final class EmailChanged
484+ {
485+ public function __construct(
486+ #[DataSubjectId]
487+ public readonly Uuid $profileId,
488+ #[PersonalData(fallback: 'unknown')]
489+ public readonly string $email,
490+ ) {
491+ }
492+ }
493+ ```
494+ after:
495+
496+ ``` php
497+ use Patchlevel\EventSourcing\Identifier\Uuid;
498+ use Patchlevel\Hydrator\Extension\Cryptography\Attribute\DataSubjectId;
499+ use Patchlevel\Hydrator\Extension\Cryptography\Attribute\SensitiveData;
500+
501+ final class EmailChanged
502+ {
503+ public function __construct(
504+ #[DataSubjectId]
505+ public readonly Uuid $profileId,
506+ #[SensitiveData(fallback: 'unknown')]
507+ public readonly string $email,
508+ ) {
509+ }
510+ }
511+ ```
512+
513+ ### DoctrineCipherKeyStore
514+
515+ The legacy ` Patchlevel\EventSourcing\Cryptography\DoctrineCipherKeyStore ` and
516+ ` Patchlevel\EventSourcing\Cryptography\ExtensionDoctrineCipherKeyStore ` have been merged into a
517+ single ` Patchlevel\EventSourcing\Cryptography\DoctrineCipherKeyStore ` that implements the new
518+ ` Patchlevel\Hydrator\Extension\Cryptography\Store\CipherKeyStore ` . The default table name changed
519+ from ` crypto_keys ` to ` cryptography_keys ` , and keys are now stored per id with a subject index.
520+
521+ To erase the data of a subject, call ` removeWithSubjectId() ` , the ` remove() ` method now deletes by key id.
522+
523+ before:
524+
525+ ``` php
526+ $cipherKeyStore->remove($subjectId);
527+ ```
528+ after:
529+
530+ ``` php
531+ $cipherKeyStore->removeWithSubjectId($subjectId);
532+ ```
533+
534+ ::: danger
535+ The key table layout changed (` crypto_keys ` -> ` cryptography_keys ` with new columns).
536+ Existing keys must be migrated, otherwise stored sensitive data can no longer be decrypted.
537+ :::
538+
539+ ### Cryptographer
540+
541+ ` Patchlevel\Hydrator\Cryptography\PayloadCryptographer ` and its implementations
542+ (` PersonalDataPayloadCryptographer ` , ` SensitiveDataPayloadCryptographer ` ) have been removed.
543+ Create a ` Patchlevel\Hydrator\Extension\Cryptography\BaseCryptographer ` and register it on the
544+ hydrator through the ` CryptographyExtension ` (see the Serializer section above).
0 commit comments