diff --git a/nuxeo-core-schema/src/main/java/org/nuxeo/ecm/core/schema/FacetNames.java b/nuxeo-core-schema/src/main/java/org/nuxeo/ecm/core/schema/FacetNames.java
--- a/nuxeo-core-schema/src/main/java/org/nuxeo/ecm/core/schema/FacetNames.java
+++ b/nuxeo-core-schema/src/main/java/org/nuxeo/ecm/core/schema/FacetNames.java
@@ -43,6 +43,8 @@
 
     public static final String BROWSE_VIA_SEARCH = "BrowseViaSearch";
 
+    public static final String HAS_RELATED_TEXT = "HasRelatedText";
+
     private FacetNames() {
     }
 
diff --git a/nuxeo-core-storage-sql/nuxeo-core-storage-sql-test/src/test/java/org/nuxeo/ecm/core/storage/sql/TestSQLRepositoryAPI.java b/nuxeo-core-storage-sql/nuxeo-core-storage-sql-test/src/test/java/org/nuxeo/ecm/core/storage/sql/TestSQLRepositoryAPI.java
--- a/nuxeo-core-storage-sql/nuxeo-core-storage-sql-test/src/test/java/org/nuxeo/ecm/core/storage/sql/TestSQLRepositoryAPI.java
+++ b/nuxeo-core-storage-sql/nuxeo-core-storage-sql-test/src/test/java/org/nuxeo/ecm/core/storage/sql/TestSQLRepositoryAPI.java
@@ -1812,7 +1812,8 @@
         assertFalse(doc.hasFacet(FacetNames.HIDDEN_IN_NAVIGATION));
         Set<String> baseFacets = new HashSet<String>(Arrays.asList(
                 FacetNames.DOWNLOADABLE, FacetNames.VERSIONABLE,
-                FacetNames.PUBLISHABLE, FacetNames.COMMENTABLE));
+                FacetNames.PUBLISHABLE, FacetNames.COMMENTABLE,
+                FacetNames.HAS_RELATED_TEXT));
         assertEquals(baseFacets, doc.getFacets());
         try {
             doc.setPropertyValue("age:age", "123");
diff --git a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLBaseProperty.java b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLBaseProperty.java
--- a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLBaseProperty.java
+++ b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLBaseProperty.java
@@ -17,12 +17,16 @@
 
 package org.nuxeo.ecm.core.storage.sql.coremodel;
 
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Set;
 
 import org.nuxeo.ecm.core.api.DocumentException;
 import org.nuxeo.ecm.core.model.Property;
 import org.nuxeo.ecm.core.schema.types.Type;
+import org.nuxeo.ecm.core.storage.sql.Model;
 
 /**
  * @author Florent Guillaume
@@ -33,9 +37,30 @@
 
     protected final boolean readonly;
 
-    public SQLBaseProperty(Type type, boolean readonly) {
+    public static final String DC_ISSUED = "dc:issued";
+
+    // authorize update of aggregated text from related resources (comments,
+    // annotations, tags, ...)
+    public static final String RELATED_TEXT_RESOURCES = "relatedtextresources";
+
+    protected static final Set<String> VERSION_WRITABLE_PROPS = new HashSet<String>(
+            Arrays.asList( //
+                    Model.FULLTEXT_JOBID_PROP, Model.FULLTEXT_BINARYTEXT_PROP, //
+                    Model.MISC_LIFECYCLE_STATE_PROP, //
+                    Model.LOCK_OWNER_PROP, //
+                    Model.LOCK_CREATED_PROP, //
+                    DC_ISSUED, //
+                    RELATED_TEXT_RESOURCES //
+            ));
+
+    public SQLBaseProperty(Type type, String name, boolean readonly) {
         this.type = type;
-        this.readonly = readonly;
+        if (VERSION_WRITABLE_PROPS.contains(name)) {
+            // special handling of system properties
+            this.readonly = false;
+        } else {
+            this.readonly = readonly;
+        }
     }
 
     // for SQLDocument
diff --git a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLCollectionProperty.java b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLCollectionProperty.java
--- a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLCollectionProperty.java
+++ b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLCollectionProperty.java
@@ -48,7 +48,7 @@
      */
     public SQLCollectionProperty(SQLSession session,
             CollectionProperty property, ListType type, boolean readonly) {
-        super(type, readonly);
+        super(type, property != null ? property.getName() : null, readonly);
         this.session = session;
         this.property = property;
         this.isArray = type == null || type.isArray();
diff --git a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLComplexListProperty.java b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLComplexListProperty.java
--- a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLComplexListProperty.java
+++ b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLComplexListProperty.java
@@ -49,7 +49,7 @@
      */
     public SQLComplexListProperty(Node node, ListType type, String name,
             SQLSession session, boolean readonly) {
-        super(type, readonly);
+        super(type, name, readonly);
         this.node = node;
         this.name = name;
         this.session = session;
diff --git a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLComplexProperty.java b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLComplexProperty.java
--- a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLComplexProperty.java
+++ b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLComplexProperty.java
@@ -56,7 +56,7 @@
      */
     public SQLComplexProperty(Node node, ComplexType type, SQLSession session,
             boolean readonly) {
-        super(type, readonly);
+        super(type, node != null ? node.getName() : null, readonly);
         this.node = node;
         this.session = session;
     }
@@ -119,7 +119,8 @@
 
     @Override
     public Property getProperty(String name) throws DocumentException {
-        return session.makeProperty(node, name, (ComplexType) type, null, readonly);
+        return session.makeProperty(node, name, (ComplexType) type, null,
+                readonly);
     }
 
     @Override
diff --git a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLDocumentVersion.java b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLDocumentVersion.java
--- a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLDocumentVersion.java
+++ b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLDocumentVersion.java
@@ -254,8 +254,7 @@
     @Override
     public void setPropertyValue(String name, Object value)
             throws DocumentException {
-        if (readonly
-                && !SQLSimpleProperty.VERSION_WRITABLE_PROPS.contains(name)) {
+        if (readonly && !VERSION_WRITABLE_PROPS.contains(name)) {
             throw new VersionNotModifiableException(String.format(
                     "Cannot set property on a version: %s = %s", name, value));
         }
diff --git a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLSimpleProperty.java b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLSimpleProperty.java
--- a/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLSimpleProperty.java
+++ b/nuxeo-core-storage-sql/nuxeo-core-storage-sql/src/main/java/org/nuxeo/ecm/core/storage/sql/coremodel/SQLSimpleProperty.java
@@ -18,14 +18,10 @@
 package org.nuxeo.ecm.core.storage.sql.coremodel;
 
 import java.io.Serializable;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
 
 import org.nuxeo.ecm.core.api.DocumentException;
 import org.nuxeo.ecm.core.schema.types.Type;
 import org.nuxeo.ecm.core.storage.StorageException;
-import org.nuxeo.ecm.core.storage.sql.Model;
 import org.nuxeo.ecm.core.storage.sql.SimpleProperty;
 
 /**
@@ -36,18 +32,6 @@
  */
 public class SQLSimpleProperty extends SQLBaseProperty {
 
-    public static final String DC_ISSUED = "dc:issued";
-
-    protected static final Set<String> VERSION_WRITABLE_PROPS = new HashSet<String>(
-            Arrays.asList( //
-                    Model.FULLTEXT_JOBID_PROP,
-                    Model.FULLTEXT_BINARYTEXT_PROP, //
-                    Model.MISC_LIFECYCLE_STATE_PROP, //
-                    Model.LOCK_OWNER_PROP, //
-                    Model.LOCK_CREATED_PROP, //
-                    DC_ISSUED //
-            ));
-
     private final SimpleProperty property;
 
     /**
@@ -55,7 +39,7 @@
      */
     public SQLSimpleProperty(SimpleProperty property, Type type,
             boolean readonly) {
-        super(type, readonly);
+        super(type, property.getName(), readonly);
         this.property = property;
     }
 
diff --git a/nuxeo-core/src/main/resources/OSGI-INF/CoreExtensions.xml b/nuxeo-core/src/main/resources/OSGI-INF/CoreExtensions.xml
--- a/nuxeo-core/src/main/resources/OSGI-INF/CoreExtensions.xml
+++ b/nuxeo-core/src/main/resources/OSGI-INF/CoreExtensions.xml
@@ -30,6 +30,7 @@
     <schema name="files" src="schema/files.xsd"/>
     <schema name="note" src="schema/note.xsd"/>
     <schema name="domain" src="schema/domain.xsd"/>
+    <schema name="relatedtext" src="schema/relatedtext.xsd"/>
 
     <schema name="publishing" prefix="publish" src="schema/publishing.xsd" />
     <schema name="webcontainer" prefix="webc" src="schema/webcontainer.xsd"/>
@@ -60,6 +61,12 @@
     <facet name="SuperSpace" />
     <facet name="HiddenInNavigation" />
 
+    <!-- facet to be used for full-text indexing of related text content
+      (e.g. comments, annotations, tags...) -->
+    <facet name="HasRelatedText">
+      <schema name="relatedtext" />
+    </facet>
+
     <doctype name="Folder" extends="Document">
       <schema name="common"/>
       <schema name="dublincore"/>
@@ -153,6 +160,7 @@
       <facet name="Versionable"/>
       <facet name="Publishable"/>
       <facet name="Commentable"/>
+      <facet name="HasRelatedText"/>
     </doctype>
 
     <doctype name="Note" extends="Document">
@@ -164,6 +172,7 @@
       <facet name="Versionable"/>
       <facet name="Publishable"/>
       <facet name="Commentable"/>
+      <facet name="HasRelatedText"/>
     </doctype>
 
   </extension>
diff --git a/nuxeo-core/src/main/resources/schema/relatedtext.xsd b/nuxeo-core/src/main/resources/schema/relatedtext.xsd
new file mode 100644
--- /dev/null
+++ b/nuxeo-core/src/main/resources/schema/relatedtext.xsd
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+
+<xs:schema targetNamespace="http://www.nuxeo.org/ecm/schemas/relatedtext/"
+  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:nxs="http://www.nuxeo.org/ecm/schemas/relatedtext/">
+
+  <!-- schema to be used for full-text indexing of related annotations, tags
+    and comments -->
+
+  <xs:element name="relatedtextresources" type="nxs:resources" />
+
+  <xs:complexType name="resources">
+    <xs:sequence>
+      <xs:element name="item" type="nxs:resource" minOccurs="0"
+        maxOccurs="unbounded" />
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="resource">
+    <xs:sequence>
+      <xs:element name="resourceid" type="xs:string" minOccurs="0"
+        maxOccurs="unbounded" />
+      <xs:element name="text" type="xs:string" minOccurs="0"
+        maxOccurs="unbounded" />
+    </xs:sequence>
+  </xs:complexType>
+
+</xs:schema>
+
+
