You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2020/12/07 03:57:37 UTC

[james-project] 07/13: JAMES-3435 Pilot Cassandra mailbox ACL changes with an event sourcing system

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 86a044f938b92d78bac33e6200030b68d6ec3d49
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Dec 4 12:19:08 2020 +0700

    JAMES-3435 Pilot Cassandra mailbox ACL changes with an event sourcing system
    
    Maintains LWT free, efficient projections which enables optimized reads.
    
    Safe, transactional source of truth with event sourcing.
    
    Rebuilding the projections needs to be added in the future.
---
 .../org/apache/james/mailbox/model/MailboxACL.java |   8 +-
 mailbox/cassandra/pom.xml                          |  12 ++
 .../james/mailbox/cassandra/ids/CassandraId.java   |   6 +-
 .../mailbox/cassandra/mail/CassandraACLMapper.java | 153 +++++++++++++++---
 .../mail/eventsourcing/acl/ACLCommandDTO.java      |  94 +++++++++++
 .../cassandra/mail/eventsourcing/acl/ACLDTO.java   |  73 +++++++++
 .../eventsourcing/acl/ACLDiffDTO.java}             |  70 ++++-----
 .../mail/eventsourcing/acl/ACLModule.java          |  45 ++++++
 .../eventsourcing/acl/ACLReseted.java}             |  67 ++++----
 .../mail/eventsourcing/acl/ACLResetedDTO.java      | 107 +++++++++++++
 .../eventsourcing/acl/ACLUpdated.java}             |  75 ++++-----
 .../mail/eventsourcing/acl/ACLUpdatedDTO.java      | 116 ++++++++++++++
 .../mail/eventsourcing/acl/AclV2DAOSubscriber.java |  46 ++++++
 .../eventsourcing/acl/DeleteMailboxCommand.java    |  61 ++++++++
 .../eventsourcing/acl/MailboxACLAggregate.java     | 100 ++++++++++++
 .../eventsourcing/acl/MailboxAggregateId.java}     |  59 ++-----
 .../mail/eventsourcing/acl/SetACLCommand.java      |  68 ++++++++
 .../mail/eventsourcing/acl/UpdateACLCommand.java   |  70 +++++++++
 .../eventsourcing/acl/UserRightsDAOSubscriber.java |  46 ++++++
 .../cassandra/mail/migration/AclV2Migration.java   |  17 +-
 .../cassandra/CassandraMailboxManagerTest.java     |  23 ++-
 .../cassandra/mail/CassandraACLMapperV1Test.java   |  21 ++-
 .../cassandra/mail/CassandraACLMapperV2Test.java   |  21 ++-
 .../mail/CassandraMailboxMapperAclTest.java        |   2 +
 .../cassandra/mail/CassandraMailboxMapperTest.java |  39 +++--
 ...est.java => CassandraMailboxMapperV10Test.java} | 173 ++++-----------------
 .../cassandra/mail/MailboxAggregateModule.java     |  32 ++--
 .../mail/migration/AclV2MigrationTest.java         |  22 ++-
 .../mail/migration/MailboxPathV2MigrationTest.java |  27 +++-
 .../mailbox/cassandra/mail/utils/GuiceUtils.java   |  23 +++
 .../modules/mailbox/CassandraMailboxModule.java    |  12 +-
 31 files changed, 1294 insertions(+), 394 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
index 22b7f8f..fe0d66f 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
@@ -69,7 +69,13 @@ public class MailboxACL {
      * SETACL command mode.
      */
     public enum EditMode {
-        ADD, REMOVE, REPLACE
+        ADD, REMOVE, REPLACE;
+
+        public static Optional<EditMode> parse(String string) {
+            return Arrays.stream(values())
+                .filter(value -> value.toString().equalsIgnoreCase(string))
+                .findAny();
+        }
     }
 
     public enum NameType {
diff --git a/mailbox/cassandra/pom.xml b/mailbox/cassandra/pom.xml
index c58966f..385f0b6 100644
--- a/mailbox/cassandra/pom.xml
+++ b/mailbox/cassandra/pom.xml
@@ -89,6 +89,18 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>event-sourcing-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>event-sourcing-event-store-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>event-sourcing-event-store-cassandra</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-json</artifactId>
             <type>test-jar</type>
             <scope>test</scope>
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
index 8de229c..6b5ff6e 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
@@ -32,7 +32,7 @@ public class CassandraId implements MailboxId, Serializable {
     public static class Factory implements MailboxId.Factory {
         @Override
         public CassandraId fromString(String serialized) {
-            return of(UUID.fromString(serialized));
+            return of(serialized);
         }
     }
     
@@ -46,6 +46,10 @@ public class CassandraId implements MailboxId, Serializable {
         return new CassandraId(id);
     }
 
+    public static CassandraId of(String serialized) {
+        return new CassandraId(UUID.fromString(serialized));
+    }
+
     private CassandraId(UUID id) {
         this.id = id;
     }
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java
index 517256e..116c8fa 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapper.java
@@ -19,66 +19,169 @@
 
 package org.apache.james.mailbox.cassandra.mail;
 
+import java.util.Set;
+
 import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
+import org.apache.james.eventsourcing.Command;
+import org.apache.james.eventsourcing.CommandHandler;
+import org.apache.james.eventsourcing.EventSourcingSystem;
+import org.apache.james.eventsourcing.Subscriber;
+import org.apache.james.eventsourcing.eventstore.EventStore;
 import org.apache.james.mailbox.acl.ACLDiff;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLReseted;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLUpdated;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.AclV2DAOSubscriber;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.DeleteMailboxCommand;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.MailboxAggregateId;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.SetACLCommand;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.UpdateACLCommand;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.UserRightsDAOSubscriber;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxACL;
 
+import com.google.common.collect.ImmutableSet;
+
 import reactor.core.publisher.Mono;
 
 public class CassandraACLMapper {
+    public interface Store {
+        Mono<MailboxACL> getACL(CassandraId cassandraId);
+
+        Mono<ACLDiff> updateACL(CassandraId cassandraId, MailboxACL.ACLCommand command);
+
+        Mono<ACLDiff> setACL(CassandraId cassandraId, MailboxACL mailboxACL);
+
+        Mono<Void> delete(CassandraId cassandraId);
+    }
+
+    public static class StoreV1 implements Store {
+        private final CassandraUserMailboxRightsDAO userMailboxRightsDAO;
+        private final CassandraACLDAOV1 cassandraACLDAOV1;
+
+        @Inject
+        public StoreV1(CassandraUserMailboxRightsDAO userMailboxRightsDAO, CassandraACLDAOV1 cassandraACLDAOV1) {
+            this.userMailboxRightsDAO = userMailboxRightsDAO;
+            this.cassandraACLDAOV1 = cassandraACLDAOV1;
+        }
+
+        @Override
+        public Mono<MailboxACL> getACL(CassandraId cassandraId) {
+            return cassandraACLDAOV1.getACL(cassandraId);
+        }
+
+        @Override
+        public Mono<ACLDiff> updateACL(CassandraId cassandraId, MailboxACL.ACLCommand command) {
+            return cassandraACLDAOV1.updateACL(cassandraId, command)
+                .flatMap(aclDiff -> userMailboxRightsDAO.update(cassandraId, aclDiff)
+                    .thenReturn(aclDiff))
+                .switchIfEmpty(Mono.error(new MailboxException("Unable to update ACL")));
+        }
+
+        @Override
+        public Mono<ACLDiff> setACL(CassandraId cassandraId, MailboxACL mailboxACL) {
+            return cassandraACLDAOV1.setACL(cassandraId, mailboxACL)
+                .flatMap(aclDiff -> userMailboxRightsDAO.update(cassandraId, aclDiff)
+                    .thenReturn(aclDiff))
+                .switchIfEmpty(Mono.defer(() -> Mono.error(new MailboxException("Unable to update ACL"))));
+        }
+
+        public Mono<Void> delete(CassandraId cassandraId) {
+            return cassandraACLDAOV1.getACL(cassandraId)
+                .flatMap(acl -> userMailboxRightsDAO.update(cassandraId, ACLDiff.computeDiff(acl, MailboxACL.EMPTY))
+                    .then(cassandraACLDAOV1.delete(cassandraId)));
+        }
+    }
+
+    public static class StoreV2 implements Store {
+        private final CassandraACLDAOV2 cassandraACLDAOV2;
+        private final EventSourcingSystem eventSourcingSystem;
+
+        @Inject
+        public StoreV2(CassandraUserMailboxRightsDAO userMailboxRightsDAO,
+                CassandraACLDAOV2 cassandraACLDAOV2,
+                EventStore eventStore) {
+            this.cassandraACLDAOV2 = cassandraACLDAOV2;
+            Set<CommandHandler<? extends Command>> commandHandlers = ImmutableSet.of(new DeleteMailboxCommand.CommandHandler(eventStore),
+                new UpdateACLCommand.CommandHandler(eventStore),
+                new SetACLCommand.CommandHandler(eventStore));
+            Set<Subscriber> subscribers = ImmutableSet.of(new UserRightsDAOSubscriber(userMailboxRightsDAO),
+                new AclV2DAOSubscriber(cassandraACLDAOV2));
+            eventSourcingSystem = EventSourcingSystem.fromJava(commandHandlers, subscribers, eventStore);
+        }
+
+        @Override
+        public Mono<MailboxACL> getACL(CassandraId cassandraId) {
+            return cassandraACLDAOV2.getACL(cassandraId);
+        }
+
+        @Override
+        public Mono<ACLDiff> updateACL(CassandraId cassandraId, MailboxACL.ACLCommand command) {
+            return Mono.from(eventSourcingSystem.dispatch(new UpdateACLCommand(new MailboxAggregateId(cassandraId), command)))
+                .flatMapIterable(events -> events)
+                .filter(ACLUpdated.class::isInstance)
+                .map(ACLUpdated.class::cast)
+                .map(ACLUpdated::getAclDiff)
+                .next()
+                .switchIfEmpty(Mono.defer(() -> Mono.error(new MailboxException("Unable to update ACL"))));
+        }
+
+        @Override
+        public Mono<ACLDiff> setACL(CassandraId cassandraId, MailboxACL mailboxACL) {
+            return Mono.from(eventSourcingSystem.dispatch(new SetACLCommand(new MailboxAggregateId(cassandraId), mailboxACL)))
+                .flatMapIterable(events -> events)
+                .filter(ACLReseted.class::isInstance)
+                .map(ACLReseted.class::cast)
+                .map(ACLReseted::getAclDiff)
+                .next()
+                .switchIfEmpty(Mono.defer(() -> Mono.error(new MailboxException("Unable to set ACL"))));
+        }
+
+        @Override
+        public Mono<Void> delete(CassandraId cassandraId) {
+            return Mono.from(eventSourcingSystem.dispatch(new DeleteMailboxCommand(new MailboxAggregateId(cassandraId)))).then();
+        }
+    }
+
     public static final SchemaVersion ACL_V2_SCHEME_VERSION = new SchemaVersion(10);
-    private final CassandraUserMailboxRightsDAO userMailboxRightsDAO;
-    private final CassandraACLDAOV1 cassandraACLDAOV1;
-    private final CassandraACLDAOV2 cassandraACLDAOV2;
+    private final StoreV1 storeV1;
+    private final StoreV2 storeV2;
     private final CassandraSchemaVersionManager versionManager;
 
     @Inject
-    public CassandraACLMapper(CassandraUserMailboxRightsDAO userMailboxRightsDAO,
-                              CassandraACLDAOV1 cassandraACLDAOV1,
-                              CassandraACLDAOV2 cassandraACLDAOV2,
-                              CassandraSchemaVersionManager versionManager) {
-        this.cassandraACLDAOV1 = cassandraACLDAOV1;
-        this.cassandraACLDAOV2 = cassandraACLDAOV2;
-        this.userMailboxRightsDAO = userMailboxRightsDAO;
+    public CassandraACLMapper(StoreV1 storeV1, StoreV2 storeV2, CassandraSchemaVersionManager versionManager) {
+        this.storeV1 = storeV1;
+        this.storeV2 = storeV2;
+
         this.versionManager = versionManager;
     }
 
-    private Mono<CassandraACLDAO> aclDao() {
+    private Mono<Store> store() {
         return versionManager.isBefore(ACL_V2_SCHEME_VERSION)
             .map(isBefore -> {
                 if (isBefore) {
-                    return cassandraACLDAOV1;
+                    return storeV1;
                 }
-                return cassandraACLDAOV2;
+                return storeV2;
             });
     }
 
     public Mono<MailboxACL> getACL(CassandraId cassandraId) {
-        return aclDao().flatMap(dao -> dao.getACL(cassandraId));
+        return store().flatMap(store -> store.getACL(cassandraId));
     }
 
     public Mono<ACLDiff> updateACL(CassandraId cassandraId, MailboxACL.ACLCommand command) {
-        return aclDao().flatMap(dao -> dao.updateACL(cassandraId, command)
-            .flatMap(aclDiff -> userMailboxRightsDAO.update(cassandraId, aclDiff)
-            .thenReturn(aclDiff))
-            .switchIfEmpty(Mono.error(new MailboxException("Unable to update ACL"))));
+        return store().flatMap(store -> store.updateACL(cassandraId, command));
     }
 
     public Mono<ACLDiff> setACL(CassandraId cassandraId, MailboxACL mailboxACL) {
-        return aclDao().flatMap(dao -> dao.setACL(cassandraId, mailboxACL)
-            .flatMap(aclDiff -> userMailboxRightsDAO.update(cassandraId, aclDiff)
-            .thenReturn(aclDiff))
-            .switchIfEmpty(Mono.defer(() -> Mono.error(new MailboxException("Unable to update ACL")))));
+        return store().flatMap(store -> store.setACL(cassandraId, mailboxACL));
     }
 
     public Mono<Void> delete(CassandraId cassandraId) {
-        return aclDao().flatMap(dao -> dao.getACL(cassandraId)
-            .flatMap(acl -> userMailboxRightsDAO.update(cassandraId, ACLDiff.computeDiff(acl, MailboxACL.EMPTY))
-            .then(dao.delete(cassandraId))));
+        return store().flatMap(store -> store.delete(cassandraId));
     }
 }
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLCommandDTO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLCommandDTO.java
new file mode 100644
index 0000000..16f5e6f
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLCommandDTO.java
@@ -0,0 +1,94 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import java.util.Objects;
+
+import org.apache.james.mailbox.exception.UnsupportedRightException;
+import org.apache.james.mailbox.model.MailboxACL;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ACLCommandDTO {
+    public static ACLCommandDTO fromCommand(MailboxACL.ACLCommand command) {
+        return new ACLCommandDTO(command.getEditMode().name(),
+            command.getEntryKey().serialize(),
+            command.getRights().serialize());
+    }
+
+    private final String mode;
+    private final String entry;
+    private final String rights;
+
+    @JsonCreator
+    public ACLCommandDTO(@JsonProperty("mode") String mode,
+                         @JsonProperty("entry") String entry,
+                         @JsonProperty("rights") String rights) {
+        this.mode = mode;
+        this.entry = entry;
+        this.rights = rights;
+    }
+
+
+    @JsonProperty("mode")
+    public String getMode() {
+        return mode;
+    }
+
+    @JsonProperty("entry")
+    public String getEntry() {
+        return entry;
+    }
+
+    @JsonProperty("rights")
+    public String getRights() {
+        return rights;
+    }
+
+    public MailboxACL.ACLCommand asACLCommand() {
+        try {
+            return MailboxACL.command()
+                .key(MailboxACL.EntryKey.deserialize(entry))
+                .rights(MailboxACL.Rfc4314Rights.deserialize(rights))
+                .mode(MailboxACL.EditMode.parse(mode).orElseThrow(() -> new IllegalArgumentException(mode + " is not a supported EditMode")))
+                .build();
+        } catch (UnsupportedRightException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof ACLCommandDTO) {
+            ACLCommandDTO that = (ACLCommandDTO) o;
+
+            return Objects.equals(this.mode, that.mode)
+                && Objects.equals(this.entry, that.entry)
+                && Objects.equals(this.rights, that.rights);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(mode, entry, rights);
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLDTO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLDTO.java
new file mode 100644
index 0000000..08dd711
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLDTO.java
@@ -0,0 +1,73 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import java.util.Map;
+import java.util.Objects;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.james.mailbox.model.MailboxACL;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.github.fge.lambdas.Throwing;
+import com.github.steveash.guavate.Guavate;
+
+public class ACLDTO {
+    public static ACLDTO fromACL(MailboxACL acl) {
+        return new ACLDTO(acl.getEntries().entrySet().stream()
+            .map(entry -> Pair.of(entry.getKey().serialize(), entry.getValue().serialize()))
+            .collect(Guavate.toImmutableMap(Pair::getKey, Pair::getValue)));
+    }
+
+    private final Map<String, String> entries;
+
+    @JsonCreator
+    public ACLDTO(@JsonProperty("entries") Map<String, String> entries) {
+        this.entries = entries;
+    }
+
+    @JsonProperty("entries")
+    public Map<String, String> getEntries() {
+        return entries;
+    }
+
+    public MailboxACL asACL() {
+        return new MailboxACL(entries.entrySet().stream()
+            .map(Throwing.function(entry -> Pair.of(MailboxACL.EntryKey.deserialize(entry.getKey()),
+                MailboxACL.Rfc4314Rights.deserialize(entry.getValue()))))
+            .collect(Guavate.toImmutableMap(Pair::getKey, Pair::getValue)));
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof ACLDTO) {
+            ACLDTO that = (ACLDTO) o;
+
+            return Objects.equals(this.entries, that.entries);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(entries);
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLDiffDTO.java
similarity index 53%
copy from mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
copy to mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLDiffDTO.java
index 8de229c..9b72e1d 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLDiffDTO.java
@@ -16,67 +16,61 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-package org.apache.james.mailbox.cassandra.ids;
 
-import java.io.Serializable;
-import java.util.Objects;
-import java.util.UUID;
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
 
-import org.apache.james.mailbox.model.MailboxId;
+import java.util.Objects;
 
-import com.datastax.driver.core.utils.UUIDs;
-import com.google.common.base.MoreObjects;
+import org.apache.james.mailbox.acl.ACLDiff;
 
-public class CassandraId implements MailboxId, Serializable {
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 
-    public static class Factory implements MailboxId.Factory {
-        @Override
-        public CassandraId fromString(String serialized) {
-            return of(UUID.fromString(serialized));
-        }
+public class ACLDiffDTO {
+    public static ACLDiffDTO fromACLDiff(ACLDiff aclDiff) {
+        return new ACLDiffDTO(ACLDTO.fromACL(aclDiff.getOldACL()),
+            ACLDTO.fromACL(aclDiff.getNewACL()));
     }
-    
-    private final UUID id;
 
-    public static CassandraId timeBased() {
-        return of(UUIDs.timeBased());
-    }
+    private final ACLDTO oldAcl;
+    private final ACLDTO newAcl;
 
-    public static CassandraId of(UUID id) {
-        return new CassandraId(id);
+    @JsonCreator
+    public ACLDiffDTO(@JsonProperty("oldAcl") ACLDTO oldAcl,
+                      @JsonProperty("newAcl") ACLDTO newAcl) {
+        this.oldAcl = oldAcl;
+        this.newAcl = newAcl;
     }
 
-    private CassandraId(UUID id) {
-        this.id = id;
+    @JsonProperty("oldAcl")
+    public ACLDTO getOldAcl() {
+        return oldAcl;
     }
 
-    @Override
-    public String serialize() {
-        return id.toString();
+    @JsonProperty("newAcl")
+    public ACLDTO getNewAcl() {
+        return newAcl;
     }
 
-    public UUID asUuid() {
-        return id;
+    public ACLDiff asACLDiff() {
+        return ACLDiff.computeDiff(
+            oldAcl.asACL(),
+            newAcl.asACL());
     }
 
     @Override
     public final boolean equals(Object o) {
-        if (o instanceof CassandraId) {
-            CassandraId other = (CassandraId) o;
-            return Objects.equals(id, other.id);
+        if (o instanceof ACLDiffDTO) {
+            ACLDiffDTO that = (ACLDiffDTO) o;
+
+            return Objects.equals(this.newAcl, that.newAcl)
+                && Objects.equals(this.oldAcl, that.oldAcl);
         }
         return false;
     }
 
     @Override
     public final int hashCode() {
-        return Objects.hash(id);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-            .add("id", id)
-            .toString();
+        return Objects.hash(newAcl, oldAcl);
     }
 }
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLModule.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLModule.java
new file mode 100644
index 0000000..64b72c7
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLModule.java
@@ -0,0 +1,45 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
+import org.apache.james.json.DTOModule;
+
+public interface ACLModule {
+
+    String RESET_TYPE_NAME = "acl-reseted";
+    String UPDATE_TYPE_NAME = "acl-updated";
+
+    EventDTOModule<ACLReseted, ACLResetedDTO> ACL_RESET =
+        new DTOModule.Builder<>(ACLReseted.class)
+            .convertToDTO(ACLResetedDTO.class)
+            .toDomainObjectConverter(ACLResetedDTO::toEvent)
+            .toDTOConverter(ACLResetedDTO::from)
+            .typeName(RESET_TYPE_NAME)
+            .withFactory(EventDTOModule::new);
+
+    EventDTOModule<ACLUpdated, ACLUpdatedDTO> ACL_UPDATE =
+        new DTOModule.Builder<>(ACLUpdated.class)
+            .convertToDTO(ACLUpdatedDTO.class)
+            .toDomainObjectConverter(ACLUpdatedDTO::toEvent)
+            .toDTOConverter(ACLUpdatedDTO::from)
+            .typeName(UPDATE_TYPE_NAME)
+            .withFactory(EventDTOModule::new);
+}
\ No newline at end of file
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLReseted.java
similarity index 56%
copy from mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
copy to mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLReseted.java
index 8de229c..33ecadc 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLReseted.java
@@ -16,67 +16,60 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-package org.apache.james.mailbox.cassandra.ids;
 
-import java.io.Serializable;
-import java.util.Objects;
-import java.util.UUID;
-
-import org.apache.james.mailbox.model.MailboxId;
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
 
-import com.datastax.driver.core.utils.UUIDs;
-import com.google.common.base.MoreObjects;
+import java.util.Objects;
 
-public class CassandraId implements MailboxId, Serializable {
+import org.apache.james.eventsourcing.AggregateId;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.EventId;
+import org.apache.james.mailbox.acl.ACLDiff;
+import org.apache.james.mailbox.cassandra.ids.CassandraId;
 
-    public static class Factory implements MailboxId.Factory {
-        @Override
-        public CassandraId fromString(String serialized) {
-            return of(UUID.fromString(serialized));
-        }
-    }
-    
-    private final UUID id;
+public class ACLReseted implements Event {
+    private final MailboxAggregateId id;
+    private final EventId eventId;
+    private final ACLDiff aclDiff;
 
-    public static CassandraId timeBased() {
-        return of(UUIDs.timeBased());
+    public ACLReseted(MailboxAggregateId id, EventId eventId, ACLDiff aclDiff) {
+        this.id = id;
+        this.eventId = eventId;
+        this.aclDiff = aclDiff;
     }
 
-    public static CassandraId of(UUID id) {
-        return new CassandraId(id);
+    public CassandraId mailboxId() {
+        return id.asMailboxId();
     }
 
-    private CassandraId(UUID id) {
-        this.id = id;
+    public ACLDiff getAclDiff() {
+        return aclDiff;
     }
 
     @Override
-    public String serialize() {
-        return id.toString();
+    public EventId eventId() {
+        return eventId;
     }
 
-    public UUID asUuid() {
+    @Override
+    public AggregateId getAggregateId() {
         return id;
     }
 
     @Override
     public final boolean equals(Object o) {
-        if (o instanceof CassandraId) {
-            CassandraId other = (CassandraId) o;
-            return Objects.equals(id, other.id);
+        if (o instanceof ACLReseted) {
+            ACLReseted that = (ACLReseted) o;
+
+            return Objects.equals(this.eventId, that.eventId)
+                && Objects.equals(this.id, that.id)
+                && Objects.equals(this.aclDiff, that.aclDiff);
         }
         return false;
     }
 
     @Override
     public final int hashCode() {
-        return Objects.hash(id);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-            .add("id", id)
-            .toString();
+        return Objects.hash(eventId, id, aclDiff);
     }
 }
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLResetedDTO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLResetedDTO.java
new file mode 100644
index 0000000..354d765
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLResetedDTO.java
@@ -0,0 +1,107 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ * http://www.apache.org/licenses/LICENSE-2.0                   *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ***************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import java.util.Objects;
+
+import org.apache.james.eventsourcing.EventId;
+import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
+import org.apache.james.mailbox.cassandra.ids.CassandraId;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Preconditions;
+
+class ACLResetedDTO implements EventDTO {
+
+    static ACLResetedDTO from(ACLReseted event, String type) {
+        Preconditions.checkNotNull(event);
+
+        return new ACLResetedDTO(
+                event.eventId().serialize(),
+                event.getAggregateId().asAggregateKey(),
+                type,
+                ACLDiffDTO.fromACLDiff(event.getAclDiff()));
+    }
+
+    static ACLResetedDTO from(ACLReseted event) {
+        return from(event, ACLModule.RESET_TYPE_NAME);
+    }
+
+    private final int eventId;
+    private final String aggregateKey;
+    private final String type;
+    private final ACLDiffDTO aclDiff;
+
+    @JsonCreator
+    ACLResetedDTO(
+            @JsonProperty("eventId") int eventId,
+            @JsonProperty("aggregateKey") String aggregateKey,
+            @JsonProperty("type") String type,
+            @JsonProperty("aclDiff") ACLDiffDTO aclDiff) {
+        this.eventId = eventId;
+        this.aggregateKey = aggregateKey;
+        this.type = type;
+        this.aclDiff = aclDiff;
+    }
+
+    @JsonIgnore
+    public ACLReseted toEvent() {
+        return new ACLReseted(
+            new MailboxAggregateId(CassandraId.of(aggregateKey)),
+            EventId.fromSerialized(eventId),
+            aclDiff.asACLDiff());
+    }
+
+    public int getEventId() {
+        return eventId;
+    }
+
+    public String getAggregateKey() {
+        return aggregateKey;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public ACLDiffDTO getAclDiff() {
+        return aclDiff;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof ACLResetedDTO) {
+            ACLResetedDTO that = (ACLResetedDTO) o;
+
+            return Objects.equals(this.eventId, that.eventId)
+                && Objects.equals(this.aggregateKey, that.aggregateKey)
+                && Objects.equals(this.type, that.type)
+                && Objects.equals(this.aclDiff, that.aclDiff);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(eventId, aggregateKey, type, aclDiff);
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLUpdated.java
similarity index 50%
copy from mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
copy to mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLUpdated.java
index 8de229c..604209c 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLUpdated.java
@@ -16,67 +16,68 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-package org.apache.james.mailbox.cassandra.ids;
 
-import java.io.Serializable;
-import java.util.Objects;
-import java.util.UUID;
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
 
-import org.apache.james.mailbox.model.MailboxId;
+import java.util.Objects;
 
-import com.datastax.driver.core.utils.UUIDs;
-import com.google.common.base.MoreObjects;
+import org.apache.james.eventsourcing.AggregateId;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.EventId;
+import org.apache.james.mailbox.acl.ACLDiff;
+import org.apache.james.mailbox.cassandra.ids.CassandraId;
+import org.apache.james.mailbox.model.MailboxACL;
 
-public class CassandraId implements MailboxId, Serializable {
+public class ACLUpdated implements Event {
+    private final MailboxAggregateId id;
+    private final EventId eventId;
+    private final MailboxACL.ACLCommand command;
+    private final ACLDiff aclDiff;
 
-    public static class Factory implements MailboxId.Factory {
-        @Override
-        public CassandraId fromString(String serialized) {
-            return of(UUID.fromString(serialized));
-        }
+    public ACLUpdated(MailboxAggregateId id, EventId eventId, MailboxACL.ACLCommand command, ACLDiff aclDiff) {
+        this.id = id;
+        this.eventId = eventId;
+        this.command = command;
+        this.aclDiff = aclDiff;
     }
-    
-    private final UUID id;
 
-    public static CassandraId timeBased() {
-        return of(UUIDs.timeBased());
+    public CassandraId mailboxId() {
+        return id.asMailboxId();
     }
 
-    public static CassandraId of(UUID id) {
-        return new CassandraId(id);
+    @Override
+    public EventId eventId() {
+        return eventId;
     }
 
-    private CassandraId(UUID id) {
-        this.id = id;
+    @Override
+    public AggregateId getAggregateId() {
+        return id;
     }
 
-    @Override
-    public String serialize() {
-        return id.toString();
+    public ACLDiff getAclDiff() {
+        return aclDiff;
     }
 
-    public UUID asUuid() {
-        return id;
+    public MailboxACL.ACLCommand getCommand() {
+        return command;
     }
 
     @Override
     public final boolean equals(Object o) {
-        if (o instanceof CassandraId) {
-            CassandraId other = (CassandraId) o;
-            return Objects.equals(id, other.id);
+        if (o instanceof ACLUpdated) {
+            ACLUpdated that = (ACLUpdated) o;
+
+            return Objects.equals(this.eventId, that.eventId)
+                && Objects.equals(this.id, that.id)
+                && Objects.equals(this.command, that.command)
+                && Objects.equals(this.aclDiff, that.aclDiff);
         }
         return false;
     }
 
     @Override
     public final int hashCode() {
-        return Objects.hash(id);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-            .add("id", id)
-            .toString();
+        return Objects.hash(eventId, id, aclDiff, command);
     }
 }
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLUpdatedDTO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLUpdatedDTO.java
new file mode 100644
index 0000000..8870745
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/ACLUpdatedDTO.java
@@ -0,0 +1,116 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ * http://www.apache.org/licenses/LICENSE-2.0                   *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ***************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import java.util.Objects;
+
+import org.apache.james.eventsourcing.EventId;
+import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
+import org.apache.james.mailbox.cassandra.ids.CassandraId;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Preconditions;
+
+class ACLUpdatedDTO implements EventDTO {
+
+    static ACLUpdatedDTO from(ACLUpdated event, String type) {
+        Preconditions.checkNotNull(event);
+
+        return new ACLUpdatedDTO(
+                event.eventId().serialize(),
+                event.getAggregateId().asAggregateKey(),
+                type,
+                ACLDiffDTO.fromACLDiff(event.getAclDiff()),
+                ACLCommandDTO.fromCommand(event.getCommand()));
+    }
+
+    static ACLUpdatedDTO from(ACLUpdated event) {
+        return from(event, ACLModule.UPDATE_TYPE_NAME);
+    }
+
+    private final int eventId;
+    private final String aggregateKey;
+    private final String type;
+    private final ACLDiffDTO aclDiff;
+    private final ACLCommandDTO command;
+
+    @JsonCreator
+    ACLUpdatedDTO(@JsonProperty("eventId") int eventId,
+                  @JsonProperty("aggregateKey") String aggregateKey,
+                  @JsonProperty("type") String type,
+                  @JsonProperty("aclDiff") ACLDiffDTO aclDiff,
+                  @JsonProperty("command") ACLCommandDTO command) {
+        this.eventId = eventId;
+        this.aggregateKey = aggregateKey;
+        this.type = type;
+        this.aclDiff = aclDiff;
+        this.command = command;
+    }
+
+    @JsonIgnore
+    public ACLUpdated toEvent() {
+        return new ACLUpdated(
+            new MailboxAggregateId(CassandraId.of(aggregateKey)),
+            EventId.fromSerialized(eventId),
+            command.asACLCommand(),
+            aclDiff.asACLDiff());
+    }
+
+    public int getEventId() {
+        return eventId;
+    }
+
+    public String getAggregateKey() {
+        return aggregateKey;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public ACLDiffDTO getAclDiff() {
+        return aclDiff;
+    }
+
+    public ACLCommandDTO getCommand() {
+        return command;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof ACLUpdatedDTO) {
+            ACLUpdatedDTO that = (ACLUpdatedDTO) o;
+
+            return Objects.equals(this.eventId, that.eventId)
+                && Objects.equals(this.aggregateKey, that.aggregateKey)
+                && Objects.equals(this.type, that.type)
+                && Objects.equals(this.command, that.command)
+                && Objects.equals(this.aclDiff, that.aclDiff);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(eventId, aggregateKey, type, aclDiff, command);
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/AclV2DAOSubscriber.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/AclV2DAOSubscriber.java
new file mode 100644
index 0000000..be41fa9
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/AclV2DAOSubscriber.java
@@ -0,0 +1,46 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.Subscriber;
+import org.apache.james.mailbox.cassandra.mail.CassandraACLDAOV2;
+
+public class AclV2DAOSubscriber implements Subscriber {
+    private final CassandraACLDAOV2 acldaov2;
+
+    public AclV2DAOSubscriber(CassandraACLDAOV2 acldaov2) {
+        this.acldaov2 = acldaov2;
+    }
+
+    @Override
+    public void handle(Event event) {
+        if (event instanceof ACLReseted) {
+            ACLReseted aclReseted = (ACLReseted) event;
+            acldaov2.setACL(aclReseted.mailboxId(), aclReseted.getAclDiff().getNewACL())
+                .block();
+        }
+        if (event instanceof ACLUpdated) {
+            ACLUpdated aclUpdated = (ACLUpdated) event;
+            acldaov2.updateACL(aclUpdated.mailboxId(), aclUpdated.getCommand())
+                .block();
+        }
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/DeleteMailboxCommand.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/DeleteMailboxCommand.java
new file mode 100644
index 0000000..958a86e
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/DeleteMailboxCommand.java
@@ -0,0 +1,61 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import java.util.List;
+
+import org.apache.james.eventsourcing.Command;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.eventstore.EventStore;
+import org.reactivestreams.Publisher;
+
+import reactor.core.publisher.Mono;
+
+public class DeleteMailboxCommand implements Command {
+    public static class CommandHandler implements org.apache.james.eventsourcing.CommandHandler<DeleteMailboxCommand> {
+        private final EventStore eventStore;
+
+        public CommandHandler(EventStore eventStore) {
+            this.eventStore = eventStore;
+        }
+
+        @Override
+        public Class<DeleteMailboxCommand> handledClass() {
+            return DeleteMailboxCommand.class;
+        }
+
+        @Override
+        public Publisher<List<? extends Event>> handle(DeleteMailboxCommand command) {
+            return Mono.from(eventStore.getEventsOfAggregate(command.getId()))
+                .map(history -> MailboxACLAggregate.load(command.getId(), history))
+                .map(aggregate -> aggregate.deleteMailbox());
+        }
+    }
+
+    private final MailboxAggregateId id;
+
+    public DeleteMailboxCommand(MailboxAggregateId id) {
+        this.id = id;
+    }
+
+    public MailboxAggregateId getId() {
+        return id;
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/MailboxACLAggregate.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/MailboxACLAggregate.java
new file mode 100644
index 0000000..485d0d2
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/MailboxACLAggregate.java
@@ -0,0 +1,100 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.eventstore.History;
+import org.apache.james.mailbox.acl.ACLDiff;
+import org.apache.james.mailbox.exception.UnsupportedRightException;
+import org.apache.james.mailbox.model.MailboxACL;
+
+import com.google.common.collect.ImmutableList;
+
+public class MailboxACLAggregate {
+
+    private static class State {
+        static State initial() {
+            return new State(Optional.empty());
+        }
+
+        static State forAcl(MailboxACL acl) {
+            return new State(Optional.of(acl));
+        }
+
+        private final Optional<MailboxACL> acl;
+
+        private State(Optional<MailboxACL> acl) {
+            this.acl = acl;
+        }
+    }
+
+    public static MailboxACLAggregate load(MailboxAggregateId aggregateId, History history) {
+        return new MailboxACLAggregate(aggregateId, history);
+    }
+
+    private final MailboxAggregateId aggregateId;
+    private final History history;
+    private State state;
+
+    public MailboxACLAggregate(MailboxAggregateId aggregateId, History history) {
+        this.aggregateId = aggregateId;
+        this.history = history;
+
+        this.state = State.initial();
+        history.getEventsJava()
+            .forEach(this::apply);
+    }
+
+    public List<Event> deleteMailbox() {
+        return ImmutableList.of(new ACLReseted(aggregateId, history.getNextEventId(),
+            ACLDiff.computeDiff(state.acl.orElse(MailboxACL.EMPTY), MailboxACL.EMPTY)));
+    }
+
+    public List<Event> set(SetACLCommand setACLCommand) {
+        return ImmutableList.of(new ACLReseted(aggregateId, history.getNextEventId(),
+            ACLDiff.computeDiff(state.acl.orElse(MailboxACL.EMPTY), setACLCommand.getAcl())));
+    }
+
+    public List<Event> update(UpdateACLCommand command) throws UnsupportedRightException {
+        MailboxACL oldACL = state.acl.orElse(MailboxACL.EMPTY);
+        return ImmutableList.of(new ACLUpdated(command.getId(), history.getNextEventId(), command.getAclCommand(),
+            ACLDiff.computeDiff(oldACL,
+                oldACL.apply(command.getAclCommand()))));
+    }
+
+    private void apply(Event event) {
+        if (event instanceof ACLReseted) {
+            ACLReseted aclReseted = (ACLReseted) event;
+            MailboxACL newACL = aclReseted.getAclDiff().getNewACL();
+            if (newACL.getEntries().isEmpty()) {
+                state = State.initial();
+            } else {
+                state = State.forAcl(newACL);
+            }
+        }
+        if (event instanceof ACLUpdated) {
+            ACLUpdated aclUpdated = (ACLUpdated) event;
+            state = State.forAcl(aclUpdated.getAclDiff().getNewACL());
+        }
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/MailboxAggregateId.java
similarity index 53%
copy from mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
copy to mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/MailboxAggregateId.java
index 8de229c..067f9bc 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/ids/CassandraId.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/MailboxAggregateId.java
@@ -16,67 +16,42 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-package org.apache.james.mailbox.cassandra.ids;
 
-import java.io.Serializable;
-import java.util.Objects;
-import java.util.UUID;
-
-import org.apache.james.mailbox.model.MailboxId;
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
 
-import com.datastax.driver.core.utils.UUIDs;
-import com.google.common.base.MoreObjects;
+import java.util.Objects;
 
-public class CassandraId implements MailboxId, Serializable {
+import org.apache.james.eventsourcing.AggregateId;
+import org.apache.james.mailbox.cassandra.ids.CassandraId;
 
-    public static class Factory implements MailboxId.Factory {
-        @Override
-        public CassandraId fromString(String serialized) {
-            return of(UUID.fromString(serialized));
-        }
-    }
-    
-    private final UUID id;
-
-    public static CassandraId timeBased() {
-        return of(UUIDs.timeBased());
-    }
+public class MailboxAggregateId implements AggregateId {
+    private final CassandraId cassandraId;
 
-    public static CassandraId of(UUID id) {
-        return new CassandraId(id);
+    public MailboxAggregateId(CassandraId cassandraId) {
+        this.cassandraId = cassandraId;
     }
 
-    private CassandraId(UUID id) {
-        this.id = id;
+    public CassandraId asMailboxId() {
+        return cassandraId;
     }
 
     @Override
-    public String serialize() {
-        return id.toString();
-    }
-
-    public UUID asUuid() {
-        return id;
+    public String asAggregateKey() {
+        return cassandraId.serialize();
     }
 
     @Override
     public final boolean equals(Object o) {
-        if (o instanceof CassandraId) {
-            CassandraId other = (CassandraId) o;
-            return Objects.equals(id, other.id);
+        if (o instanceof MailboxAggregateId) {
+            MailboxAggregateId that = (MailboxAggregateId) o;
+
+            return Objects.equals(this.cassandraId, that.cassandraId);
         }
         return false;
     }
 
     @Override
     public final int hashCode() {
-        return Objects.hash(id);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-            .add("id", id)
-            .toString();
+        return Objects.hash(cassandraId);
     }
 }
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/SetACLCommand.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/SetACLCommand.java
new file mode 100644
index 0000000..8b797f5
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/SetACLCommand.java
@@ -0,0 +1,68 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import java.util.List;
+
+import org.apache.james.eventsourcing.Command;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.eventstore.EventStore;
+import org.apache.james.mailbox.model.MailboxACL;
+import org.reactivestreams.Publisher;
+
+import reactor.core.publisher.Mono;
+
+public class SetACLCommand implements Command {
+    public static class CommandHandler implements org.apache.james.eventsourcing.CommandHandler<SetACLCommand> {
+        private final EventStore eventStore;
+
+        public CommandHandler(EventStore eventStore) {
+            this.eventStore = eventStore;
+        }
+
+        @Override
+        public Class<SetACLCommand> handledClass() {
+            return SetACLCommand.class;
+        }
+
+        @Override
+        public Publisher<List<? extends Event>> handle(SetACLCommand command) {
+            return Mono.from(eventStore.getEventsOfAggregate(command.getId()))
+                .map(history -> MailboxACLAggregate.load(command.getId(), history))
+                .map(aggregate -> aggregate.set(command));
+        }
+    }
+
+    private final MailboxAggregateId id;
+    private final MailboxACL acl;
+
+    public SetACLCommand(MailboxAggregateId id, MailboxACL acl) {
+        this.id = id;
+        this.acl = acl;
+    }
+
+    public MailboxAggregateId getId() {
+        return id;
+    }
+
+    public MailboxACL getAcl() {
+        return acl;
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/UpdateACLCommand.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/UpdateACLCommand.java
new file mode 100644
index 0000000..607657f
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/UpdateACLCommand.java
@@ -0,0 +1,70 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import java.util.List;
+
+import org.apache.james.eventsourcing.Command;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.eventstore.EventStore;
+import org.apache.james.mailbox.model.MailboxACL;
+import org.reactivestreams.Publisher;
+
+import com.github.fge.lambdas.Throwing;
+
+import reactor.core.publisher.Mono;
+
+public class UpdateACLCommand implements Command {
+    public static class CommandHandler implements org.apache.james.eventsourcing.CommandHandler<UpdateACLCommand> {
+        private final EventStore eventStore;
+
+        public CommandHandler(EventStore eventStore) {
+            this.eventStore = eventStore;
+        }
+
+        @Override
+        public Class<UpdateACLCommand> handledClass() {
+            return UpdateACLCommand.class;
+        }
+
+        @Override
+        public Publisher<List<? extends Event>> handle(UpdateACLCommand command) {
+            return Mono.from(eventStore.getEventsOfAggregate(command.getId()))
+                .map(history -> MailboxACLAggregate.load(command.getId(), history))
+                .map(Throwing.function(aggregate -> aggregate.update(command)));
+        }
+    }
+
+    private final MailboxAggregateId id;
+    private final MailboxACL.ACLCommand aclCommand;
+
+    public UpdateACLCommand(MailboxAggregateId id, MailboxACL.ACLCommand aclCommand) {
+        this.id = id;
+        this.aclCommand = aclCommand;
+    }
+
+    public MailboxAggregateId getId() {
+        return id;
+    }
+
+    public MailboxACL.ACLCommand getAclCommand() {
+        return aclCommand;
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/UserRightsDAOSubscriber.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/UserRightsDAOSubscriber.java
new file mode 100644
index 0000000..3566b6a
--- /dev/null
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/eventsourcing/acl/UserRightsDAOSubscriber.java
@@ -0,0 +1,46 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.cassandra.mail.eventsourcing.acl;
+
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.Subscriber;
+import org.apache.james.mailbox.cassandra.mail.CassandraUserMailboxRightsDAO;
+
+public class UserRightsDAOSubscriber implements Subscriber {
+    private final CassandraUserMailboxRightsDAO userRightsDAO;
+
+    public UserRightsDAOSubscriber(CassandraUserMailboxRightsDAO userRightsDAO) {
+        this.userRightsDAO = userRightsDAO;
+    }
+
+    @Override
+    public void handle(Event event) {
+        if (event instanceof ACLReseted) {
+            ACLReseted aclReseted = (ACLReseted) event;
+            userRightsDAO.update(aclReseted.mailboxId(), aclReseted.getAclDiff())
+                .block();
+        }
+        if (event instanceof ACLUpdated) {
+            ACLUpdated aclUpdated = (ACLUpdated) event;
+            userRightsDAO.update(aclUpdated.mailboxId(), aclUpdated.getAclDiff())
+                .block();
+        }
+    }
+}
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AclV2Migration.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AclV2Migration.java
index 9d6c7df..6dc1b1b 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AclV2Migration.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/migration/AclV2Migration.java
@@ -27,8 +27,7 @@ import javax.inject.Inject;
 
 import org.apache.james.backends.cassandra.migration.Migration;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
-import org.apache.james.mailbox.cassandra.mail.CassandraACLDAOV1;
-import org.apache.james.mailbox.cassandra.mail.CassandraACLDAOV2;
+import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxDAO;
 import org.apache.james.task.Task;
 import org.apache.james.task.TaskExecutionDetails;
@@ -81,14 +80,14 @@ public class AclV2Migration implements Migration {
     public static final TaskType TYPE = TaskType.of("acl-v2-migration");
 
     private final CassandraMailboxDAO mailboxDAO;
-    private final CassandraACLDAOV1 daoV1;
-    private final CassandraACLDAOV2 daoV2;
+    private final CassandraACLMapper.StoreV1 storeV1;
+    private final CassandraACLMapper.StoreV2 storeV2;
 
     @Inject
-    public AclV2Migration(CassandraMailboxDAO mailboxDAO, CassandraACLDAOV1 daoV1, CassandraACLDAOV2 daoV2) {
+    public AclV2Migration(CassandraMailboxDAO mailboxDAO, CassandraACLMapper.StoreV1 storeV1, CassandraACLMapper.StoreV2 storeV2) {
         this.mailboxDAO = mailboxDAO;
-        this.daoV1 = daoV1;
-        this.daoV2 = daoV2;
+        this.storeV1 = storeV1;
+        this.storeV2 = storeV2;
     }
 
     @Override
@@ -96,8 +95,8 @@ public class AclV2Migration implements Migration {
         mailboxDAO.retrieveAllMailboxes()
             .flatMap(mailbox -> {
                 CassandraId id = (CassandraId) mailbox.getMailboxId();
-                return daoV1.getACL(id)
-                    .flatMap(acl -> daoV2.doSetACL(id, acl));
+                return storeV1.getACL(id)
+                    .flatMap(acl -> storeV2.setACL(id, acl));
             }, CONCURRENCY)
             .doOnError(t -> LOGGER.error("Error while performing migration", t))
             .subscribeOn(Schedulers.elastic())
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
index f1aa8b2..84dd5b1 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
@@ -32,6 +32,7 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
+import org.apache.james.backends.cassandra.init.configuration.CassandraConsistenciesConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
@@ -39,6 +40,9 @@ import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.cassandra.BlobTables;
 import org.apache.james.core.Username;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStore;
+import org.apache.james.eventsourcing.eventstore.cassandra.EventStoreDao;
+import org.apache.james.eventsourcing.eventstore.cassandra.JsonEventSerializer;
 import org.apache.james.mailbox.MailboxManagerTest;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
@@ -62,6 +66,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraUserMailboxRightsDAO;
 import org.apache.james.mailbox.cassandra.mail.MailboxAggregateModule;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLModule;
 import org.apache.james.mailbox.events.EventBus;
 import org.apache.james.mailbox.model.AttachmentId;
 import org.apache.james.mailbox.model.FetchGroup;
@@ -791,13 +796,19 @@ public class CassandraMailboxManagerTest extends MailboxManagerTest<CassandraMai
         }
 
         private CassandraACLMapper aclMapper(CassandraCluster cassandraCluster) {
+            CassandraSchemaVersionDAO schemaVersionDAO = new CassandraSchemaVersionDAO(cassandraCluster.getConf());
+            CassandraSchemaVersionManager versionManager = new CassandraSchemaVersionManager(schemaVersionDAO);
+            CassandraACLDAOV1 aclDAOV1 = new CassandraACLDAOV1(cassandraCluster.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION, CassandraConsistenciesConfiguration.DEFAULT);
+            CassandraACLDAOV2 aclDAOv2 = new CassandraACLDAOV2(cassandraCluster.getConf());
+            JsonEventSerializer jsonEventSerializer = JsonEventSerializer
+                .forModules(ACLModule.ACL_RESET, ACLModule.ACL_UPDATE)
+                .withoutNestedType();
+            CassandraUserMailboxRightsDAO usersRightDAO = new CassandraUserMailboxRightsDAO(cassandraCluster.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
+            CassandraEventStore eventStore = new CassandraEventStore(new EventStoreDao(cassandraCluster.getConf(), jsonEventSerializer, CassandraConsistenciesConfiguration.DEFAULT));
             return new CassandraACLMapper(
-                rightsDAO(cassandraCluster),
-                new CassandraACLDAOV1(cassandraCluster.getConf(),
-                    CassandraConfiguration.DEFAULT_CONFIGURATION,
-                    cassandra.getCassandraConsistenciesConfiguration()),
-                new CassandraACLDAOV2(cassandraCluster.getConf()),
-                new CassandraSchemaVersionManager(new CassandraSchemaVersionDAO(cassandraCluster.getConf())));
+                new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1),
+                new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore),
+                versionManager);
         }
 
         private CassandraUserMailboxRightsDAO rightsDAO(CassandraCluster cassandraCluster) {
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV1Test.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV1Test.java
index 7cfa3e5..1d52765 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV1Test.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV1Test.java
@@ -39,6 +39,11 @@ import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStore;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
+import org.apache.james.eventsourcing.eventstore.cassandra.EventStoreDao;
+import org.apache.james.eventsourcing.eventstore.cassandra.JsonEventSerializer;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.table.CassandraACLTable;
 import org.apache.james.mailbox.model.MailboxACL;
@@ -49,7 +54,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class CassandraACLMapperV1Test extends CassandraACLMapperContract {
     @RegisterExtension
     static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(
-        CassandraModule.aggregateModules(CassandraAclModule.MODULE, CassandraSchemaVersionModule.MODULE));
+        CassandraModule.aggregateModules(CassandraAclModule.MODULE, CassandraSchemaVersionModule.MODULE, CassandraEventStoreModule.MODULE()));
 
     private CassandraACLMapper cassandraACLMapper;
 
@@ -59,10 +64,16 @@ class CassandraACLMapperV1Test extends CassandraACLMapperContract {
         schemaVersionDAO.truncateVersion().block();
         schemaVersionDAO.updateVersion(new SchemaVersion(9)).block();
         CassandraSchemaVersionManager versionManager = new CassandraSchemaVersionManager(schemaVersionDAO);
-        cassandraACLMapper =  new CassandraACLMapper(
-            new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION),
-            new CassandraACLDAOV1(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION, CassandraConsistenciesConfiguration.DEFAULT),
-            new CassandraACLDAOV2(cassandra.getConf()),
+        CassandraACLDAOV1 aclDAOV1 = new CassandraACLDAOV1(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION, CassandraConsistenciesConfiguration.DEFAULT);
+        CassandraACLDAOV2 aclDAOv2 = new CassandraACLDAOV2(cassandra.getConf());
+        JsonEventSerializer jsonEventSerializer = JsonEventSerializer
+            .forModules(ACLModule.ACL_RESET, ACLModule.ACL_UPDATE)
+            .withoutNestedType();
+        CassandraUserMailboxRightsDAO usersRightDAO = new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
+        CassandraEventStore eventStore = new CassandraEventStore(new EventStoreDao(cassandra.getConf(), jsonEventSerializer, CassandraConsistenciesConfiguration.DEFAULT));
+        cassandraACLMapper = new CassandraACLMapper(
+            new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1),
+            new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore),
             versionManager);
     }
 
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java
index f6f8cef..a1367f1 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraACLMapperV2Test.java
@@ -38,6 +38,11 @@ import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStore;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
+import org.apache.james.eventsourcing.eventstore.cassandra.EventStoreDao;
+import org.apache.james.eventsourcing.eventstore.cassandra.JsonEventSerializer;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.model.MailboxACL;
 import org.junit.jupiter.api.BeforeEach;
@@ -47,7 +52,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class CassandraACLMapperV2Test extends CassandraACLMapperContract {
     @RegisterExtension
     static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(
-        CassandraModule.aggregateModules(CassandraAclModule.MODULE, CassandraSchemaVersionModule.MODULE));
+        CassandraModule.aggregateModules(CassandraAclModule.MODULE, CassandraSchemaVersionModule.MODULE, CassandraEventStoreModule.MODULE()));
 
     private CassandraACLMapper cassandraACLMapper;
 
@@ -58,10 +63,16 @@ class CassandraACLMapperV2Test extends CassandraACLMapperContract {
         schemaVersionDAO.truncateVersion().block();
         schemaVersionDAO.updateVersion(new SchemaVersion(10)).block();
         CassandraSchemaVersionManager versionManager = new CassandraSchemaVersionManager(schemaVersionDAO);
-        cassandraACLMapper =  new CassandraACLMapper(
-            new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION),
-            new CassandraACLDAOV1(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION, CassandraConsistenciesConfiguration.DEFAULT),
-            new CassandraACLDAOV2(cassandra.getConf()),
+        CassandraACLDAOV1 aclDAOV1 = new CassandraACLDAOV1(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION, CassandraConsistenciesConfiguration.DEFAULT);
+        CassandraACLDAOV2 aclDAOv2 = new CassandraACLDAOV2(cassandra.getConf());
+        JsonEventSerializer jsonEventSerializer = JsonEventSerializer
+            .forModules(ACLModule.ACL_RESET, ACLModule.ACL_UPDATE)
+            .withoutNestedType();
+        CassandraUserMailboxRightsDAO usersRightDAO = new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
+        CassandraEventStore eventStore = new CassandraEventStore(new EventStoreDao(cassandra.getConf(), jsonEventSerializer, CassandraConsistenciesConfiguration.DEFAULT));
+        cassandraACLMapper = new CassandraACLMapper(
+            new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1),
+            new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore),
             versionManager);
     }
 
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperAclTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperAclTest.java
index 119b715..245205e 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperAclTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperAclTest.java
@@ -23,6 +23,7 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
 import org.apache.james.mailbox.cassandra.mail.utils.GuiceUtils;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
@@ -33,6 +34,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 class CassandraMailboxMapperAclTest extends MailboxMapperACLTest {
 
     private static final CassandraModule MODULES = CassandraModule.aggregateModules(
+        CassandraEventStoreModule.MODULE(),
         CassandraSchemaVersionModule.MODULE,
         CassandraAclModule.MODULE,
         CassandraMailboxModule.MODULE,
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
index 678dd69..b2b5caa 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
@@ -33,13 +33,19 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.Scenario;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
+import org.apache.james.backends.cassandra.init.configuration.CassandraConsistenciesConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
 import org.apache.james.core.Username;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStore;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
+import org.apache.james.eventsourcing.eventstore.cassandra.EventStoreDao;
+import org.apache.james.eventsourcing.eventstore.cassandra.JsonEventSerializer;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
@@ -78,9 +84,10 @@ class CassandraMailboxMapperTest {
     private static final Mailbox MAILBOX_BIS = new Mailbox(MAILBOX_PATH, UID_VALIDITY, MAILBOX_ID_2);
 
     private static final CassandraModule MODULES = CassandraModule.aggregateModules(
+        CassandraAclModule.MODULE,
+        CassandraEventStoreModule.MODULE(),
         CassandraMailboxModule.MODULE,
-        CassandraSchemaVersionModule.MODULE,
-        CassandraAclModule.MODULE);
+        CassandraSchemaVersionModule.MODULE);
     private static final int TRY_COUNT_BEFORE_FAILURE = 6;
 
     @RegisterExtension
@@ -100,28 +107,32 @@ class CassandraMailboxMapperTest {
         mailboxPathDAO = new CassandraMailboxPathDAOImpl(cassandra.getConf(), cassandra.getTypesProvider(), cassandraCluster.getCassandraConsistenciesConfiguration());
         mailboxPathV2DAO = new CassandraMailboxPathV2DAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION, cassandraCluster.getCassandraConsistenciesConfiguration());
         mailboxPathV3DAO = new CassandraMailboxPathV3DAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION, cassandraCluster.getCassandraConsistenciesConfiguration());
-        CassandraUserMailboxRightsDAO userMailboxRightsDAO = new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
-        CassandraACLMapper aclMapper = new CassandraACLMapper(
-            new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION),
-            new CassandraACLDAOV1(cassandra.getConf(),
-                CassandraConfiguration.DEFAULT_CONFIGURATION,
-                cassandraCluster.getCassandraConsistenciesConfiguration()),
-            new CassandraACLDAOV2(cassandra.getConf()),
-            new CassandraSchemaVersionManager(new CassandraSchemaVersionDAO(cassandra.getConf())));
-        versionDAO = new CassandraSchemaVersionDAO(cassandra.getConf());
 
+        versionDAO = new CassandraSchemaVersionDAO(cassandra.getConf());
         versionDAO.truncateVersion()
             .then(versionDAO.updateVersion(new SchemaVersion(7)))
             .block();
-
+        CassandraSchemaVersionManager versionManager = new CassandraSchemaVersionManager(versionDAO);
+
+        CassandraACLDAOV1 aclDAOV1 = new CassandraACLDAOV1(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION, CassandraConsistenciesConfiguration.DEFAULT);
+        CassandraACLDAOV2 aclDAOv2 = new CassandraACLDAOV2(cassandra.getConf());
+        JsonEventSerializer jsonEventSerializer = JsonEventSerializer
+            .forModules(ACLModule.ACL_RESET, ACLModule.ACL_UPDATE)
+            .withoutNestedType();
+        CassandraUserMailboxRightsDAO usersRightDAO = new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
+        CassandraEventStore eventStore = new CassandraEventStore(new EventStoreDao(cassandra.getConf(), jsonEventSerializer, CassandraConsistenciesConfiguration.DEFAULT));
+        CassandraACLMapper aclMapper = new CassandraACLMapper(
+            new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1),
+            new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore),
+            versionManager);
         testee = new CassandraMailboxMapper(
             mailboxDAO,
             mailboxPathDAO,
             mailboxPathV2DAO,
             mailboxPathV3DAO,
-            userMailboxRightsDAO,
+            usersRightDAO,
             aclMapper,
-            new CassandraSchemaVersionManager(versionDAO),
+            versionManager,
             CassandraConfiguration.DEFAULT_CONFIGURATION);
     }
 
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperV10Test.java
similarity index 88%
copy from mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
copy to mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperV10Test.java
index 678dd69..6c70f72 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperV10Test.java
@@ -33,13 +33,19 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.Scenario;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
+import org.apache.james.backends.cassandra.init.configuration.CassandraConsistenciesConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
 import org.apache.james.core.Username;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStore;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
+import org.apache.james.eventsourcing.eventstore.cassandra.EventStoreDao;
+import org.apache.james.eventsourcing.eventstore.cassandra.JsonEventSerializer;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
@@ -64,7 +70,7 @@ import com.github.fge.lambdas.runnable.ThrowingRunnable;
 
 import reactor.core.publisher.Mono;
 
-class CassandraMailboxMapperTest {
+class CassandraMailboxMapperV10Test {
     private static final UidValidity UID_VALIDITY = UidValidity.of(52);
     private static final Username USER = Username.of("user");
     private static final CassandraId MAILBOX_ID = CassandraId.timeBased();
@@ -78,9 +84,10 @@ class CassandraMailboxMapperTest {
     private static final Mailbox MAILBOX_BIS = new Mailbox(MAILBOX_PATH, UID_VALIDITY, MAILBOX_ID_2);
 
     private static final CassandraModule MODULES = CassandraModule.aggregateModules(
+        CassandraAclModule.MODULE,
+        CassandraEventStoreModule.MODULE(),
         CassandraMailboxModule.MODULE,
-        CassandraSchemaVersionModule.MODULE,
-        CassandraAclModule.MODULE);
+        CassandraSchemaVersionModule.MODULE);
     private static final int TRY_COUNT_BEFORE_FAILURE = 6;
 
     @RegisterExtension
@@ -100,28 +107,32 @@ class CassandraMailboxMapperTest {
         mailboxPathDAO = new CassandraMailboxPathDAOImpl(cassandra.getConf(), cassandra.getTypesProvider(), cassandraCluster.getCassandraConsistenciesConfiguration());
         mailboxPathV2DAO = new CassandraMailboxPathV2DAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION, cassandraCluster.getCassandraConsistenciesConfiguration());
         mailboxPathV3DAO = new CassandraMailboxPathV3DAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION, cassandraCluster.getCassandraConsistenciesConfiguration());
-        CassandraUserMailboxRightsDAO userMailboxRightsDAO = new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
-        CassandraACLMapper aclMapper = new CassandraACLMapper(
-            new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION),
-            new CassandraACLDAOV1(cassandra.getConf(),
-                CassandraConfiguration.DEFAULT_CONFIGURATION,
-                cassandraCluster.getCassandraConsistenciesConfiguration()),
-            new CassandraACLDAOV2(cassandra.getConf()),
-            new CassandraSchemaVersionManager(new CassandraSchemaVersionDAO(cassandra.getConf())));
-        versionDAO = new CassandraSchemaVersionDAO(cassandra.getConf());
 
+        versionDAO = new CassandraSchemaVersionDAO(cassandra.getConf());
         versionDAO.truncateVersion()
-            .then(versionDAO.updateVersion(new SchemaVersion(7)))
+            .then(versionDAO.updateVersion(new SchemaVersion(10)))
             .block();
+        CassandraSchemaVersionManager versionManager = new CassandraSchemaVersionManager(versionDAO);
 
+        CassandraACLDAOV1 aclDAOV1 = new CassandraACLDAOV1(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION, CassandraConsistenciesConfiguration.DEFAULT);
+        CassandraACLDAOV2 aclDAOv2 = new CassandraACLDAOV2(cassandra.getConf());
+        JsonEventSerializer jsonEventSerializer = JsonEventSerializer
+            .forModules(ACLModule.ACL_RESET, ACLModule.ACL_UPDATE)
+            .withoutNestedType();
+        CassandraUserMailboxRightsDAO usersRightDAO = new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
+        CassandraEventStore eventStore = new CassandraEventStore(new EventStoreDao(cassandra.getConf(), jsonEventSerializer, CassandraConsistenciesConfiguration.DEFAULT));
+        CassandraACLMapper aclMapper = new CassandraACLMapper(
+            new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1),
+            new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOv2, eventStore),
+            versionManager);
         testee = new CassandraMailboxMapper(
             mailboxDAO,
             mailboxPathDAO,
             mailboxPathV2DAO,
             mailboxPathV3DAO,
-            userMailboxRightsDAO,
+            usersRightDAO,
             aclMapper,
-            new CassandraSchemaVersionManager(versionDAO),
+            versionManager,
             CassandraConfiguration.DEFAULT_CONFIGURATION);
     }
 
@@ -799,23 +810,6 @@ class CassandraMailboxMapperTest {
     }
 
     @Test
-    void deleteShouldDeleteMailboxAndMailboxPathFromAllTables() {
-        mailboxDAO.save(MAILBOX)
-            .block();
-        mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-        mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-        mailboxPathV3DAO.save(MAILBOX)
-            .block();
-
-        testee.delete(MAILBOX).block();
-
-        assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
-            .isEmpty();
-    }
-
-    @Test
     void findMailboxByPathShouldReturnMailboxWhenExistsInV1Table() {
         mailboxDAO.save(MAILBOX)
             .block();
@@ -920,62 +914,6 @@ class CassandraMailboxMapperTest {
     }
 
     @Test
-    void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInV1Table() {
-        mailboxDAO.save(MAILBOX)
-            .block();
-        mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-
-        List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
-            .privateNamespace()
-            .username(USER)
-            .expression(Wildcard.INSTANCE)
-            .build()
-            .asUserBound())
-            .collectList().block();
-
-        assertThat(mailboxes).containsOnly(MAILBOX);
-    }
-
-    @Test
-    void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInBothTables() {
-        mailboxDAO.save(MAILBOX)
-            .block();
-        mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-        mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-
-        List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
-            .privateNamespace()
-            .username(USER)
-            .expression(Wildcard.INSTANCE)
-            .build()
-            .asUserBound())
-            .collectList().block();
-
-        assertThat(mailboxes).containsOnly(MAILBOX);
-    }
-
-    @Test
-    void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInV2Table() {
-        mailboxDAO.save(MAILBOX)
-            .block();
-        mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-
-        List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
-            .privateNamespace()
-            .username(USER)
-            .expression(Wildcard.INSTANCE)
-            .build()
-            .asUserBound())
-            .collectList().block();
-
-        assertThat(mailboxes).containsOnly(MAILBOX);
-    }
-
-    @Test
     void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInV3Table() {
         mailboxDAO.save(MAILBOX)
             .block();
@@ -995,65 +933,6 @@ class CassandraMailboxMapperTest {
     }
 
     @Test
-    void hasChildrenShouldReturnChildWhenExistsInV1Table() {
-        mailboxDAO.save(MAILBOX)
-            .block();
-        mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-        CassandraId childMailboxId = CassandraId.timeBased();
-        MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
-        Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
-        mailboxDAO.save(childMailbox)
-            .block();
-        mailboxPathDAO.save(childMailboxPath, childMailboxId)
-            .block();
-    
-        boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
-
-        assertThat(hasChildren).isTrue();
-    }
-
-    @Test
-    void hasChildrenShouldReturnChildWhenExistsInBothTables() {
-        mailboxDAO.save(MAILBOX)
-            .block();
-        mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-        mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-        CassandraId childMailboxId = CassandraId.timeBased();
-        MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
-        Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
-        mailboxDAO.save(childMailbox)
-            .block();
-        mailboxPathDAO.save(childMailboxPath, childMailboxId)
-            .block();
-
-        boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
-
-        assertThat(hasChildren).isTrue();
-    }
-
-    @Test
-    void hasChildrenShouldReturnChildWhenExistsInV2Table() {
-        mailboxDAO.save(MAILBOX)
-            .block();
-        mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
-            .block();
-        CassandraId childMailboxId = CassandraId.timeBased();
-        MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
-        Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
-        mailboxDAO.save(childMailbox)
-            .block();
-        mailboxPathV2DAO.save(childMailboxPath, childMailboxId)
-            .block();
-    
-        boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
-    
-        assertThat(hasChildren).isTrue();
-    }
-
-    @Test
     void hasChildrenShouldReturnChildWhenExistsInV3Table() {
         mailboxDAO.save(MAILBOX)
             .block();
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/MailboxAggregateModule.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/MailboxAggregateModule.java
index dd1fd57..3b49629 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/MailboxAggregateModule.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/MailboxAggregateModule.java
@@ -22,6 +22,7 @@ package org.apache.james.mailbox.cassandra.mail;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.blob.cassandra.CassandraBlobModule;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
@@ -39,21 +40,22 @@ import org.apache.james.mailbox.cassandra.modules.CassandraUidModule;
 
 public interface MailboxAggregateModule {
     CassandraModule MODULE = CassandraModule.aggregateModules(
-            CassandraSchemaVersionModule.MODULE,
-            CassandraAclModule.MODULE,
-            CassandraMailboxModule.MODULE,
-            CassandraMessageModule.MODULE,
-            CassandraBlobModule.MODULE,
-            CassandraAttachmentModule.MODULE,
-            CassandraMailboxCounterModule.MODULE,
-            CassandraMailboxRecentsModule.MODULE,
-            CassandraFirstUnseenModule.MODULE,
-            CassandraUidModule.MODULE,
-            CassandraModSeqModule.MODULE,
-            CassandraSubscriptionModule.MODULE,
-            CassandraDeletedMessageModule.MODULE,
-            CassandraAnnotationModule.MODULE,
-            CassandraApplicableFlagsModule.MODULE);
+        CassandraAclModule.MODULE,
+        CassandraAnnotationModule.MODULE,
+        CassandraApplicableFlagsModule.MODULE,
+        CassandraAttachmentModule.MODULE,
+        CassandraBlobModule.MODULE,
+        CassandraEventStoreModule.MODULE(),
+        CassandraDeletedMessageModule.MODULE,
+        CassandraFirstUnseenModule.MODULE,
+        CassandraMailboxCounterModule.MODULE,
+        CassandraMailboxModule.MODULE,
+        CassandraMailboxRecentsModule.MODULE,
+        CassandraMessageModule.MODULE,
+        CassandraModSeqModule.MODULE,
+        CassandraSchemaVersionModule.MODULE,
+        CassandraSubscriptionModule.MODULE,
+        CassandraUidModule.MODULE);
 
     CassandraModule MODULE_WITH_QUOTA = CassandraModule.aggregateModules(CassandraQuotaModule.MODULE, MODULE);
 }
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AclV2MigrationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AclV2MigrationTest.java
index 213df82..83c0c97 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AclV2MigrationTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/AclV2MigrationTest.java
@@ -26,12 +26,20 @@ import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConsistenciesConfiguration;
+import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.core.Username;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStore;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
+import org.apache.james.eventsourcing.eventstore.cassandra.EventStoreDao;
+import org.apache.james.eventsourcing.eventstore.cassandra.JsonEventSerializer;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLDAOV1;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLDAOV2;
+import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxDAO;
+import org.apache.james.mailbox.cassandra.mail.CassandraUserMailboxRightsDAO;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
 import org.apache.james.mailbox.model.Mailbox;
@@ -52,8 +60,9 @@ class AclV2MigrationTest {
         UidValidity.generate(), MAILBOX_ID);
 
     public static final CassandraModule MODULES = CassandraModule.aggregateModules(
-        CassandraMailboxModule.MODULE,
         CassandraAclModule.MODULE,
+        CassandraEventStoreModule.MODULE(),
+        CassandraMailboxModule.MODULE,
         CassandraSchemaVersionModule.MODULE);
 
     @RegisterExtension
@@ -69,7 +78,14 @@ class AclV2MigrationTest {
         mailboxDAO = new CassandraMailboxDAO(cassandra.getConf(), cassandra.getTypesProvider(), CassandraConsistenciesConfiguration.DEFAULT);
         daoV1 = new CassandraACLDAOV1(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION, CassandraConsistenciesConfiguration.DEFAULT);
         daoV2 = new CassandraACLDAOV2(cassandra.getConf());
-        migration = new AclV2Migration(mailboxDAO, daoV1, daoV2);
+        JsonEventSerializer jsonEventSerializer = JsonEventSerializer
+            .forModules(ACLModule.ACL_RESET, ACLModule.ACL_UPDATE)
+            .withoutNestedType();
+        CassandraEventStore eventStore = new CassandraEventStore(new EventStoreDao(cassandra.getConf(), jsonEventSerializer, CassandraConsistenciesConfiguration.DEFAULT));
+        CassandraUserMailboxRightsDAO usersRightDAO = new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
+        migration = new AclV2Migration(mailboxDAO,
+            new CassandraACLMapper.StoreV1(usersRightDAO, daoV1),
+            new CassandraACLMapper.StoreV2(usersRightDAO, daoV2, eventStore));
     }
 
     @Test
@@ -105,7 +121,7 @@ class AclV2MigrationTest {
         MailboxACL acl = new MailboxACL(ImmutableMap.of(MailboxACL.EntryKey.createUserEntryKey(Username.of("alice")), MailboxACL.FULL_RIGHTS));
         daoV1.setACL(MAILBOX_ID, acl).block();
 
-        Task.Result result = migration.runTask();
+        migration.runTask();
 
         assertThat(daoV2.getACL(MAILBOX_ID).block()).isEqualTo(acl);
     }
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/MailboxPathV2MigrationTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/MailboxPathV2MigrationTest.java
index 0d72d2b..86baa97 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/MailboxPathV2MigrationTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/migration/MailboxPathV2MigrationTest.java
@@ -25,11 +25,16 @@ import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
 import org.apache.james.backends.cassandra.components.CassandraModule;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
+import org.apache.james.backends.cassandra.init.configuration.CassandraConsistenciesConfiguration;
 import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionDAO;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionManager;
 import org.apache.james.backends.cassandra.versions.CassandraSchemaVersionModule;
 import org.apache.james.core.Username;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStore;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
+import org.apache.james.eventsourcing.eventstore.cassandra.EventStoreDao;
+import org.apache.james.eventsourcing.eventstore.cassandra.JsonEventSerializer;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLDAOV1;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLDAOV2;
@@ -41,6 +46,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraMailboxPathDAOImpl;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxPathV2DAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMailboxPathV3DAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraUserMailboxRightsDAO;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraMailboxModule;
 import org.apache.james.mailbox.model.Mailbox;
@@ -62,7 +68,8 @@ class MailboxPathV2MigrationTest {
     public static final CassandraModule MODULES = CassandraModule.aggregateModules(
             CassandraMailboxModule.MODULE,
             CassandraAclModule.MODULE,
-            CassandraSchemaVersionModule.MODULE);
+            CassandraSchemaVersionModule.MODULE,
+            CassandraEventStoreModule.MODULE());
 
     @RegisterExtension
     static CassandraClusterExtension cassandraCluster = new CassandraClusterExtension(MODULES);
@@ -94,6 +101,16 @@ class MailboxPathV2MigrationTest {
             cassandra.getConf(),
             cassandra.getTypesProvider(),
             cassandraCluster.getCassandraConsistenciesConfiguration());
+        CassandraACLDAOV1 aclDAOV1 = new CassandraACLDAOV1(
+            cassandra.getConf(),
+            CassandraConfiguration.DEFAULT_CONFIGURATION,
+            cassandraCluster.getCassandraConsistenciesConfiguration());
+        CassandraACLDAOV2 aclDAOV2 = new CassandraACLDAOV2(cassandra.getConf());
+        JsonEventSerializer jsonEventSerializer = JsonEventSerializer
+            .forModules(ACLModule.ACL_RESET, ACLModule.ACL_UPDATE)
+            .withoutNestedType();
+        CassandraEventStore eventStore = new CassandraEventStore(new EventStoreDao(cassandra.getConf(), jsonEventSerializer, CassandraConsistenciesConfiguration.DEFAULT));
+        CassandraUserMailboxRightsDAO usersRightDAO = new CassandraUserMailboxRightsDAO(cassandra.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
         mailboxMapper = new CassandraMailboxMapper(
             mailboxDAO,
             daoV1,
@@ -101,12 +118,8 @@ class MailboxPathV2MigrationTest {
             daoV3,
             userMailboxRightsDAO,
             new CassandraACLMapper(
-                userMailboxRightsDAO,
-                new CassandraACLDAOV1(
-                    cassandra.getConf(),
-                    CassandraConfiguration.DEFAULT_CONFIGURATION,
-                    cassandraCluster.getCassandraConsistenciesConfiguration()),
-                new CassandraACLDAOV2(cassandra.getConf()),
+                new CassandraACLMapper.StoreV1(usersRightDAO, aclDAOV1),
+                new CassandraACLMapper.StoreV2(usersRightDAO, aclDAOV2, eventStore),
                 new CassandraSchemaVersionManager(new CassandraSchemaVersionDAO(cassandra.getConf()))),
             new CassandraSchemaVersionManager(new CassandraSchemaVersionDAO(cassandra.getConf())),
             CassandraConfiguration.DEFAULT_CONFIGURATION);
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/GuiceUtils.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/GuiceUtils.java
index 6dc6dab..ad7fa95 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/GuiceUtils.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/utils/GuiceUtils.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.mailbox.cassandra.mail.utils;
 
+import java.util.Set;
+
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.init.CassandraTypesProvider;
 import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
@@ -27,15 +29,28 @@ import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.cassandra.CassandraBlobStoreFactory;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.eventstore.EventStore;
+import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStore;
+import org.apache.james.eventsourcing.eventstore.cassandra.EventNestedTypes;
+import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
+import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
+import org.apache.james.json.DTO;
+import org.apache.james.json.DTOModule;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraACLDAOV1;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLModule;
 import org.apache.james.mailbox.model.MessageId;
 
 import com.datastax.driver.core.Session;
+import com.google.common.collect.ImmutableSet;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
 import com.google.inject.util.Modules;
 
 public class GuiceUtils {
@@ -64,6 +79,14 @@ public class GuiceUtils {
             binder -> binder.bind(BlobId.Factory.class).toInstance(new HashBlobId.Factory()),
             binder -> binder.bind(BlobStore.class).toProvider(() -> CassandraBlobStoreFactory.forTesting(session).passthrough()),
             binder -> binder.bind(Session.class).toInstance(session),
+            binder -> Multibinder.newSetBinder(binder, new TypeLiteral<EventDTOModule<? extends Event, ? extends EventDTO>>() {})
+                .addBinding().toInstance(ACLModule.ACL_RESET),
+            binder -> Multibinder.newSetBinder(binder, new TypeLiteral<EventDTOModule<? extends Event, ? extends EventDTO>>() {})
+                .addBinding().toInstance(ACLModule.ACL_UPDATE),
+            binder -> binder.bind(new TypeLiteral<Set<DTOModule<?, ? extends DTO>>>() {}).annotatedWith(Names.named(EventNestedTypes.EVENT_NESTED_TYPES_INJECTION_NAME))
+                .toInstance(ImmutableSet.of()),
+            binder -> Multibinder.newSetBinder(binder, new TypeLiteral<EventDTOModule<? extends Event, ? extends EventDTO>>() {}),
+            binder -> binder.bind(EventStore.class).to(CassandraEventStore.class),
             binder -> binder.bind(CassandraTypesProvider.class).toInstance(typesProvider),
             binder -> binder.bind(CassandraConfiguration.class).toInstance(configuration),
             binder -> binder.bind(CassandraConsistenciesConfiguration.class)
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
index 5db0098..23408f1 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
@@ -25,6 +25,9 @@ import javax.inject.Singleton;
 import org.apache.james.adapter.mailbox.UserRepositoryAuthenticator;
 import org.apache.james.adapter.mailbox.UserRepositoryAuthorizator;
 import org.apache.james.backends.cassandra.components.CassandraModule;
+import org.apache.james.eventsourcing.Event;
+import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
+import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
 import org.apache.james.mailbox.AttachmentContentLoader;
 import org.apache.james.mailbox.AttachmentManager;
 import org.apache.james.mailbox.Authenticator;
@@ -64,6 +67,7 @@ import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraModSeqProvider;
 import org.apache.james.mailbox.cassandra.mail.CassandraUidProvider;
 import org.apache.james.mailbox.cassandra.mail.CassandraUserMailboxRightsDAO;
+import org.apache.james.mailbox.cassandra.mail.eventsourcing.acl.ACLModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAclModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraAnnotationModule;
 import org.apache.james.mailbox.cassandra.modules.CassandraApplicableFlagsModule;
@@ -104,6 +108,7 @@ import org.apache.mailbox.tools.indexer.ReIndexerImpl;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
 import com.google.inject.multibindings.Multibinder;
 import com.google.inject.name.Names;
 
@@ -206,6 +211,11 @@ public class CassandraMailboxModule extends AbstractModule {
         mailboxListeners.addBinding().to(DeleteMessageListener.class);
 
         bind(MailboxManager.class).annotatedWith(Names.named(MAILBOXMANAGER_NAME)).to(MailboxManager.class);
+
+        Multibinder.newSetBinder(binder(), new TypeLiteral<EventDTOModule<? extends Event, ? extends EventDTO>>() {})
+            .addBinding().toInstance(ACLModule.ACL_RESET);
+        Multibinder.newSetBinder(binder(), new TypeLiteral<EventDTOModule<? extends Event, ? extends EventDTO>>() {})
+            .addBinding().toInstance(ACLModule.ACL_UPDATE);
     }
     
     @Singleton
@@ -215,6 +225,4 @@ public class CassandraMailboxModule extends AbstractModule {
             super("cassandra-mailboxmanager", manager);
         }
     }
-    
-
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org