diff --git a/xwiki-platform-core/pom.xml b/xwiki-platform-core/pom.xml
index 7bfe46023de532ea64f7893270c9b34a727ac192..fe333ad95f24e07038d7de1a90b6380684193088 100644
--- a/xwiki-platform-core/pom.xml
+++ b/xwiki-platform-core/pom.xml
@@ -138,10 +138,23 @@
 
                  Single justification example:
             -->
-            
-            
-            
-            
+
+            <revapi.differences>
+              <justification>Change in generated class of the REST model to add the
+                enforceRequiredRights property.</justification>
+              <criticality>allowed</criticality>
+              <differences>
+                <item>
+                  <code>java.annotation.attributeValueChanged</code>
+                  <old>class org.xwiki.rest.model.jaxb.Page</old>
+                  <new>class org.xwiki.rest.model.jaxb.Page</new>
+                  <annotationType>javax.xml.bind.annotation.XmlType</annotationType>
+                  <attribute>propOrder</attribute>
+                  <oldValue>{"language", "majorVersion", "minorVersion", "hidden", "created", "creator", "creatorName", "modified", "modifier", "modifierName", "originalMetadataAuthor", "originalMetadataAuthorName", "comment", "content", "clazz", "objects", "attachments", "hierarchy"}</oldValue>
+                  <newValue>{"language", "majorVersion", "minorVersion", "hidden", "enforceRequiredRights", "created", "creator", "creatorName", "modified", "modifier", "modifierName", "originalMetadataAuthor", "originalMetadataAuthorName", "comment", "content", "clazz", "objects", "attachments", "hierarchy"}</newValue>
+                </item>
+              </differences>
+            </revapi.differences>
           </analysisConfiguration>
         </configuration>
       </plugin>
diff --git a/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentModelBridge.java b/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentModelBridge.java
index dfb642810ab418c94ae2ef68a133c5422ca58105..535cadb0a5457978427a44077b92f4337d23a451 100644
--- a/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentModelBridge.java
+++ b/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentModelBridge.java
@@ -221,4 +221,16 @@ default boolean isRestricted()
     {
         return false;
     }
+
+    /**
+     * @return {@code true} if required rights defined in a {@code XWiki.RequiredRightClass} object shall be
+     * enforced, meaning that editing will be limited to users with these rights and content of this document can't
+     * use more rights than defined in the object, {@code false} otherwise
+     * @since 16.10.0RC1
+     */
+    @Unstable
+    default boolean isEnforceRequiredRights()
+    {
+        return false;
+    }
 }
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-events/xwiki-platform-filter-event-model/src/main/java/org/xwiki/filter/event/model/WikiDocumentFilter.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-events/xwiki-platform-filter-event-model/src/main/java/org/xwiki/filter/event/model/WikiDocumentFilter.java
index f371bfc469ec05c8048c3bc5335d690c0e9db1c7..5ffb495b5cb12613102ffc1cb11392a3178cd4ed 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-events/xwiki-platform-filter-event-model/src/main/java/org/xwiki/filter/event/model/WikiDocumentFilter.java
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-events/xwiki-platform-filter-event-model/src/main/java/org/xwiki/filter/event/model/WikiDocumentFilter.java
@@ -26,6 +26,7 @@
 import org.xwiki.filter.FilterEventParameters;
 import org.xwiki.filter.FilterException;
 import org.xwiki.filter.annotation.Default;
+import org.xwiki.stability.Unstable;
 
 /**
  * Document related events.
@@ -197,6 +198,14 @@ public interface WikiDocumentFilter
      */
     String PARAMETER_REVISION_MINOR = "revision_minor";
 
+    // required rights
+    /**
+     * @type {@link Boolean}
+     * @since 16.10.0RC1
+     */
+    @Unstable
+    String PARAMETER_ENFORCE_REQUIRED_RIGHTS = "enforce_required_rights";
+
     // Events
 
     /**
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARDocumentModel.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARDocumentModel.java
index 42f2cc533bb65f963319634dd1f6a79fd6b58165..cc0eecfb76909faf930038400890e6e863f9856c 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARDocumentModel.java
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARDocumentModel.java
@@ -72,6 +72,8 @@ public class XARDocumentModel extends XarDocumentModel
                 new EventParameter(XWikiWikiDocumentFilter.PARAMETER_REVISION_EFFECTIVEMETADATA_AUTHOR));
             put(ELEMENT_REVISION_ORIGINALMEDATAAUTHOR,
                 new EventParameter(XWikiWikiDocumentFilter.PARAMETER_REVISION_ORIGINALMETADATA_AUTHOR));
+            put(ELEMENT_ENFORCE_REQUIRED_RIGHTS,
+                new EventParameter(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS, Boolean.class));
             put(ELEMENT_REVISION_COMMENT, new EventParameter(XWikiWikiDocumentFilter.PARAMETER_REVISION_COMMENT));
             put(ELEMENT_REVISION_DATE, new EventParameter(XWikiWikiDocumentFilter.PARAMETER_REVISION_DATE, Date.class));
             put(ELEMENT_REVISION_MINOR,
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARFilterUtils.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARFilterUtils.java
index 3fcb53a6cf211cea4b4fd29951ed520c21112038..3a2f5802d06b214f9a213df27c33520909b688fd 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARFilterUtils.java
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/XARFilterUtils.java
@@ -76,10 +76,15 @@ public EventParameter(String name)
      */
     public static final String ROLEHINT_15 = ROLEHINT_PREFIX + XarDocumentModel.VERSION_15;
 
+    /**
+     * @since 16.10.0RC1
+     */
+    public static final String ROLEHINT_16 = ROLEHINT_PREFIX + XarDocumentModel.VERSION_16;
+
     /**
      * @since 7.2M1
      */
-    public static final String ROLEHINT_CURRENT = ROLEHINT_15;
+    public static final String ROLEHINT_CURRENT = ROLEHINT_16;
 
     /**
      * @since 6.2M1
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/DocumentLocaleReader.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/DocumentLocaleReader.java
index e526cea9742aca86fcbe3fd5e871b667955477e0..3f355e089220e01302005db86e777394a1bef61d 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/DocumentLocaleReader.java
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/DocumentLocaleReader.java
@@ -404,6 +404,7 @@ private void readDocument(XMLStreamReader xmlReader, Object filter, XARInputFilt
         // Initialize with a few defaults (thing that don't exist in old XAR format)
         this.currentDocumentRevisionParameters.put(XWikiWikiDocumentFilter.PARAMETER_SYNTAX, Syntax.XWIKI_1_0);
         this.currentDocumentRevisionParameters.put(XWikiWikiDocumentFilter.PARAMETER_HIDDEN, false);
+        this.currentDocumentRevisionParameters.put(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS, false);
 
         // Reference
         String referenceString = xmlReader.getAttributeValue(null, XARDocumentModel.ATTRIBUTE_DOCUMENT_REFERENCE);
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStream.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStream.java
index 36ad0c863344b163fe566c1a3bfce19edd9498d8..394c948d9dc52da4c9dac832eb75400cd23d6210 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStream.java
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStream.java
@@ -44,8 +44,14 @@
  * @version $Id$
  * @since 6.2M1
  */
-@Component(hints = {XARFilterUtils.ROLEHINT_15, XARFilterUtils.ROLEHINT_14, XARFilterUtils.ROLEHINT_13,
-    XARFilterUtils.ROLEHINT_12, XARFilterUtils.ROLEHINT_11})
+@Component(hints = {
+    XARFilterUtils.ROLEHINT_16,
+    XARFilterUtils.ROLEHINT_15,
+    XARFilterUtils.ROLEHINT_14,
+    XARFilterUtils.ROLEHINT_13,
+    XARFilterUtils.ROLEHINT_12,
+    XARFilterUtils.ROLEHINT_11
+})
 @InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
 public class XARInputFilterStream extends AbstractBeanInputFilterStream<XARInputProperties, XARInputFilter>
 {
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStreamFactory.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStreamFactory.java
index f31841c318d12f91757399ac367dfde56e298490..adbe2f295f332a925170f3de447c774ac8265cf1 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStreamFactory.java
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/input/XARInputFilterStreamFactory.java
@@ -33,8 +33,14 @@
  * @version $Id$
  * @since 6.2M1
  */
-@Component(hints = {XARFilterUtils.ROLEHINT_15, XARFilterUtils.ROLEHINT_14, XARFilterUtils.ROLEHINT_13,
-    XARFilterUtils.ROLEHINT_12, XARFilterUtils.ROLEHINT_11})
+@Component(hints = {
+    XARFilterUtils.ROLEHINT_16,
+    XARFilterUtils.ROLEHINT_15,
+    XARFilterUtils.ROLEHINT_14,
+    XARFilterUtils.ROLEHINT_13,
+    XARFilterUtils.ROLEHINT_12,
+    XARFilterUtils.ROLEHINT_11
+})
 @Singleton
 public class XARInputFilterStreamFactory
     extends AbstractBeanInputFilterStreamFactory<XARInputProperties, XARInputFilter>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStream.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStream.java
index 399ff9f466323b5360d93cded4068ffc73940193..752f82ac1f801d07c0aa7252d19e0435e76caab5 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStream.java
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStream.java
@@ -69,8 +69,14 @@
  * @version $Id$
  * @since 6.2M1
  */
-@Component(hints = {XARFilterUtils.ROLEHINT_15, XARFilterUtils.ROLEHINT_14, XARFilterUtils.ROLEHINT_13,
-    XARFilterUtils.ROLEHINT_12, XARFilterUtils.ROLEHINT_11})
+@Component(hints = {
+    XARFilterUtils.ROLEHINT_16,
+    XARFilterUtils.ROLEHINT_15,
+    XARFilterUtils.ROLEHINT_14,
+    XARFilterUtils.ROLEHINT_13,
+    XARFilterUtils.ROLEHINT_12,
+    XARFilterUtils.ROLEHINT_11
+})
 @InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
 public class XAROutputFilterStream extends AbstractBeanOutputFilterStream<XAROutputProperties> implements XARFilter
 {
@@ -382,6 +388,10 @@ public void beginWikiDocumentRevision(String revision, FilterEventParameters par
                 this.writer.writeElement(XarDocumentModel.ELEMENT_HIDDEN,
                     toString(parameters.get(XWikiWikiDocumentFilter.PARAMETER_HIDDEN)));
             }
+            if (parameters.containsKey(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS)) {
+                this.writer.writeElement(XarDocumentModel.ELEMENT_ENFORCE_REQUIRED_RIGHTS,
+                    toString(parameters.get(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS)));
+            }
             if (parameters.containsKey(XWikiWikiDocumentFilter.PARAMETER_CONTENT)) {
                 this.writer.writeElement(XarDocumentModel.ELEMENT_CONTENT,
                     (String) parameters.get(XWikiWikiDocumentFilter.PARAMETER_CONTENT));
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStreamFactory.java b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStreamFactory.java
index 6d28e95627c4bcb3dd72ce868c8cfbc5c05936b0..3a64f7484ad89c47b1623fa6c8f9b5380f391a3f 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStreamFactory.java
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/main/java/org/xwiki/filter/xar/internal/output/XAROutputFilterStreamFactory.java
@@ -34,8 +34,14 @@
  * @version $Id$
  * @since 6.2M1
  */
-@Component(hints = {XARFilterUtils.ROLEHINT_15, XARFilterUtils.ROLEHINT_14, XARFilterUtils.ROLEHINT_13,
-    XARFilterUtils.ROLEHINT_12, XARFilterUtils.ROLEHINT_11})
+@Component(hints = {
+    XARFilterUtils.ROLEHINT_16,
+    XARFilterUtils.ROLEHINT_15,
+    XARFilterUtils.ROLEHINT_14,
+    XARFilterUtils.ROLEHINT_13,
+    XARFilterUtils.ROLEHINT_12,
+    XARFilterUtils.ROLEHINT_11
+})
 @Singleton
 public class XAROutputFilterStreamFactory extends AbstractBeanOutputFilterStreamFactory<XAROutputProperties, XARFilter>
 {
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/class/class1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/class/class1.test
index 33f5d88777d4a30e5000b0d2a8287f9a23806f1e..f37e980d1f6e2c297460aef6ebca49bc6ab06c19 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/class/class1.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/class/class1.test
@@ -58,6 +58,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
           </parameters>
         </p>
         <wikiClass>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document1.test
index 78de35d8ba2852734f682d87e39f493a830325cc..63b77d0c45b4b33b95c3b1babe2daf0952023bde 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document1.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document1.test
@@ -2,7 +2,7 @@
 .inputexpect|xwiki+xar/1.4
 .#------------------------------------------------------------------------------
 <?xml version='1.1' encoding='UTF-8'?>
-<xwikidoc version="1.5" reference="space.page" locale="">
+<xwikidoc version="1.6" reference="space.page" locale="">
   <web>space</web>
   <name>page</name>
   <language/>
@@ -26,6 +26,7 @@
   <minorEdit>false</minorEdit>
   <syntaxId>syntax/1.0</syntaxId>
   <hidden>true</hidden>
+  <enforceRequiredRights>true</enforceRequiredRights>
   <content>content</content>
   <renderedcontent/>
   <attachment>
@@ -167,6 +168,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>true</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document2.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document2.test
index 670b3aacc425b597d7ad97f59a7014cfc13cfd30..173c3b7b68f026ab393fa47a10d4d1a64eb05d28 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document2.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/document2.test
@@ -165,6 +165,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentattachmentwithoutcontent.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentattachmentwithoutcontent.test
index 334ed032575037d2f255a5309aff90e6843225aa..1bc08f32de84a6785e9431ca6492b73ad4a6025d 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentattachmentwithoutcontent.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentattachmentwithoutcontent.test
@@ -3,7 +3,7 @@
 .# Attachment with no content
 .#------------------------------------------------------------------------------
 <?xml version='1.1' encoding='UTF-8'?>
-<xwikidoc version="1.5" reference="space.page" locale="">
+<xwikidoc version="1.6" reference="space.page" locale="">
   <web>space</web>
   <name>page</name>
   <language/>
@@ -26,6 +26,7 @@
   <minorEdit>false</minorEdit>
   <syntaxId>syntax/1.0</syntaxId>
   <hidden>true</hidden>
+  <enforceRequiredRights>true</enforceRequiredRights>
   <content>content</content>
   <renderedcontent/>
   <attachment>
@@ -87,6 +88,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>true</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithnestedspaces1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithnestedspaces1.test
index 55a62b98a49862fc5e3efe7248bd69a3d401eaa4..d411e20eee275e6f3df7e81857e42874a96659cc 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithnestedspaces1.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithnestedspaces1.test
@@ -2,7 +2,7 @@
 .inputexpect|xwiki+xar/1.3
 .#------------------------------------------------------------------------------
 <?xml version='1.1' encoding='UTF-8'?>
-<xwikidoc version="1.5" reference="space1.space2.page" locale="">
+<xwikidoc version="1.6" reference="space1.space2.page" locale="">
   <web>space1.space2</web>
   <name>page</name>
   <language/>
@@ -25,6 +25,7 @@
   <minorEdit>false</minorEdit>
   <syntaxId>syntax/1.0</syntaxId>
   <hidden>true</hidden>
+  <enforceRequiredRights>true</enforceRequiredRights>
   <content>content</content>
   <renderedcontent/>
   <attachment>
@@ -165,6 +166,10 @@
                 <string>hidden</string>
                 <boolean>true</boolean>
               </entry>
+              <entry>
+                <string>enforce_required_rights</string>
+                <boolean>true</boolean>
+              </entry>
               <entry>
                 <string>parent_reference</string>
                 <org.xwiki.model.reference.EntityReference>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithunknownelements.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithunknownelements.test
index 093765872ff506057ca67a68bde7bc351eb5a075..42215e0a8431c914ffa9b0db27730816afc0d87e 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithunknownelements.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/documentwithunknownelements.test
@@ -144,6 +144,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/emptydocument.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/emptydocument.test
index a31e808f89de67d21baab705d8da4e925ed0b1ed..552894aa5e3810a234029ae96b1bead6ed64e594 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/emptydocument.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/emptydocument.test
@@ -39,6 +39,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
           </parameters>
         </p>
       </wikiDocumentRevision>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacy1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacy1.test
index 607484f12dc0ee49b0f8195ba9c432e5129f7aea..1646850cd60a77cbf42f733280aaf989cafa7031 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacy1.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacy1.test
@@ -165,6 +165,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacytranslation1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacytranslation1.test
index a5530e5459df9a7a8e8ba3ec0d79c5f54dffec84..9f93e8f4ae94ec68158d96f1a4a5438687c2fd84 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacytranslation1.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/legacytranslation1.test
@@ -3,7 +3,7 @@
 .# Make sure legacy XAR format is properly parsed
 .#------------------------------------------------------------------------------
 <?xml version='1.1' encoding='UTF-8'?>
-<xwikidoc version="1.5" reference="space.page" locale="fr">
+<xwikidoc version="1.6" reference="space.page" locale="fr">
   <web>space</web>
   <name>page</name>
   <language>fr</language>
@@ -26,6 +26,7 @@
   <minorEdit>false</minorEdit>
   <syntaxId>syntax/1.0</syntaxId>
   <hidden>true</hidden>
+  <enforceRequiredRights>true</enforceRequiredRights>
   <content>content</content>
   <renderedcontent/>
   <attachment>
@@ -165,6 +166,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>true</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/new1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/new1.test
index 1afa12a6bab6bd68e5e4a71a5e20b2f7fcbdb38b..36cc06412646c17b19090c2082ea427a7c1e861b 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/new1.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/document/new1.test
@@ -176,6 +176,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/object1.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/object1.test
index 7e8ea8b84dd785bdd28dc7d21bafc610843e963c..6478c22440970e20498675d943077d3f539c0980 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/object1.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/object1.test
@@ -2,7 +2,7 @@
 .inputexpect|xwiki+xar/1.1
 .#------------------------------------------------------------------------------
 <?xml version='1.1' encoding='UTF-8'?>
-<xwikidoc version="1.5" reference="space.page" locale="">
+<xwikidoc version="1.6" reference="space.page" locale="">
   <web>space</web>
   <name>page</name>
   <language/>
@@ -11,6 +11,7 @@
   <version>1.1</version>
   <syntaxId>xwiki/1.0</syntaxId>
   <hidden>false</hidden>
+  <enforceRequiredRights>true</enforceRequiredRights>
   <object>
     <name>space.page</name>
     <number>0</number>
@@ -117,6 +118,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>true</boolean>
+            </entry>
           </parameters>
         </p>
         <wikiObject name="space.class[0]">
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/objectwithoutclass.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/objectwithoutclass.test
index 358e8cd8633f56501f5622071dd933a16ccbd14b..4e45c482962d6f059c3245a75fada7537e5880fd 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/objectwithoutclass.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/object/objectwithoutclass.test
@@ -2,7 +2,7 @@
 .inputexpect|xwiki+xar/1.1
 .#------------------------------------------------------------------------------
 <?xml version='1.1' encoding='UTF-8'?>
-<xwikidoc version="1.5" reference="space.page" locale="">
+<xwikidoc version="1.6" reference="space.page" locale="">
   <web>space</web>
   <name>page</name>
   <language/>
@@ -11,6 +11,7 @@
   <version>1.1</version>
   <syntaxId>xwiki/1.0</syntaxId>
   <hidden>false</hidden>
+  <enforceRequiredRights>true</enforceRequiredRights>
   <object>
     <name>space.page</name>
     <number>0</number>
@@ -52,6 +53,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>true</boolean>
+            </entry>
           </parameters>
         </p>
         <wikiObject name="space.class[0]">
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/property/nullvalueproperty.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/property/nullvalueproperty.test
index 0bd1bbd134ca1a9ca7cbfa2ae8da956bc4916349..17b95720939afca99acce160d34ef53c13c419c3 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/property/nullvalueproperty.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/document/property/nullvalueproperty.test
@@ -2,7 +2,7 @@
 .expect|xwiki+xar/1.1
 .#------------------------------------------------------------------------------
 <?xml version='1.1' encoding='UTF-8'?>
-<xwikidoc version="1.5" reference="space.page" locale="">
+<xwikidoc version="1.6" reference="space.page" locale="">
   <web>space</web>
   <name>page</name>
   <language/>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/nestedspace/page.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/nestedspace/page.xml
index ec48980eaf69e761c409fa697c6fbc3e7c1d031f..9711add6a39c1b8bcc76a7404397385430cbe20f 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/nestedspace/page.xml
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/nestedspace/page.xml
@@ -1,5 +1,5 @@
 <?xml version='1.1' encoding='UTF-8'?>
-<xwikidoc version="1.5" reference="space.nestedspace.page" locale="">
+<xwikidoc version="1.6" reference="space.nestedspace.page" locale="">
   <web>space.nestedspace</web>
   <name>page</name>
   <language/>
@@ -19,6 +19,7 @@
   <validationScript/>
   <comment/>
   <minorEdit>false</minorEdit>
+  <enforceRequiredRights>true</enforceRequiredRights>
   <syntaxId>xwiki/2.0</syntaxId>
   <hidden>false</hidden>
   <content>content</content>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/page.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/page.xml
index 1e4efba789aacb185c6e15262f54bc4d79d57976..bb0cb05bea7606da1dc2f91005cd1404515936d3 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/page.xml
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/test1/space/page.xml
@@ -1,5 +1,5 @@
 <?xml version='1.1' encoding='UTF-8'?>
-<xwikidoc version="1.5" reference="space.page" locale="">
+<xwikidoc version="1.6" reference="space.page" locale="">
   <web>space</web>
   <name>page</name>
   <language/>
@@ -21,6 +21,7 @@
   <minorEdit>false</minorEdit>
   <syntaxId>xwiki/2.0</syntaxId>
   <hidden>false</hidden>
+  <enforceRequiredRights>false</enforceRequiredRights>
   <content>content</content>
   <class>
     <name>space.page</name>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/xar1/space2/page2.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/xar1/space2/page2.xml
index a7e2f81fc7c31fa448198b787865e1996a6ee228..e41700ea89dc3277f1aca6b0ed0fbd87560534fd 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/xar1/space2/page2.xml
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/packagefile/xar1/space2/page2.xml
@@ -20,5 +20,6 @@
   <minorEdit>false</minorEdit>
   <syntaxId>xwiki/2.0</syntaxId>
   <hidden>false</hidden>
+  <enforceRequiredRights>true</enforceRequiredRights>
   <content>content2</content>
 </xwikidoc>
\ No newline at end of file
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/legacymixed1.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/legacymixed1.input.test
index d36b6ca2c5df3fe003d1abf4aaaa1c17dd26211c..a37e11ba3c754e151e518ebccfc165f757c407e3 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/legacymixed1.input.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/legacymixed1.input.test
@@ -47,6 +47,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
@@ -151,6 +155,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
@@ -255,6 +263,10 @@
               <string>hidden</string>
               <boolean>true</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>parent_reference</string>
               <org.xwiki.model.reference.EntityReference>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested1.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested1.input.test
index a028763a3c20f4cf21f14452e55d7bd7d3593a46..fe975a13cc6ecd7da182c966602b61ef0397f8dd 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested1.input.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested1.input.test
@@ -43,6 +43,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>revision_author</string>
               <string>XWiki.author</string>
@@ -135,6 +139,10 @@
                     <string>hidden</string>
                     <boolean>false</boolean>
                   </entry>
+                  <entry>
+                    <string>enforce_required_rights</string>
+                    <boolean>false</boolean>
+                  </entry>
                   <entry>
                     <string>revision_author</string>
                     <string>XWiki.author</string>
@@ -227,6 +235,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>revision_author</string>
               <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested2.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested2.input.test
index 01dd8e900e025539d1df3a6beb006f45abc83544..a0732fcc3d195c71ce126ea0b7a129bd6396a4ef 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested2.input.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/nested2.input.test
@@ -44,6 +44,10 @@
                 <string>hidden</string>
                 <boolean>false</boolean>
               </entry>
+              <entry>
+                <string>enforce_required_rights</string>
+                <boolean>false</boolean>
+              </entry>
               <entry>
                 <string>revision_author</string>
                 <string>XWiki.author</string>
@@ -137,6 +141,10 @@
                 <string>hidden</string>
                 <boolean>false</boolean>
               </entry>
+              <entry>
+                <string>enforce_required_rights</string>
+                <boolean>false</boolean>
+              </entry>
               <entry>
                 <string>revision_author</string>
                 <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-noforcedocument.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-noforcedocument.input.test
index 7804a08b4fe61b077a0e6663f542d83cb12894bb..e2c2a43764dd86ce1049c31353e521d819b4dc5b 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-noforcedocument.input.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-noforcedocument.input.test
@@ -43,6 +43,10 @@
                 <string>hidden</string>
                 <boolean>false</boolean>
               </entry>
+              <entry>
+                <string>enforce_required_rights</string>
+                <boolean>false</boolean>
+              </entry>
               <entry>
                 <string>revision_author</string>
                 <string>XWiki.author</string>
@@ -429,6 +433,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>revision_author</string>
               <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-sourcetype.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-sourcetype.input.test
index a7beb10b8de67e4c645504f59f32bcef2ebaac44..c2d7a0ed22439cb540e601d915d393a90aa1fc57 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-sourcetype.input.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1-sourcetype.input.test
@@ -43,6 +43,10 @@
                 <string>hidden</string>
                 <boolean>false</boolean>
               </entry>
+              <entry>
+                <string>enforce_required_rights</string>
+                <boolean>false</boolean>
+              </entry>
               <entry>
                 <string>revision_author</string>
                 <string>XWiki.author</string>
@@ -429,6 +433,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>revision_author</string>
               <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.input.test
index 2dcd3a506402b2e07c5d94c4ea6d22e3bfebf267..c02ae8e92aa27b4cfca2f94366d87e2fa87208f3 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.input.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.input.test
@@ -43,6 +43,10 @@
                 <string>hidden</string>
                 <boolean>false</boolean>
               </entry>
+              <entry>
+                <string>enforce_required_rights</string>
+                <boolean>false</boolean>
+              </entry>
               <entry>
                 <string>revision_author</string>
                 <string>XWiki.author</string>
@@ -429,6 +433,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>revision_author</string>
               <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.output.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.output.test
index f9459a4cb153ac9df4359c7cc83467238d036454..9c641ca36c31cb67ebf643db09a89a6b34340722 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.output.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/test1.output.test
@@ -42,6 +42,10 @@
                 <string>hidden</string>
                 <boolean>false</boolean>
               </entry>
+              <entry>
+                <string>enforce_required_rights</string>
+                <boolean>true</boolean>
+              </entry>
               <entry>
                 <string>revision_author</string>
                 <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipFirstDocument.output.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipFirstDocument.output.xml
index b4004f3b04b789b8c956feb3a5bc4a9610eda40b..823bb94604fc9cae1571e075861c5ab8058a94d2 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipFirstDocument.output.xml
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipFirstDocument.output.xml
@@ -39,6 +39,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>true</boolean>
+            </entry>
             <entry>
               <string>revision_author</string>
               <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipLastSpace.output.xml b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipLastSpace.output.xml
index ec147da2d5b76d09d2ec5e493cc3040861b04597..4205194ad91916058d8d787656e5059421659b76 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipLastSpace.output.xml
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/testSkipLastSpace.output.xml
@@ -39,6 +39,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>revision_author</string>
               <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/xar1.input.test b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/xar1.input.test
index 744c305db9f07bf4660e1634cd5ae9eca5e763f0..900643e203aad04d9c7a1d4cdf6e3f25ca98e179 100644
--- a/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/xar1.input.test
+++ b/xwiki-platform-core/xwiki-platform-filter/xwiki-platform-filter-streams/xwiki-platform-filter-stream-xar/src/test/resources/xar/xar1.input.test
@@ -43,6 +43,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>revision_author</string>
               <string>XWiki.author</string>
@@ -134,6 +138,10 @@
               <string>hidden</string>
               <boolean>false</boolean>
             </entry>
+            <entry>
+              <string>enforce_required_rights</string>
+              <boolean>false</boolean>
+            </entry>
             <entry>
               <string>revision_author</string>
               <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/api/Document.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/api/Document.java
index a610a5179510f3819d96ce30b76c5a3b1c478148..fd0ab72c1fa0254285f6f0868562d15fb0a367bb 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/api/Document.java
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/api/Document.java
@@ -3263,6 +3263,34 @@ public void setHidden(boolean hidden)
         this.doc.setHidden(hidden);
     }
 
+    /**
+     * @return {@code true} if required rights defined in a {@code XWiki.RequiredRightClass} object shall be
+     * enforced, meaning that editing will be limited to users with these rights and content of this document can't
+     * use more rights than defined in the object, {@code false} otherwise
+     * @since 16.6.0RC1
+     */
+    @Unstable
+    public boolean isEnforceRequiredRights()
+    {
+        return this.doc.isEnforceRequiredRights();
+    }
+
+    /**
+     * @param enforceRequiredRights if required rights defined in a {@code XWiki.RequiredRightClass} object shall be
+     * enforced, meaning that editing will be limited to users with these rights and content of this document can't use
+     * more rights than defined in the object
+     * @since 16.6.0RC1
+     */
+    @Unstable
+    public void setEnforceRequiredRights(boolean enforceRequiredRights)
+    {
+        getDoc().setEnforceRequiredRights(enforceRequiredRights);
+
+        updateAuthor();
+
+        updateContentAuthor();
+    }
+
     /**
      * Drop permissions for the remainder of the rendering cycle. After this is called:
      * <ul>
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/LazyXWikiDocument.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/LazyXWikiDocument.java
index b5eea80f1936984c1a75f8661104ffd9b4c2fc2b..c9c5ffe19fa3c897a83351569a40d3cd05337cf7 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/LazyXWikiDocument.java
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/LazyXWikiDocument.java
@@ -286,6 +286,12 @@ public Boolean isHidden()
         return getDocument().isHidden();
     }
 
+    @Override
+    public boolean isEnforceRequiredRights()
+    {
+        return getDocument().isEnforceRequiredRights();
+    }
+
     @Override
     public XWikiDocumentArchive getDocumentArchive()
     {
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
index 33e7c5ca07e9bd7c4333f6198f0b70e41f05f12e..4b5272563d4be024f0b96651d795bcc7a35bc122 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
@@ -518,6 +518,13 @@ private static Transformation getMacroTransformation()
      */
     private Syntax syntax;
 
+    /**
+     * If required rights that can be defined in a {@code XWiki.RequiredRightClass} shall be enforced. For
+     * backwards-compatibility reasons, this is {@code false} by default.
+     * @since 16.10.0RC1
+     */
+    private boolean enforceRequiredRights = false;
+
     /**
      * Is latest modification a minor edit.
      */
@@ -4189,6 +4196,11 @@ public void readDocMetaFromForm(EditForm eform, XWikiContext context) throws XWi
         if (eform.getHidden() != null) {
             setHidden("1".equals(eform.getHidden()));
         }
+
+        // Read the enforce required rights flag from the form
+        if (eform.getEnforceRequiredRights() != null) {
+            setEnforceRequiredRights("1".equals(eform.getEnforceRequiredRights()));
+        }
     }
 
     private Syntax resolveSyntax(String syntaxId)
@@ -4537,6 +4549,7 @@ public void clone(XWikiDocument document)
         setMinorEdit(document.isMinorEdit());
         setSyntax(document.getSyntax());
         setHidden(document.isHidden());
+        setEnforceRequiredRights(document.isEnforceRequiredRights());
 
         cloneXObjects(document);
         cloneAttachments(document);
@@ -4620,6 +4633,7 @@ private XWikiDocument cloneInternal(DocumentReference newDocumentReference, bool
             doc.setSyntax(getSyntax());
             doc.setHidden(isHidden());
             doc.setRestricted(isRestricted());
+            doc.setEnforceRequiredRights(isEnforceRequiredRights());
 
             if (this.xClass != null) {
                 doc.setXClass(this.xClass.clone());
@@ -4918,6 +4932,10 @@ public boolean equalsData(XWikiDocument otherDocument)
             return false;
         }
 
+        if (isEnforceRequiredRights() != otherDocument.isEnforceRequiredRights()) {
+            return false;
+        }
+
         // XClass
 
         if (!getXClass().equals(otherDocument.getXClass())) {
@@ -7084,6 +7102,11 @@ public List<MetaDataDiff> getMetaDataDiff(XWikiDocument fromDoc, XWikiDocument t
             list.add(new MetaDataDiff("hidden", fromDoc.isHidden(), toDoc.isHidden()));
         }
 
+        if (fromDoc.isEnforceRequiredRights() != toDoc.isEnforceRequiredRights()) {
+            list.add(new MetaDataDiff("enforceRequiredRights", fromDoc.isEnforceRequiredRights(),
+                toDoc.isEnforceRequiredRights()));
+        }
+
         return list;
     }
 
@@ -7700,6 +7723,32 @@ public void setSyntaxId(String syntaxId)
         setSyntax(syntax);
     }
 
+    /**
+     * @return {@code true} if required rights defined in a {@code XWiki.RequiredRightClass} object shall be
+     * enforced, meaning that editing will be limited to users with these rights and content of this document can't
+     * use more rights than defined in the object, {@code false} otherwise
+     * @since 16.10.0RC1
+     */
+    @Unstable
+    public boolean isEnforceRequiredRights()
+    {
+        return this.enforceRequiredRights;
+    }
+
+    /**
+     * @param enforceRequiredRights if required rights defined in a {@code XWiki.RequiredRightClass} object shall be
+     * enforced, meaning that editing will be limited to users with these rights and content of this document can't use
+     * more rights than defined in the object
+     * @since 16.10.0RC1
+     */
+    @Unstable
+    public void setEnforceRequiredRights(boolean enforceRequiredRights)
+    {
+        this.enforceRequiredRights = enforceRequiredRights;
+
+        setContentDirty(true);
+    }
+
     public Vector<BaseObject> getComments(boolean asc)
     {
         List<BaseObject> list = getXObjects(COMMENTSCLASS_REFERENCE);
@@ -9370,6 +9419,11 @@ public boolean apply(XWikiDocument document, boolean clean)
             modified = true;
         }
 
+        if (isEnforceRequiredRights() != document.isEnforceRequiredRights()) {
+            setEnforceRequiredRights(document.isEnforceRequiredRights());
+            modified = true;
+        }
+
         // /////////////////////////////////
         // XObjects
 
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/input/XWikiDocumentLocaleEventGenerator.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/input/XWikiDocumentLocaleEventGenerator.java
index 9fd24ad2678aef5b45f152d8da0cd5482395c4a2..35f2141bd7f0a32c144ec4140f57865469e49c89 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/input/XWikiDocumentLocaleEventGenerator.java
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/input/XWikiDocumentLocaleEventGenerator.java
@@ -183,6 +183,8 @@ private void writeRevision(XWikiDocument document, Object filter, XWikiDocumentF
         }
         revisionParameters.put(WikiDocumentFilter.PARAMETER_SYNTAX, document.getSyntax());
         revisionParameters.put(WikiDocumentFilter.PARAMETER_HIDDEN, document.isHidden());
+        revisionParameters.put(XWikiWikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS,
+            document.isEnforceRequiredRights());
 
         revisionParameters.put(WikiDocumentFilter.PARAMETER_REVISION_EFFECTIVEMETADATA_AUTHOR, toString(document.getAuthors().getEffectiveMetadataAuthor()));
         revisionParameters.put(WikiDocumentFilter.PARAMETER_REVISION_ORIGINALMETADATA_AUTHOR, toString(document.getAuthors().getOriginalMetadataAuthor()));
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/XWikiDocumentOutputFilterStream.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/XWikiDocumentOutputFilterStream.java
index 90a066ce4e2c77f676e5fe6d55cc02baf2c4a9dd..5db50c843e803477c96cd472d012e87ee66d9498 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/XWikiDocumentOutputFilterStream.java
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/filter/output/XWikiDocumentOutputFilterStream.java
@@ -293,6 +293,9 @@ private void begin(FilterEventParameters parameters) throws FilterException
 
         this.entity.setMinorEdit(getBoolean(WikiDocumentFilter.PARAMETER_REVISION_MINOR, parameters, false));
 
+        this.entity.setEnforceRequiredRights(getBoolean(WikiDocumentFilter.PARAMETER_ENFORCE_REQUIRED_RIGHTS,
+            parameters, false));
+
         String revisions =
             getString(XWikiWikiDocumentFilter.PARAMETER_JRCSREVISIONS, this.currentLocaleParameters, null);
         if (revisions != null) {
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/web/EditForm.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/web/EditForm.java
index ce57090f11a0b76f60c1e0a98f6a49b5db71d1ce..881ad496fc52781be02100ffc98f098f406e3176 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/web/EditForm.java
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/web/EditForm.java
@@ -33,8 +33,10 @@
 import org.apache.commons.lang3.math.NumberUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.xwiki.stability.Unstable;
 import org.xwiki.store.TemporaryAttachmentSessionsManager;
 
+import com.xpn.xwiki.doc.XWikiDocument;
 import com.xpn.xwiki.util.Util;
 
 /**
@@ -97,6 +99,8 @@ public class EditForm extends XWikiForm
     private boolean convertSyntax;
 
     private String hidden;
+
+    private String enforceRequiredRights;
     
     private ObjectPolicyType objectPolicy;
 
@@ -129,6 +133,7 @@ public void readRequest()
         setSyntaxId(request.getParameter("syntaxId"));
         setConvertSyntax(Boolean.valueOf(request.getParameter("convertSyntax")));
         setHidden(request.getParameter("xhidden"));
+        setEnforceRequiredRights(request.getParameter("enforceRequiredRights"));
         setObjectPolicy(request.getParameter("objectPolicy"));
         setUpdateOrCreateMap(request);
         setObjectsToRemove(request.getParameterValues("deletedObjects"));
@@ -357,6 +362,26 @@ public void setHidden(String hidden)
         this.hidden = hidden;
     }
 
+    /**
+     * @return the enforce required rights flag, see {@link XWikiDocument#isEnforceRequiredRights()}
+     * @since 16.10.0RC1
+     */
+    @Unstable
+    public String getEnforceRequiredRights()
+    {
+        return this.enforceRequiredRights;
+    }
+
+    /**
+     * @param enforceRequiredRights the enforce required rights flag, see {@link XWikiDocument#isEnforceRequiredRights()}
+     * @since 16.10.0RC1
+     */
+    @Unstable
+    public void setEnforceRequiredRights(String enforceRequiredRights)
+    {
+        this.enforceRequiredRights = enforceRequiredRights;
+    }
+
     /**
      * Return the object policy given in the HTTP request. See {@link com.xpn.xwiki.web.ObjectPolicyType
      * ObjectPolicyType} for more information about what is an object policy.
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.db2.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.db2.hbm.xml
index f10d3cdbf5e69077fd33a2cfc9c553aeb3d6bd1e..0b32367b840979f5728db35847de94bfb7c4b54a 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.db2.hbm.xml
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.db2.hbm.xml
@@ -75,6 +75,8 @@
         <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" />
         <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" />
         <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="255" index="DOC_ORIGINAL_METADATA_AUTHOR" />
+        <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS"
+            index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/>
     </class>
 
     <!-- com.xpn.xwiki.doc.XWikiSpace root -->
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.derby.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.derby.hbm.xml
index fd8297e2f9f484f31336772868151d534546dcf1..052d9339d3cbe3a4316c4efa48ee86715e46c11b 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.derby.hbm.xml
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.derby.hbm.xml
@@ -75,6 +75,8 @@
         <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" />
         <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" />
         <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="768" index="DOC_ORIGINAL_METADATA_AUTHOR" />
+        <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS"
+            index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/>
     </class>
 
     <!-- com.xpn.xwiki.doc.XWikiSpace root -->
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.hbm.xml
index 9fe3245b3e223adced7833167fe0667eca4e5e57..097b6726aff17304268652fd4926c9272e570a2d 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.hbm.xml
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.hbm.xml
@@ -70,6 +70,8 @@
         <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" />
         <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" />
         <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="768" index="DOC_ORIGINAL_METADATA_AUTHOR" />
+        <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS"
+                  index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/>
     </class>
 
     <!-- com.xpn.xwiki.doc.XWikiSpace root -->
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.mssql.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.mssql.hbm.xml
index 604665327a2f25685a64c89903e0ee1330bf8da1..d94c1227f9906c9fe232f3ec2fc851cc175b2581 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.mssql.hbm.xml
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.mssql.hbm.xml
@@ -77,6 +77,8 @@
         <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" />
         <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" />
         <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="255" index="DOC_ORIGINAL_METADATA_AUTHOR" />
+        <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS"
+            index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/>
     </class>
 
     <!-- com.xpn.xwiki.doc.XWikiSpace root -->
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.oracle.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.oracle.hbm.xml
index e37c976d9afa225adc72aa848d9657556b0c4d3c..ce2b676b2c2c891955e261aa039170d3f29160f1 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.oracle.hbm.xml
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.oracle.hbm.xml
@@ -83,6 +83,8 @@
         <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" />
         <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" />
         <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA" length="768" index="DOC_ORIGINAL_METADATA" />
+        <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS"
+            index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/>
     </class>
 
     <!-- com.xpn.xwiki.doc.XWikiSpace root -->
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.postgresql.hbm.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.postgresql.hbm.xml
index 81948bd7fa13e71602e41ad3d2cfb9eb3be7680d..1e2f2d9b4d2fbdbecf4870cf4a47045e75b442fa 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.postgresql.hbm.xml
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/xwiki.postgresql.hbm.xml
@@ -79,6 +79,8 @@
         <property name="syntaxId" type="string" column="XWD_SYNTAX_ID" length="50" />
         <property name="hidden" type="boolean" column="XWD_HIDDEN" index="DOC_HIDDEN" not-null="true" />
         <property name="originalMetadataAuthorReference" type="string" column="XWD_ORIGINAL_METADATA_AUTHOR" length="768" index="DOC_ORIGINAL_METADATA_AUTHOR" />
+        <property name="enforceRequiredRights" type="boolean" column="XWD_ENFORCE_REQUIRED_RIGHTS"
+            index="DOC_ENFORCE_REQUIRED_RIGHTS" not-null="true"/>
     </class>
 
     <!-- com.xpn.xwiki.doc.XWikiSpace root -->
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/document1.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/document1.xml
index 0f0bb271c52bf4e15e89126068410740a0ecb1b7..f1f357da37eeb131d2eb045047ca4ec84c449dae 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/document1.xml
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/document1.xml
@@ -48,6 +48,10 @@
                   <string>hidden</string>
                   <boolean>false</boolean>
                 </entry>
+                <entry>
+                  <string>enforce_required_rights</string>
+                  <boolean>false</boolean>
+                </entry>
                 <entry>
                   <string>revision_author</string>
                   <string>XWiki.author</string>
@@ -200,6 +204,10 @@
                   <string>hidden</string>
                   <boolean>true</boolean>
                 </entry>
+                <entry>
+                  <string>enforce_required_rights</string>
+                  <boolean>false</boolean>
+                </entry>
                 <entry>
                   <string>revision_author</string>
                   <string>XWiki.author</string>
@@ -530,6 +538,10 @@
                     <string>hidden</string>
                     <boolean>true</boolean>
                   </entry>
+                  <entry>
+                    <string>enforce_required_rights</string>
+                    <boolean>false</boolean>
+                  </entry>
                   <entry>
                     <string>revision_author</string>
                     <string>XWiki.author</string>
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml
index 3d5891effb62630bba9348b64be92c71ba495d11..a107f777731b75dae90c43b583d473684a175889 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment1content.xml
@@ -49,6 +49,10 @@
                   <string>hidden</string>
                   <boolean>false</boolean>
                 </entry>
+                <entry>
+                  <string>enforce_required_rights</string>
+                  <boolean>false</boolean>
+                </entry>
                 <entry>
                   <string>revision_author</string>
                   <string>XWiki.XWikiGuest</string>
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml
index 77e524ef589e2f428f128fbb5f48181e445a7a5a..ffef321f09cdb41ba6b4c7ddc73b9960b570c2f8 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/resources/filter/documentwithattachment2content.xml
@@ -49,6 +49,10 @@
                   <string>hidden</string>
                   <boolean>false</boolean>
                 </entry>
+                <entry>
+                  <string>enforce_required_rights</string>
+                  <boolean>false</boolean>
+                </entry>
                 <entry>
                   <string>revision_author</string>
                   <string>XWiki.XWikiGuest</string>
diff --git a/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-model/src/main/resources/xwiki.rest.model.xsd b/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-model/src/main/resources/xwiki.rest.model.xsd
index 5b4b166e1a6f862847db2e4d157491968953f3be..7d157e1d03282d19204bb2d4a5ed876732abbb58 100644
--- a/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-model/src/main/resources/xwiki.rest.model.xsd
+++ b/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-model/src/main/resources/xwiki.rest.model.xsd
@@ -128,6 +128,7 @@
           <element name="majorVersion" type="int"></element>
           <element name="minorVersion" type="int"></element>
           <element name="hidden" type="boolean" default="false"></element>
+          <element name="enforceRequiredRights" type="boolean" minOccurs="0"/>
           <element name="created" type="dateTime"></element>
           <element name="creator" type="string"></element>
           <element name="creatorName" type="string"></element>
diff --git a/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/ModelFactory.java b/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/ModelFactory.java
index 12697d3140b7332f1a0d9fba916504905a690d04..e74082acd0dd4cbd8be5496c1a9cf1c6d300fbe0 100644
--- a/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/ModelFactory.java
+++ b/xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/ModelFactory.java
@@ -212,6 +212,11 @@ public boolean toDocument(Document doc, org.xwiki.rest.model.jaxb.Page restPage)
 
         doc.setHidden(restPage.isHidden());
 
+        if (restPage.isEnforceRequiredRights() != null) {
+            doc.setEnforceRequiredRights(restPage.isEnforceRequiredRights());
+            modified = true;
+        }
+
         // Set objects
         if (restPage.getObjects() != null) {
             Set<ObjectReference> newReferences = new HashSet<>();
@@ -761,6 +766,7 @@ public Page toRestPage(URI baseUri, URI self, Document doc, boolean useVersion,
         page.setMajorVersion(doc.getRCSVersion().at(0));
         page.setMinorVersion(doc.getRCSVersion().at(1));
         page.setHidden(doc.isHidden());
+        page.setEnforceRequiredRights(doc.isEnforceRequiredRights());
         page.setLanguage(doc.getLocale().toString());
         page.setCreator(doc.getCreator());
         if (withPrettyNames) {
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DefaultAuthorizationManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DefaultAuthorizationManager.java
index 5366e2597113ad7d7473d35248f2fddd572fb2a9..0b338d81c7b300710af3db7cd9b9cd5f814c8088 100644
--- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DefaultAuthorizationManager.java
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DefaultAuthorizationManager.java
@@ -38,6 +38,7 @@
 import org.xwiki.security.UserSecurityReference;
 import org.xwiki.security.authorization.cache.SecurityCache;
 import org.xwiki.security.authorization.cache.SecurityCacheLoader;
+import org.xwiki.security.authorization.internal.DocumentRequiredRightsChecker;
 import org.xwiki.security.internal.XWikiBridge;
 
 /**
@@ -79,6 +80,9 @@ public class DefaultAuthorizationManager implements AuthorizationManager
     @Inject
     private XWikiBridge xwikiBridge;
 
+    @Inject
+    private DocumentRequiredRightsChecker documentRequiredRightsChecker;
+
     /**
      * Check if the user is the super admin.
      *
@@ -148,9 +152,7 @@ private boolean hasSecurityAccess(Right right, DocumentReference userReference,
         }
 
         if (right == null || right == Right.ILLEGAL) {
-            if (check) {
-                logDeny(userReference, entityReference, right, "no such right");
-            }
+            logDenyIfCheck(right, userReference, entityReference, check, "no such right");
             return false;
         }
 
@@ -159,9 +161,26 @@ private boolean hasSecurityAccess(Right right, DocumentReference userReference,
             return false;
         }
 
+        // For edit right, check if the user has all required rights.
+        if (right == Right.EDIT && !this.documentRequiredRightsChecker.hasRequiredRights(userReference,
+            entityReference))
+        {
+            logDenyIfCheck(right, userReference, entityReference, check, "misses required right");
+
+            return false;
+        }
+
         return evaluateSecurityAccess(right, userReference, entityReference, check);
     }
 
+    private void logDenyIfCheck(Right right, DocumentReference userReference, EntityReference entityReference,
+        boolean check, String info)
+    {
+        if (check) {
+            logDeny(userReference, entityReference, right, info);
+        }
+    }
+
     private boolean evaluateSecurityAccess(Right right, DocumentReference userReference,
         EntityReference entityReference, boolean check)
         throws AuthorizationException
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DocumentAuthorizationManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DocumentAuthorizationManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..be32b7b671bdcd78e175d882493a47ef0ab48e2f
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DocumentAuthorizationManager.java
@@ -0,0 +1,76 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.security.authorization;
+
+import org.xwiki.component.annotation.Role;
+import org.xwiki.model.EntityType;
+import org.xwiki.model.reference.DocumentReference;
+import org.xwiki.stability.Unstable;
+
+/**
+ * Authorization manager that checks rights of document authors taking required rights into account.
+ *
+ * @version $Id$
+ * @since 16.10.0RC1
+ */
+@Unstable
+@Role
+public interface DocumentAuthorizationManager
+{
+    /**
+     * Tests if the given context author of the context document has the specified right at the given level, taking the
+     * required rights of the document into account.
+     *
+     * @param right the right to check
+     * @param level the level of the right, for example, for admin right, this could be {@link EntityType#DOCUMENT} for
+     * admin right directly on the document itself or {@link EntityType#WIKI} for admin right on the whole wiki.
+     * @param contextAuthor the author for which rights shall be checked
+     * @param contextDocument the document for which the rights shall be checked
+     * @return if the context author has the right
+     */
+    boolean hasAccess(Right right, EntityType level, DocumentReference contextAuthor,
+        DocumentReference contextDocument);
+
+    /**
+     * Check if the given document has the given required right.
+     *
+     * @param right the right to check
+     * @param level the level of the right
+     * @param contextDocument the reference of the context document
+     * @return if the document has the required right (independent of the actual author)
+     * @throws AuthorizationException if loading the required rights fails
+     */
+    boolean hasRequiredRight(Right right, EntityType level, DocumentReference contextDocument)
+        throws AuthorizationException;
+
+    /**
+     * Checks if the given context author of the context document has the specified right at the given level, taking the
+     * required rights of the document into account. This function should be used at security checkpoint.
+     *
+     * @param right the right to check
+     * @param level the level of the right, for example, for admin right, this could be {@link EntityType#DOCUMENT} for
+     * admin right directly on the document itself or {@link EntityType#WIKI} for admin right on the whole wiki.
+     * @param contextAuthor the author for which rights shall be checked
+     * @param contextDocument the document for which the rights shall be checked
+     * @throws AccessDeniedException if the context author does not have the right
+     */
+    void checkAccess(Right right, EntityType level, DocumentReference contextAuthor,
+        DocumentReference contextDocument) throws AccessDeniedException;
+}
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/internal/DocumentRequiredRightsChecker.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/internal/DocumentRequiredRightsChecker.java
new file mode 100644
index 0000000000000000000000000000000000000000..3787136158da4f28cb102612c83bd3b766787881
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/internal/DocumentRequiredRightsChecker.java
@@ -0,0 +1,103 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.security.authorization.internal;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.model.EntityType;
+import org.xwiki.model.reference.DocumentReference;
+import org.xwiki.model.reference.EntityReference;
+import org.xwiki.security.authorization.AuthorizationException;
+import org.xwiki.security.authorization.AuthorizationManager;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRight;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRightsManager;
+
+/**
+ * Check if a user has all required rights defined for an entity.
+ *
+ * @version $Id$
+ * @since 16.10.0RC1
+ */
+@Component(roles = DocumentRequiredRightsChecker.class)
+@Singleton
+public class DocumentRequiredRightsChecker
+{
+    @Inject
+    private Provider<AuthorizationManager> authorizationManagerProvider;
+
+    @Inject
+    private DocumentRequiredRightsManager documentRequiredRightsManager;
+
+    /**
+     * Check if a user has all required rights defined for an entity.
+     *
+     * @param userReference the user reference
+     * @param entityReference the entity reference
+     * @return true if the user has all required rights, false otherwise
+     * @throws AuthorizationException if an error occurs while loading the required rights
+     */
+    public boolean hasRequiredRights(DocumentReference userReference, EntityReference entityReference)
+        throws AuthorizationException
+    {
+        DocumentReference documentReference = getDocumentReference(entityReference);
+
+        if (documentReference == null) {
+            return true;
+        }
+
+        AuthorizationManager authorizationManager = this.authorizationManagerProvider.get();
+
+        DocumentRequiredRights documentRequiredRights =
+            this.documentRequiredRightsManager.getRequiredRights(documentReference)
+                .orElse(DocumentRequiredRights.EMPTY);
+        if (documentRequiredRights.enforce()) {
+            for (DocumentRequiredRight requiredRight : documentRequiredRights.rights()) {
+                if (!authorizationManager.hasAccess(requiredRight.right(), userReference,
+                    documentReference.extractReference(requiredRight.scope())))
+                {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    private DocumentReference getDocumentReference(EntityReference entityReference)
+    {
+        if (entityReference != null) {
+            if (entityReference instanceof DocumentReference documentReference) {
+                return documentReference;
+            }
+
+            EntityReference documentEntityReference = entityReference.extractReference(EntityType.DOCUMENT);
+
+            if (documentEntityReference != null) {
+                return new DocumentReference(documentEntityReference);
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRight.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRight.java
new file mode 100644
index 0000000000000000000000000000000000000000..595ed91f869fde3f0217a932695d76093873ece4
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRight.java
@@ -0,0 +1,38 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.security.authorization.requiredrights;
+
+import org.xwiki.model.EntityType;
+import org.xwiki.security.authorization.Right;
+import org.xwiki.stability.Unstable;
+
+/**
+ * A required right set on a document.
+ *
+ * @param right the right
+ * @param scope the scope of the right, e.g., wiki or document level
+ *
+ * @version $Id$
+ * @since 16.10.0RC1
+ */
+@Unstable
+public record DocumentRequiredRight(Right right, EntityType scope)
+{
+}
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRights.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRights.java
new file mode 100644
index 0000000000000000000000000000000000000000..aadd0f253b70b60fb1a93ab8a10e65be4b033d82
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRights.java
@@ -0,0 +1,42 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.security.authorization.requiredrights;
+
+import java.util.Set;
+
+import org.xwiki.stability.Unstable;
+
+/**
+ * Represents the required rights that are configured on a document.
+ *
+ * @param enforce if the required rights shall be enforced
+ * @param rights the configured rights
+ *
+ * @version $Id$
+ * @since 16.10.0RC1
+ */
+@Unstable
+public record DocumentRequiredRights(boolean enforce, Set<DocumentRequiredRight> rights)
+{
+    /**
+     * Empty required rights.
+     */
+    public static final DocumentRequiredRights EMPTY = new DocumentRequiredRights(false, Set.of());
+}
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRightsManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRightsManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..64c68e45758123ad66ed5e290d3ece9c8be37b1c
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/requiredrights/DocumentRequiredRightsManager.java
@@ -0,0 +1,47 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.security.authorization.requiredrights;
+
+import java.util.Optional;
+
+import org.xwiki.component.annotation.Role;
+import org.xwiki.model.reference.DocumentReference;
+import org.xwiki.security.authorization.AuthorizationException;
+import org.xwiki.stability.Unstable;
+
+/**
+ * Manager for document required rights.
+ *
+ * @version $Id$
+ * @since 16.10.0RC1
+ */
+@Unstable
+@Role
+public interface DocumentRequiredRightsManager
+{
+    /**
+     * Get the document required rights for the given document.
+     *
+     * @param documentReference the document to get the required rights for
+     * @return the document required rights if the document exists, empty otherwise
+     */
+    Optional<DocumentRequiredRights> getRequiredRights(DocumentReference documentReference)
+        throws AuthorizationException;
+}
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/resources/META-INF/components.txt b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/resources/META-INF/components.txt
index f6e89bad263c01ae70f55f28b52d1f7d9f1399e2..0e25145cbe9fbbcdbe95d0d2e8c9e29f2107a5e4 100644
--- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/resources/META-INF/components.txt
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/resources/META-INF/components.txt
@@ -2,6 +2,7 @@ org.xwiki.security.DefaultSecurityReferenceFactory
 org.xwiki.security.authorization.cache.internal.DefaultSecurityCache
 org.xwiki.security.authorization.cache.internal.DefaultSecurityCacheLoader
 org.xwiki.security.authorization.internal.AuthorizationSettlerProvider
+org.xwiki.security.authorization.internal.DocumentRequiredRightsChecker
 org.xwiki.security.authorization.DefaultAuthorizationManager
 org.xwiki.security.authorization.internal.DefaultAuthorizationManagerConfiguration
 org.xwiki.security.authorization.internal.DefaultAuthorizationSettler
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/DefaultAuthorizationManagerIntegrationTest.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/DefaultAuthorizationManagerIntegrationTest.java
index f87ed2f51fd88f041c125ed41f20d89425e90558..843801ce814793320b680bc94a29750b9b0e90e2 100644
--- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/DefaultAuthorizationManagerIntegrationTest.java
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/DefaultAuthorizationManagerIntegrationTest.java
@@ -55,6 +55,7 @@
 import org.xwiki.security.authorization.cache.internal.TestCache;
 import org.xwiki.security.authorization.internal.AbstractSecurityRuleEntry;
 import org.xwiki.security.authorization.internal.DefaultAuthorizationSettler;
+import org.xwiki.security.authorization.internal.DocumentRequiredRightsChecker;
 import org.xwiki.security.authorization.testwikis.SecureTestEntity;
 import org.xwiki.security.authorization.testwikis.TestAccessRule;
 import org.xwiki.security.authorization.testwikis.TestDefinition;
@@ -137,6 +138,9 @@ class DefaultAuthorizationManagerIntegrationTest extends AbstractAuthorizationTe
     @MockComponent
     private SecurityCacheRulesInvalidator securityCacheRulesInvalidator;
 
+    @MockComponent
+    private DocumentRequiredRightsChecker documentRequiredRightsChecker;
+
     /** Mocked cache */
     private TestCache<Object> cache;
 
@@ -161,6 +165,8 @@ public EntityReference answer(InvocationOnMock invocation) throws Throwable
             });
 
         when(xWikiBridge.getMainWikiReference()).thenReturn(new WikiReference("xwiki"));
+
+        when(this.documentRequiredRightsChecker.hasRequiredRights(any(), any())).thenReturn(true);
     }
 
     @BeforeEach
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/DefaultDocumentAuthorizationManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/DefaultDocumentAuthorizationManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0966cf5599ee54389de5dd6207c9637e439f3d6
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/DefaultDocumentAuthorizationManager.java
@@ -0,0 +1,122 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.security.authorization.internal;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.slf4j.Logger;
+import org.xwiki.component.annotation.Component;
+import org.xwiki.model.EntityType;
+import org.xwiki.model.reference.DocumentReference;
+import org.xwiki.model.reference.EntityReference;
+import org.xwiki.security.authorization.AccessDeniedException;
+import org.xwiki.security.authorization.AuthorizationException;
+import org.xwiki.security.authorization.AuthorizationManager;
+import org.xwiki.security.authorization.DocumentAuthorizationManager;
+import org.xwiki.security.authorization.Right;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRightsManager;
+
+/**
+ * Default implementation of {@link DocumentAuthorizationManager}.
+ *
+ * @version $Id$
+ * @since 16.10.0RC1
+ */
+@Component
+@Singleton
+public class DefaultDocumentAuthorizationManager implements DocumentAuthorizationManager
+{
+    @Inject
+    private AuthorizationManager authorizationManager;
+
+    @Inject
+    private DocumentRequiredRightsManager documentRequiredRightsManager;
+
+    @Inject
+    private Logger logger;
+
+    @Override
+    public boolean hasAccess(Right right, EntityType level, DocumentReference contextAuthor,
+        DocumentReference contextDocument)
+    {
+        EntityReference reference = contextDocument != null ? contextDocument.extractReference(level) : null;
+
+        try {
+            return hasRequiredRight(right, level, contextDocument)
+                && this.authorizationManager.hasAccess(right, contextAuthor, reference);
+        } catch (Exception e) {
+            this.logger.error("Failed to load required rights for user [{}] on [{}].",
+                contextAuthor, contextDocument, e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean hasRequiredRight(Right right, EntityType level, DocumentReference contextDocument)
+        throws AuthorizationException
+    {
+        DocumentRequiredRights documentRequiredRights =
+            this.documentRequiredRightsManager.getRequiredRights(contextDocument)
+                .orElse(DocumentRequiredRights.EMPTY);
+
+        boolean hasAccess;
+
+        if (documentRequiredRights.enforce()) {
+            hasAccess = documentRequiredRights.rights().stream()
+                .filter(requiredRight -> level.isAllowedAncestor(requiredRight.scope()))
+                .anyMatch(requiredRight ->
+                    requiredRight.right().equals(right) || requiredRight.right()
+                        .getImpliedRights()
+                        // TODO: this is wrong. Not all rights are implied on all levels. For example, if there was
+                        //  no script right on space level, admin right on space level wouldn't imply script right.
+                        // Need to investigate what's the proper solution here but either a) check enabled rights per
+                        // level or b) raise the input level to the first level where the input right is defined.
+                        .contains(right));
+        } else {
+            hasAccess = true;
+        }
+
+        return hasAccess;
+    }
+
+    @Override
+    public void checkAccess(Right right, EntityType level, DocumentReference contextAuthor,
+        DocumentReference contextDocument) throws AccessDeniedException
+    {
+        EntityReference reference = contextDocument != null ? contextDocument.extractReference(level) : null;
+
+        try {
+            if (hasRequiredRight(right, level, contextDocument)) {
+                this.authorizationManager.checkAccess(right, contextAuthor, reference);
+            } else {
+                this.logger.info("[{}] right has been denied to user [{}] on entity [{}] based on required rights"
+                        + " of document [{}] on level [{}]: security checkpoint", right, contextAuthor, reference,
+                    contextDocument, level);
+                throw new AccessDeniedException(right, contextAuthor, reference);
+            }
+        } catch (AccessDeniedException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new AccessDeniedException(right, contextAuthor, contextDocument, e);
+        }
+    }
+}
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/RightsFilterListener.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/RightsFilterListener.java
index 722c52c26f8dc39ab40878593c0881a91802e9e1..9d61582a07cc4087cfecba54fd6efb968456f465 100644
--- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/RightsFilterListener.java
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/RightsFilterListener.java
@@ -32,6 +32,9 @@
 import org.xwiki.observation.AbstractEventListener;
 import org.xwiki.observation.event.CancelableEvent;
 import org.xwiki.observation.event.Event;
+import org.xwiki.security.authorization.internal.requiredrights.DocumentRequiredRightsReader;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRight;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights;
 import org.xwiki.security.authorization.AccessDeniedException;
 import org.xwiki.security.authorization.AuthorizationManager;
 import org.xwiki.security.authorization.Right;
@@ -64,9 +67,15 @@ public class RightsFilterListener extends AbstractEventListener
      */
     public static final String NAME = "org.xwiki.security.authorization.internal.RightsFilterListener";
 
+    private static final LocalDocumentReference REQUIRED_RIGHT_CLASS =
+        new LocalDocumentReference("XWiki", "RequiredRightClass");
+
     @Inject
     private AuthorizationManager authorization;
 
+    @Inject
+    private DocumentRequiredRightsReader documentRequiredRightsReader;
+
     /**
      * The default constructor.
      */
@@ -89,6 +98,36 @@ public void onEvent(Event event, Object source, Object data)
         // Check global rights
         checkModifiedRights(userEvent.getUserReference(), document,
             XWikiGlobalRightsDocumentInitializer.CLASS_REFERENCE, (CancelableEvent) event);
+
+        // Check the required rights.
+        checkModifiedRequiredRights(userEvent.getUserReference(), document, (CancelableEvent) event);
+    }
+
+    private void checkModifiedRequiredRights(DocumentReference user, XWikiDocument document,
+        CancelableEvent event)
+    {
+        XWikiDocument originalDocument = document.getOriginalDocument();
+        DocumentRequiredRights originalRequiredRights =
+            this.documentRequiredRightsReader.readRequiredRights(originalDocument);
+        DocumentRequiredRights requiredRights = this.documentRequiredRightsReader.readRequiredRights(document);
+
+        if (!originalRequiredRights.equals(requiredRights) && requiredRights.enforce()) {
+            // We can assume that the current user has all existing required rights as otherwise editing would be
+            // denied.
+            // Therefore, only check if the user has all rights specified in the updated document that could either
+            // have changed required rights or where enforcing has just been enabled.
+            for (DocumentRequiredRight requiredRight : requiredRights.rights()) {
+                try {
+                    this.authorization.checkAccess(requiredRight.right(), user,
+                        document.getDocumentReference().extractReference(requiredRight.scope()));
+                } catch (AccessDeniedException e) {
+                    event.cancel(
+                        "The author doesn't have the right [%s] on the [%s] level that has been specified as required."
+                            .formatted(requiredRight.right().getName(), requiredRight.scope().getLowerCase()));
+                    break;
+                }
+            }
+        }
     }
 
     private void checkModifiedRights(DocumentReference user, XWikiDocument document,
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DefaultDocumentRequiredRightsManager.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DefaultDocumentRequiredRightsManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5c5465ccab932752959f6f3a02a7d5d6a29ef34
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DefaultDocumentRequiredRightsManager.java
@@ -0,0 +1,71 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.security.authorization.internal.requiredrights;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.model.reference.DocumentReference;
+import org.xwiki.security.authorization.AuthorizationException;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRightsManager;
+
+import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.doc.XWikiDocument;
+
+/**
+ * Default implementation of {@link DocumentRequiredRightsManager}.
+ *
+ * @version $Id$
+ */
+@Component
+@Singleton
+public class DefaultDocumentRequiredRightsManager implements DocumentRequiredRightsManager
+{
+    @Inject
+    private Provider<XWikiContext> contextProvider;
+
+    @Inject
+    private DocumentRequiredRightsReader documentRequiredRightsReader;
+
+    @Override
+    public Optional<DocumentRequiredRights> getRequiredRights(DocumentReference documentReference)
+        throws AuthorizationException
+    {
+        XWikiContext context = this.contextProvider.get();
+
+        // Load the document.
+        try {
+            XWikiDocument document = context.getWiki().getDocument(documentReference, context);
+            if (!document.isNew()) {
+                return Optional.of(this.documentRequiredRightsReader.readRequiredRights(document));
+            }
+        } catch (XWikiException e) {
+            throw new AuthorizationException("Failed to load the document", e);
+        }
+
+        return Optional.empty();
+    }
+}
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReader.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8daa1ea3472e920c2c94bcfca245cfdd03a3eee
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReader.java
@@ -0,0 +1,103 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.security.authorization.internal.requiredrights;
+
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.inject.Singleton;
+
+import org.apache.commons.lang3.StringUtils;
+import org.xwiki.component.annotation.Component;
+import org.xwiki.model.EntityType;
+import org.xwiki.model.reference.EntityReference;
+import org.xwiki.model.reference.LocalDocumentReference;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRight;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights;
+import org.xwiki.security.authorization.Right;
+
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.objects.BaseObject;
+
+/**
+ * Read the required rights from a document.
+ *
+ * @version $Id$
+ * @since 16.6.0RC1
+ */
+@Component(roles = DocumentRequiredRightsReader.class)
+@Singleton
+public class DocumentRequiredRightsReader
+{
+    private static final LocalDocumentReference CLASS_REFERENCE =
+        new LocalDocumentReference("XWiki", "RequiredRightClass");
+
+    private static final String PROPERTY_NAME = "level";
+
+    /**
+     * Read the required rights from a document.
+     *
+     * @param document the document to read the required rights from
+     * @return the required rights
+     */
+    public DocumentRequiredRights readRequiredRights(XWikiDocument document)
+    {
+        return new DocumentRequiredRights(document.isEnforceRequiredRights(),
+            document.getXObjects(CLASS_REFERENCE).stream()
+                .filter(Objects::nonNull)
+                .map(this::readRequiredRight)
+                // Don't allow edit right/edit right implies no extra right.
+                .filter(requiredRight -> !Right.EDIT.equals(requiredRight.right()))
+                .collect(Collectors.toUnmodifiableSet()));
+    }
+
+    private DocumentRequiredRight readRequiredRight(BaseObject object)
+    {
+        String value = object.getStringValue(PROPERTY_NAME);
+        EntityType entityType = EntityType.DOCUMENT;
+        Right right = Right.toRight(value);
+        if (right.equals(Right.ILLEGAL)) {
+            String[] levelRight = StringUtils.split(value, "_", 2);
+            if (levelRight.length == 2) {
+                right = Right.toRight(levelRight[1]);
+                entityType = EntityType.valueOf(levelRight[0].toUpperCase());
+            }
+        }
+
+        // TODO: add some handling for invalid values.
+        Set<EntityType> targetedEntityTypes = right.getTargetedEntityType();
+        if (targetedEntityTypes == null) {
+            // This means the right targets only the farm level, which is null.
+            entityType = null;
+        } else {
+            EntityReference entityReference = object.getDocumentReference().extractReference(entityType);
+            // Try to get the highest level where this right can be assigned. This is done to ensure that, e.g.,
+            // programming right can imply admin right on the wiki level even if programming right is only specified on
+            // the document level.
+            while (!targetedEntityTypes.contains(entityType) && entityReference != null) {
+                entityType = entityReference.getType();
+                entityReference = entityReference.getParent();
+            }
+        }
+
+        return new DocumentRequiredRight(right, entityType);
+    }
+}
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/resources/META-INF/components.txt b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/resources/META-INF/components.txt
index f9d7d702026fe8edeefde5f6845a35973fedaea6..fbfbca70d58ef94234931b35b239676c930729bc 100644
--- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/resources/META-INF/components.txt
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/main/resources/META-INF/components.txt
@@ -1,8 +1,11 @@
 500:org.xwiki.security.authorization.internal.BridgeAuthorizationManager
 org.xwiki.security.authorization.internal.DefaultContextualAuthorizationManager
+org.xwiki.security.authorization.internal.DefaultDocumentAuthorizationManager
 org.xwiki.security.authorization.internal.DefaultSecurityCacheRulesInvalidator
 org.xwiki.security.authorization.internal.DefaultSecurityCacheRulesInvalidatorListener
 org.xwiki.security.authorization.internal.DefaultSecurityEntryReader
+org.xwiki.security.authorization.internal.requiredrights.DefaultDocumentRequiredRightsManager
+org.xwiki.security.authorization.internal.requiredrights.DocumentRequiredRightsReader
 org.xwiki.security.authorization.internal.RightsFilterListener
 org.xwiki.security.internal.DefaultUserBridge
 org.xwiki.security.internal.DefaultXWikiBridge
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/RightsFilterListenerTest.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/RightsFilterListenerTest.java
index 9681754a839c290dc2d64949c40d677bc2c8d40a..52bfc41a47c756c9a04dbff4f857b7a503242422 100644
--- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/RightsFilterListenerTest.java
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/RightsFilterListenerTest.java
@@ -19,11 +19,14 @@
  */
 package org.xwiki.security.authorization.internal;
 
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.xwiki.model.reference.DocumentReference;
 import org.xwiki.security.authorization.AccessDeniedException;
 import org.xwiki.security.authorization.AuthorizationManager;
 import org.xwiki.security.authorization.Right;
+import org.xwiki.security.authorization.internal.requiredrights.DocumentRequiredRightsReader;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights;
 import org.xwiki.test.junit5.mockito.InjectMockComponents;
 import org.xwiki.test.junit5.mockito.MockComponent;
 
@@ -40,7 +43,9 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.when;
 
 /**
  * Validate {@link RightsFilterListener}.
@@ -54,12 +59,21 @@ public class RightsFilterListenerTest
     @MockComponent
     private AuthorizationManager authorization;
 
+    @MockComponent
+    private DocumentRequiredRightsReader requiredRightsReader;
+
     @InjectMockComponents
     private RightsFilterListener listener;
 
     @InjectMockitoOldcore
     private MockitoOldcore oldcore;
 
+    @BeforeEach
+    void setUp()
+    {
+        when(this.requiredRightsReader.readRequiredRights(any())).thenReturn(DocumentRequiredRights.EMPTY);
+    }
+
     @Test
     public void noRight()
     {
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReaderTest.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReaderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..bedfdcb46db48bc54d84b559dcc2b2e56bf6c368
--- /dev/null
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/internal/requiredrights/DocumentRequiredRightsReaderTest.java
@@ -0,0 +1,128 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.security.authorization.internal.requiredrights;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.xwiki.model.EntityType;
+import org.xwiki.model.reference.DocumentReference;
+import org.xwiki.model.reference.LocalDocumentReference;
+import org.xwiki.security.authorization.Right;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRight;
+import org.xwiki.security.authorization.requiredrights.DocumentRequiredRights;
+import org.xwiki.test.junit5.mockito.ComponentTest;
+import org.xwiki.test.junit5.mockito.InjectMockComponents;
+
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.objects.BaseObject;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Unit test for {@link DocumentRequiredRightsReader}.
+ *
+ * @version $Id$
+ */
+@ComponentTest
+class DocumentRequiredRightsReaderTest
+{
+    private static final LocalDocumentReference CLASS_REFERENCE =
+        new LocalDocumentReference("XWiki", "RequiredRightClass");
+
+    private static final DocumentReference DOCUMENT_REFERENCE =
+        new DocumentReference("wiki", "Space", "Page");
+
+    @InjectMockComponents
+    private DocumentRequiredRightsReader documentRequiredRightsReader;
+
+    @ParameterizedTest
+    @MethodSource("getArguments")
+    void readRequiredRights(boolean enforce, List<String> values, DocumentRequiredRights expected)
+    {
+        XWikiDocument document = mock();
+        when(document.isEnforceRequiredRights()).thenReturn(enforce);
+        List<BaseObject> objects = values.stream()
+            .map(value -> {
+                if (value == null) {
+                    return null;
+                } else {
+                    BaseObject object = mock();
+                    when(object.getStringValue("level")).thenReturn(value);
+                    when(object.getDocumentReference()).thenReturn(DOCUMENT_REFERENCE);
+                    return object;
+                }
+            })
+            .toList();
+        when(document.getXObjects(CLASS_REFERENCE)).thenReturn(objects);
+
+        DocumentRequiredRights actual = this.documentRequiredRightsReader.readRequiredRights(document);
+
+        assertEquals(expected, actual);
+    }
+
+    static Stream<Arguments> getArguments()
+    {
+        return Stream.of(
+            Arguments.of(
+                false,
+                List.of(),
+                DocumentRequiredRights.EMPTY
+            ),
+            Arguments.of(
+                true,
+                List.of(),
+                new DocumentRequiredRights(true, Set.of())
+            ),
+            Arguments.of(
+                true,
+                List.of("programming"),
+                new DocumentRequiredRights(true, Set.of(new DocumentRequiredRight(Right.PROGRAM, null)))
+            ),
+            Arguments.of(
+                true,
+                List.of("edit"),
+                new DocumentRequiredRights(true, Set.of())
+            ),
+            Arguments.of(
+                true,
+                List.of("wiki_admin"),
+                new DocumentRequiredRights(true, Set.of(new DocumentRequiredRight(Right.ADMIN, EntityType.WIKI)))
+            ),
+            Arguments.of(
+                true,
+                Arrays.asList(null, "script"),
+                new DocumentRequiredRights(true, Set.of(new DocumentRequiredRight(Right.SCRIPT, EntityType.DOCUMENT)))
+            ),
+            Arguments.of(
+                true,
+                Arrays.asList(null, "admin", null),
+                new DocumentRequiredRights(true, Set.of(new DocumentRequiredRight(Right.ADMIN, EntityType.SPACE)))
+            )
+        );
+    }
+}
diff --git a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/testwikibuilding/LegacyTestWiki.java b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/testwikibuilding/LegacyTestWiki.java
index 0a03bc4596a8cb69677ac33f0fd241d06bdd8d29..e493946830e50fb621eb964d940dcca16e5504f9 100644
--- a/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/testwikibuilding/LegacyTestWiki.java
+++ b/xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-bridge/src/test/java/org/xwiki/security/authorization/testwikibuilding/LegacyTestWiki.java
@@ -1073,6 +1073,12 @@ public Object invoke(Invocation invocation)
                     allowing(mockedDocument)
                         .getXObjects(XWikiGroupsDocumentInitializer.XWIKI_GROUPS_DOCUMENT_REFERENCE);
                     will(returnValue(Collections.emptyList()));
+                    // TODO: implement support for returning other values to add test cases for required rights.
+                    allowing(mockedDocument).isEnforceRequiredRights();
+                    will(returnValue(false));
+                    allowing(mockedDocument)
+                        .getXObjects(with(equal(new LocalDocumentReference("XWiki", "RequiredRightClass"))));
+                    will(returnValue(List.of()));
                 }
             });
 
diff --git a/xwiki-platform-core/xwiki-platform-xar/xwiki-platform-xar-model/src/main/java/org/xwiki/xar/internal/model/XarDocumentModel.java b/xwiki-platform-core/xwiki-platform-xar/xwiki-platform-xar-model/src/main/java/org/xwiki/xar/internal/model/XarDocumentModel.java
index a49b99ceb5a542512c2969e7697146ee3ad895a9..703905e136f1a91762684e83cab04c1c6e2d167c 100644
--- a/xwiki-platform-core/xwiki-platform-xar/xwiki-platform-xar-model/src/main/java/org/xwiki/xar/internal/model/XarDocumentModel.java
+++ b/xwiki-platform-core/xwiki-platform-xar/xwiki-platform-xar-model/src/main/java/org/xwiki/xar/internal/model/XarDocumentModel.java
@@ -19,6 +19,8 @@
  */
 package org.xwiki.xar.internal.model;
 
+import org.xwiki.stability.Unstable;
+
 /**
  * @version $Id$
  * @since 5.4M1
@@ -61,12 +63,20 @@ public class XarDocumentModel
      */
     public static final String VERSION_15 = "1.5";
 
+    /**
+     * Introduce the concept of required right enforcement.
+     *
+     * @since 16.10.0RC1
+     */
+    @Unstable
+    public static final String VERSION_16 = "1.6";
+
     /**
      * The current version.
      * 
      * @since 9.0RC1
      */
-    public static final String VERSION_CURRENT = VERSION_15;
+    public static final String VERSION_CURRENT = VERSION_16;
 
     public static final String ELEMENT_DOCUMENT = "xwikidoc";
 
@@ -163,6 +173,12 @@ public class XarDocumentModel
      */
     public static final String ELEMENT_REVISION_ORIGINALMEDATAAUTHOR = "originalMetadataAuthor";
 
+    /**
+     * @since 16.10.0RC1
+     */
+    @Unstable
+    public static final String ELEMENT_ENFORCE_REQUIRED_RIGHTS = "enforceRequiredRights";
+
     public static final String ELEMENT_REVISION_COMMENT = "comment";
 
     public static final String ELEMENT_REVISION_MINOR = "minorEdit";