diff --git a/docs/Running.adoc b/docs/Running.adoc
index 33be156..0d5b206 100644
--- a/docs/Running.adoc
+++ b/docs/Running.adoc
@@ -180,20 +180,3 @@ Invalid:
        ]
    }
 ```
-
-=== Syncing Users and Groups
-
-Grabbit has support for syncing users and groups. One *important note* about syncing users is that you must take care to avoid syncing the _admin user_.
-Jackrabbit will not allow modification of the admin user, so Grabbit will fail on a job that attempts to do so. You can find the path of your admin user
-on your data-warehouse instance or other source instance; and add it as an exclude path as so:
-
-```
- pathConfigurations :
-     -
-       path : /home/groups
-     -
-       path : /home/users
-       excludePaths:
-         - k/ki9zhpzfe    #Admin user
-```
-
diff --git a/src/main/groovy/com/twcable/grabbit/client/batch/ClientBatchJobExecutionListener.groovy b/src/main/groovy/com/twcable/grabbit/client/batch/ClientBatchJobExecutionListener.groovy
index 7305aa8..5497f5d 100644
--- a/src/main/groovy/com/twcable/grabbit/client/batch/ClientBatchJobExecutionListener.groovy
+++ b/src/main/groovy/com/twcable/grabbit/client/batch/ClientBatchJobExecutionListener.groovy
@@ -16,7 +16,7 @@
 
 package com.twcable.grabbit.client.batch
 
-import com.twcable.grabbit.jcr.JcrUtil
+import com.twcable.grabbit.jcr.JCRUtil
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
 import org.apache.sling.jcr.api.SlingRepository
@@ -58,7 +58,7 @@ class ClientBatchJobExecutionListener implements JobExecutionListener {
     void beforeJob(JobExecution jobExecution) {
         log.debug "SlingRepository : ${slingRepository}"
         final clientUsername = jobExecution.jobParameters.getString(ClientBatchJob.CLIENT_USERNAME)
-        final Session session = JcrUtil.getSession(slingRepository, clientUsername)
+        final Session session = JCRUtil.getSession(slingRepository, clientUsername)
 
         ClientBatchJobContext.setSession(session)
         log.info "Starting job : ${jobExecution}\n\n"
diff --git a/src/main/groovy/com/twcable/grabbit/client/batch/steps/validation/ValidJobDecider.groovy b/src/main/groovy/com/twcable/grabbit/client/batch/steps/validation/ValidJobDecider.groovy
index 5921c61..e911c5f 100644
--- a/src/main/groovy/com/twcable/grabbit/client/batch/steps/validation/ValidJobDecider.groovy
+++ b/src/main/groovy/com/twcable/grabbit/client/batch/steps/validation/ValidJobDecider.groovy
@@ -17,17 +17,15 @@ package com.twcable.grabbit.client.batch.steps.validation
 
 import com.twcable.grabbit.client.batch.ClientBatchJob
 import com.twcable.grabbit.client.batch.ClientBatchJobContext
+import com.twcable.grabbit.jcr.JCRUtil
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
+import javax.jcr.Session
 import org.springframework.batch.core.JobExecution
 import org.springframework.batch.core.StepExecution
 import org.springframework.batch.core.job.flow.FlowExecutionStatus
 import org.springframework.batch.core.job.flow.JobExecutionDecider
 
-import javax.jcr.PathNotFoundException
-import javax.jcr.RepositoryException
-import javax.jcr.Session
-
 /**
  * This class serves as a validation gate for jobs in-flight.  It should be the first step on the client when running a job to determine
  * if the job is job that is safe, and valid to execute.
@@ -57,29 +55,14 @@ class ValidJobDecider implements JobExecutionDecider {
     @Override
     FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
         String jobPath = jobExecution.jobParameters.getString(ClientBatchJob.PATH)
-        //For processing, remove trailing /
-        jobPath = jobPath.replaceFirst(/\/$/, '')
-        //Get the parent's path (if applicable) and determine if it exists already
-        final parts = jobPath.split('/')
-        //No parent, so nothing to worry about
-        if(parts.length <= 2) return JOB_VALID
-
-        final parentPath = parts[0..-2].join('/')
-        final Session session = theSession()
-        try {
-            session.getNode(parentPath)
-        } catch(PathNotFoundException pathException) {
-            log.warn "${jobPath} is not a valid job path.  Make sure a parent is synched or created before this job is run"
-            log.debug pathException.toString()
-            return JOB_INVALID
+        if(JCRUtil.writingToExistingNode(jobPath, theSession())) {
+            log.debug "${ValidJobDecider.class.canonicalName} Job determined to be valid for job path ${jobPath}"
+            return JOB_VALID
         }
-        catch(RepositoryException repoException) {
-            log.error "${RepositoryException.class.canonicalName} Something went wrong when accessing the repository at ${this.class.canonicalName} for job path ${jobPath}!"
-            log.error repoException.toString()
+        else {
+            log.warn "${jobPath} is not a valid job path.  Make sure a parent is synched or created before this job is run"
             return JOB_INVALID
         }
-        log.debug "${ValidJobDecider.class.canonicalName} Job determined to be valid for job path ${jobPath}"
-        return JOB_VALID
     }
 
 }
diff --git a/src/main/groovy/com/twcable/grabbit/jcr/ACLProtoNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/ACLProtoNodeDecorator.groovy
index d53fd33..369d632 100644
--- a/src/main/groovy/com/twcable/grabbit/jcr/ACLProtoNodeDecorator.groovy
+++ b/src/main/groovy/com/twcable/grabbit/jcr/ACLProtoNodeDecorator.groovy
@@ -105,7 +105,7 @@ class ACLProtoNodeDecorator extends ProtoNodeDecorator {
         final String principalName = getPrincipalName(aceNode)
         Principal principal = getPrincipal(session, principalName)
         if(principal == null) {
-            log.warn "Principal for name ${principalName} does not exist, or is not accessible. Can not write ACE/ACL information."
+            log.warn "Principal for name ${principalName} does not exist, or is not accessible. Can not write ACE/ACL information for this principal on ${getParentPath()}. If this principal is currently being synched, it may not be accessible."
             return
         }
         Privilege[] privileges = getPrivilegeNames(aceNode).collect { String privilegeName ->
@@ -166,7 +166,7 @@ class ACLProtoNodeDecorator extends ProtoNodeDecorator {
         final ProtoPropertyDecorator privilegeProperty = node.propertiesList.collect { new ProtoPropertyDecorator(it) }.find { ProtoPropertyDecorator property ->
             property.isPrivilege()
         }
-        return privilegeProperty.getPropertyValues().collect { Value value -> value.string }.toArray() as String[]
+        return privilegeProperty.getStringValues().toArray() as String[]
     }
 
 
diff --git a/src/main/groovy/com/twcable/grabbit/jcr/AuthorizableProtoNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/AuthorizableProtoNodeDecorator.groovy
index c264bfb..1f54a0f 100644
--- a/src/main/groovy/com/twcable/grabbit/jcr/AuthorizableProtoNodeDecorator.groovy
+++ b/src/main/groovy/com/twcable/grabbit/jcr/AuthorizableProtoNodeDecorator.groovy
@@ -25,7 +25,6 @@ import groovy.util.logging.Slf4j
 import java.lang.reflect.Field
 import java.lang.reflect.Method
 import java.lang.reflect.ReflectPermission
-import java.util.regex.Pattern
 import javax.annotation.Nonnull
 import javax.jcr.Session
 import org.apache.jackrabbit.api.security.user.Authorizable
@@ -35,7 +34,6 @@ import org.apache.jackrabbit.api.security.user.UserManager
 import org.apache.jackrabbit.value.StringValue
 import org.apache.sling.jcr.base.util.AccessControlUtil
 
-
 /**
  * This class wraps a serialized node that represents an Authorizable. Authorizables are special system protected nodes, that can only be written under certain
  * trees, and can not be written directly by a client.
@@ -57,10 +55,14 @@ class AuthorizableProtoNodeDecorator extends ProtoNodeDecorator {
             throw new InsufficientGrabbitPrivilegeException("JVM Permissions needed by Grabbit to sync Users/Groups were not found. See log for specific permissions needed, and add these to your security manager; or do not sync users and groups." +
                                                             "Unfortunately, the way Jackrabbit goes about certain things requires us to do a bit of hacking in order to sync Authorizables securely, and efficiently.")
         }
-        Authorizable existingAuthorizable = findAuthorizable(session)
+        //the administrator is a special user that Jackrabbit will not let us mess with.
+        if(getAuthorizableID() == 'admin') {
+            return new JCRNodeDecorator(session.getNode(findAuthorizable(session, 'admin').getPath()))
+        }
+
+        Authorizable existingAuthorizable = findAuthorizable(session, getAuthorizableID())
         Authorizable newAuthorizable = existingAuthorizable ? updateAuthorizable(existingAuthorizable, session) : createNewAuthorizable(session)
-        writeAuthorizablePieces(newAuthorizable, session)
-        return new JCRNodeDecorator(session.getNode(newAuthorizable.getPath()))
+        return new JCRNodeDecorator(session.getNode(newAuthorizable.getPath()), getID())
     }
 
 
@@ -86,11 +88,20 @@ class AuthorizableProtoNodeDecorator extends ProtoNodeDecorator {
                 setPasswordForUser(newUser, session)
             }
             session.save()
+            writeMandatoryPieces(session, newUser.getPath())
             return newUser
         }
-        final Group group = userManager.createGroup(authorizableID, new AuthorizablePrincipal(authorizableID), getParentPath())
+        final Group newGroup = userManager.createGroup(authorizableID, new AuthorizablePrincipal(authorizableID), getParentPath())
+        /*
+         * Write all mandatory pieces, and find those that are authorizables. We then need to see if any of them have membership in this group, and add them.
+         */
+        final Collection<JCRNodeDecorator> authorizablePieces = writeMandatoryPieces(session, newGroup.getPath()).findAll { it.isAuthorizableType() }
+        final Collection<JCRNodeDecorator> members = authorizablePieces.findAll { getMembershipIDs().contains(it.getTransferredID()) }
+        members.each { JCRNodeDecorator member ->
+            newGroup.addMember(member as Authorizable)
+        }
         session.save()
-        return group
+        return newGroup
     }
 
 
@@ -100,28 +111,25 @@ class AuthorizableProtoNodeDecorator extends ProtoNodeDecorator {
      * @return new instance of updated authorizable
      */
     private Authorizable updateAuthorizable(final Authorizable authorizable, final Session session) {
+        //We get all the declared groups of this authorizable so that we can add them back to the new, updated authorizable
+        final Collection<Group> declaredGroups = authorizable.declaredMemberOf().toList()
+        for(Group group : declaredGroups) {
+            group.removeMember(authorizable)
+        }
         authorizable.remove()
         session.save()
-        createNewAuthorizable(session)
-    }
-
-
-    /**
-     * Authorizable pieces (nodes that live under Authorizables - profile, preferences, etc) get sent with the authorizable node instead of streamed independently because we do not know the client's new
-     * authorizable UUID node name at runtime. In other words, authorizables can live under different node names from server to server
-     */
-    private void writeAuthorizablePieces(final Authorizable authorizable, final Session session) {
-        innerProtoNode.mandatoryChildNodeList.each {
-            //We replace the incoming server authorizable path, with the new authorizable path
-            createFrom(it, it.name.replaceFirst(Pattern.quote(getName()), authorizable.getPath())).writeToJcr(session)
+        final Authorizable newAuthorizable = createNewAuthorizable(session)
+        for(Group group: declaredGroups) {
+            group.addMember(newAuthorizable)
         }
         session.save()
+        return newAuthorizable
     }
 
 
-    private Authorizable findAuthorizable(final Session session) {
+    private Authorizable findAuthorizable(final Session session, final String authorizableID) {
         final UserManager userManager = getUserManager(session)
-        return userManager.getAuthorizable(getAuthorizableID())
+        return userManager.getAuthorizable(authorizableID)
     }
 
 
@@ -135,6 +143,11 @@ class AuthorizableProtoNodeDecorator extends ProtoNodeDecorator {
     }
 
 
+    private Collection<String> getMembershipIDs() {
+        return hasProperty('rep:members') ? getStringValuesFrom('rep:members') : []
+    }
+
+
     /**
      * Some JVM's have a SecurityManager set, which based on configuration, can potentially inhibit our hack {@code setPasswordForUser(User, Session)} from working.
      * We need to check security permissions before proceeding
@@ -245,13 +258,4 @@ class AuthorizableProtoNodeDecorator extends ProtoNodeDecorator {
         */
         setPasswordMethod.invoke(userManagerDelegate, getTreeMethod.invoke(authorizable), getAuthorizableID(), getStringValueFrom('rep:password'), false)
     }
-
-
-    /**
-     * An instance wrapper for ease of mocking
-     * @see super.createFrom
-     */
-    ProtoNodeDecorator createFrom(final ProtoNode protoNode, final String nameOverride) {
-        super.createFrom(protoNode, nameOverride)
-    }
 }
diff --git a/src/main/groovy/com/twcable/grabbit/jcr/DefaultProtoNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/DefaultProtoNodeDecorator.groovy
index 2d6dc8f..7817000 100644
--- a/src/main/groovy/com/twcable/grabbit/jcr/DefaultProtoNodeDecorator.groovy
+++ b/src/main/groovy/com/twcable/grabbit/jcr/DefaultProtoNodeDecorator.groovy
@@ -19,11 +19,12 @@ import com.twcable.grabbit.proto.NodeProtos.Node as ProtoNode
 import com.twcable.grabbit.proto.NodeProtos.Value as ProtoValue
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
-import java.util.regex.Pattern
 import javax.annotation.Nonnull
 import javax.jcr.Node as JCRNode
 import javax.jcr.Session
+import javax.jcr.Value
 import org.apache.jackrabbit.commons.JcrUtils
+import org.apache.jackrabbit.value.StringValue
 
 
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES
@@ -49,16 +50,34 @@ class DefaultProtoNodeDecorator extends ProtoNodeDecorator {
         if(mixinProperty) {
             addMixins(mixinProperty, jcrNode)
         }
-        //Then add other properties
-        writableProperties.each { it.writeToNode(jcrNode) }
 
-        if(innerProtoNode.mandatoryChildNodeList && innerProtoNode.mandatoryChildNodeList.size() > 0) {
-            for(ProtoNode childNode: innerProtoNode.mandatoryChildNodeList) {
-                //Mandatory children must inherit any name overrides from their parent (if they exist)
-                createFrom(childNode, childNode.getName().replaceFirst(Pattern.quote(innerProtoNode.name), getName())).writeToJcr(session)
+        final Collection<ProtoPropertyDecorator> referenceTypeProperties = writableProperties.findAll { it.isReferenceType() }
+        final Collection<ProtoPropertyDecorator> nonReferenceTypeProperties = writableProperties.findAll { !it.isReferenceType() }
+
+        //These can be written now. Reference properties can be written after we write the referenced nodes
+        nonReferenceTypeProperties.each { it.writeToNode(jcrNode) }
+
+        final Collection<JCRNodeDecorator> referenceables = writeMandatoryPieces(session, getName()).findAll { it.isReferenceable() }
+
+        /*
+         * Nodes that are referenced from reference properties are written above in writeMandatoryPieces(). We can now map each
+         * reference pointer to a transferred id from a node above, and write the pointer with a mapped nodes new identifier.
+         * The transferred id is what the identifier was on sending server, and the current identifier is what it is now that it is
+          * written to this server. Identifiers only apply to referenceable nodes (i.e nodes with mix:referenceable)
+         */
+        referenceTypeProperties.each { ProtoPropertyDecorator property ->
+            final Collection<Value> newReferenceIDValues = property.getStringValues().findResults { String referenceID ->
+                final JCRNodeDecorator match = referenceables.find { it.transferredID == referenceID }
+                if(match) {
+                    return new StringValue(match.getIdentifier())
+                }
+            } as Collection<Value>
+            if(!newReferenceIDValues.isEmpty()) {
+                property.writeToNode(jcrNode, (newReferenceIDValues.toArray() as Value[]))
             }
         }
-        return new JCRNodeDecorator(jcrNode)
+
+        return new JCRNodeDecorator(jcrNode, getID())
     }
 
 
diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy
index 61aa8be..138a2b9 100644
--- a/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy
+++ b/src/main/groovy/com/twcable/grabbit/jcr/JCRNodeDecorator.groovy
@@ -27,14 +27,21 @@ import javax.jcr.Node as JCRNode
 import javax.jcr.PathNotFoundException
 import javax.jcr.Property as JcrProperty
 import javax.jcr.RepositoryException
+import javax.jcr.Session
+import javax.jcr.Value as JcrValue
 import javax.jcr.nodetype.ItemDefinition
+import org.apache.jackrabbit.api.security.user.Authorizable
+import org.apache.jackrabbit.api.security.user.UserManager
 import org.apache.jackrabbit.commons.flat.TreeTraverser
 import org.apache.jackrabbit.value.DateValue
+import org.apache.sling.jcr.base.util.AccessControlUtil
+import org.slf4j.Logger
 
 
 import static org.apache.jackrabbit.JcrConstants.JCR_CREATED
 import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE
+import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE
 import static org.apache.jackrabbit.commons.flat.TreeTraverser.ErrorHandler
 import static org.apache.jackrabbit.commons.flat.TreeTraverser.InclusionPolicy
 import static org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants.AC_NODETYPE_NAMES
@@ -47,25 +54,42 @@ class JCRNodeDecorator {
     @Delegate
     JCRNode innerNode
 
-    private final Collection<JcrPropertyDecorator> properties
+    private final Collection<JCRPropertyDecorator> wrappedProperties
 
     //Evaluated in a lazy fashion
     private Collection<JCRNodeDecorator> immediateChildNodes
     private List<JCRNodeDecorator> childNodeList
 
+    private final String transferredID
+
 
     JCRNodeDecorator(@Nonnull JCRNode node) {
+        this(node, null)
+    }
+
+
+    JCRNodeDecorator(@Nonnull JCRNode node, @Nullable String transferredID) {
         if(!node) throw new IllegalArgumentException("node must not be null!")
         this.innerNode = node
         Collection<JcrProperty> innerProperties = node.properties.toList()
-        this.properties = innerProperties.collect { JcrProperty property ->
-            new JcrPropertyDecorator(property, this)
+        this.wrappedProperties = innerProperties.collect { JcrProperty property ->
+            new JCRPropertyDecorator(property, this)
         }
+        this.transferredID = transferredID
     }
 
 
+    private Collection<JCRPropertyDecorator> getWrappedProperties() { return wrappedProperties }
+
+
     /**
-     * @return this node's immediate children, empty if none
+     * @return an identifier for this node on a sending server. Not all wrapped nodes will have this. Will return null if it does not exist
+     */
+    String getTransferredID() { return transferredID }
+
+
+    /**
+     * @return this node's immediate children (depth 1), empty if none
      */
     Collection<JCRNodeDecorator> getImmediateChildNodes() {
         if(!immediateChildNodes) {
@@ -74,7 +98,9 @@ class JCRNodeDecorator {
         return immediateChildNodes
     }
 
-
+    /**
+     * @return this node's children via pre-order traversal.
+     */
     List<JCRNodeDecorator> getChildNodeList() {
         if(!childNodeList) {
             childNodeList = (getChildNodeIterator().collect { JCRNode node -> new JCRNodeDecorator(node) } ?: []) as List<JCRNodeDecorator>
@@ -83,10 +109,6 @@ class JCRNodeDecorator {
     }
 
 
-    Iterator<JCRNode> getChildNodeIterator() {
-        return TreeTraverser.nodeIterator(innerNode, ErrorHandler.IGNORE, new NoRootInclusionPolicy(this))
-    }
-
 
     void setLastModified() {
         final lastModified = new DateValue(Calendar.instance)
@@ -104,19 +126,25 @@ class JCRNodeDecorator {
 
 
     /**
-    * Identify all required child nodes
+    * Identify all required child nodes. This may include any mandatory nodes per definition, associated nodes that are required to write this node info on another server,
+    * and nodes that are referenced via this node's weak/strong reference pointers
     * @return list of immediate required child nodes that must be transported with this node, or an empty collection if no required nodes
     */
     @Nullable
     Collection<JCRNodeDecorator> getRequiredChildNodes() {
+        final Collection<JCRNodeDecorator> requiredNodes = []
         if(isAuthorizableType()){
-            return getChildNodeList().findAll { JCRNodeDecorator childJcrNode -> !childJcrNode.isLoginToken() && !childJcrNode.isACType() }
+            requiredNodes.addAll(getChildNodeList().findAll { JCRNodeDecorator childJcrNode -> !childJcrNode.isLoginToken() && !childJcrNode.isACType() })
         }
         else if(isRepACLType()) {
             //Send all ACE parts underneath the ACL as required nodes
-            return getChildNodeList()
+            requiredNodes.addAll(getChildNodeList())
+        }
+        else {
+            requiredNodes.addAll(getMandatoryChildren())
         }
-        return getMandatoryChildren()
+        requiredNodes.addAll(referencedNodesFrom(requiredNodes + this))
+        return requiredNodes
     }
 
 
@@ -125,6 +153,30 @@ class JCRNodeDecorator {
     }
 
 
+    /**
+     * Find any weak or strong references on this collection of nodes, and attempt to find their nodes
+     * @return any nodes we can find through references
+     */
+    private Collection<JCRNodeDecorator> referencedNodesFrom(Collection<JCRNodeDecorator> nodes) {
+        final Collection<JCRPropertyDecorator> referenceProperties = nodes.collectMany { JCRNodeDecorator node ->
+            /**
+             * Find all references that are transferable. We don't want to send referenced nodes that belong to a protected property that are not being transferred back to the client,
+             * such as version storage entries
+             */
+            return node.getWrappedProperties().findAll { JCRPropertyDecorator property -> property.isReferenceType() && property.isTransferable() }
+        }
+        return referenceProperties.collectMany { JCRPropertyDecorator property ->
+            property.values.toList().findResults { JcrValue value ->
+                try {
+                    return new JCRNodeDecorator(getSession().getNodeByIdentifier(value.string))
+                } catch(ItemNotFoundException ex) {
+                    _log().info "Tried following reference ${value.string} from ${getInnerNode().path}, but this node does not exist any longer. Skipping"
+                }
+            }
+        } as Collection<JCRNodeDecorator>
+    }
+
+
     /**
      * Some nodes must be saved together, per node definition
      */
@@ -151,13 +203,14 @@ class JCRNodeDecorator {
         return definition.isMandatory()
     }
 
-    /**
-     * Build node and "only" mandatory child nodes
-     */
+
     @Nonnull
      ProtoNode toProtoNode() {
         final ProtoNodeBuilder protoNodeBuilder = ProtoNode.newBuilder()
         protoNodeBuilder.setName(path)
+        if(isNodeType(MIX_REFERENCEABLE)) {
+            protoNodeBuilder.setIdentifier(getIdentifier())
+        }
         protoNodeBuilder.addAllProperties(getProtoProperties())
         requiredChildNodes.each {
             protoNodeBuilder.addMandatoryChildNode(it.toProtoNode())
@@ -165,15 +218,14 @@ class JCRNodeDecorator {
         return protoNodeBuilder.build()
     }
 
-    /**
-     * @return resulting collection of transferable proto properties collected from jcrNode
-     */
+
     @Nonnull
     private Collection<ProtoProperty> getProtoProperties() {
-        final Collection<JcrPropertyDecorator> transferableProperties = properties.findAll{ it.isTransferable() }
+        final Collection<JCRPropertyDecorator> transferableProperties = getWrappedProperties().findAll{ it.isTransferable() }
         return transferableProperties.collect{ it.toProtoProperty() }
     }
 
+
     /**
      * Returns the "jcr:lastModified", "cq:lastModified" or "jcr:created" date property
      * for current Jcr Node
@@ -243,15 +295,41 @@ class JCRNodeDecorator {
     }
 
 
+    boolean isReferenceable() {
+        return isNodeType(MIX_REFERENCEABLE)
+    }
+
+
+    /**
+     * For ease of mocking. Simply delegates to static accessor in AccessControlUtil
+     */
+    UserManager getUserManager(final Session session) {
+        return AccessControlUtil.getUserManager(session)
+    }
+
+
+    /**
+     * For ease of mocking
+     */
+    Iterator<JCRNode> getChildNodeIterator() {
+        return TreeTraverser.nodeIterator(innerNode, ErrorHandler.IGNORE, new NoRootInclusionPolicy(this))
+    }
+
+
     Object asType(Class clazz) {
         if(clazz == JCRNode) {
             return innerNode
         }
+        else if(clazz == Authorizable) {
+            if(!isAuthorizableType()) throw new ClassCastException('This class is not an Authorizable type. Check isAuthorizableType() before casting.')
+            return getUserManager(session).getAuthorizableByPath(getPath())
+        }
         else {
             super.asType(clazz)
         }
     }
 
+
     @Override
     boolean equals(Object obj) {
         if (this.is(obj)) return true
@@ -262,11 +340,20 @@ class JCRNodeDecorator {
         return this.hashCode() == that.hashCode()
     }
 
+
     @Override
     int hashCode() {
         return innerNode.getName().hashCode()
     }
 
+    /**
+     * @SL4J generated log property, and @Delegate conflict on accessing log sometimes within closures. This is to get around that
+     */
+    private static Logger _log() {
+        return log
+    }
+
+
     @CompileStatic
     private static class NoRootInclusionPolicy implements InclusionPolicy<JCRNode> {
 
diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JcrPropertyDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JcrPropertyDecorator.groovy
index b5aa8fa..3892e85 100644
--- a/src/main/groovy/com/twcable/grabbit/jcr/JcrPropertyDecorator.groovy
+++ b/src/main/groovy/com/twcable/grabbit/jcr/JcrPropertyDecorator.groovy
@@ -22,28 +22,39 @@ import com.twcable.grabbit.proto.NodeProtos.Value as ProtoValue
 import com.twcable.grabbit.proto.NodeProtos.Value.Builder as ProtoValueBuilder
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
-
 import javax.annotation.Nonnull
 import javax.jcr.Property as JCRProperty
 import javax.jcr.Value
 
+
 import static javax.jcr.PropertyType.BINARY
-import static org.apache.jackrabbit.JcrConstants.*
+import static javax.jcr.PropertyType.REFERENCE
+import static javax.jcr.PropertyType.WEAKREFERENCE
+import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE
 
 @CompileStatic
 @Slf4j
-class JcrPropertyDecorator {
+class JCRPropertyDecorator {
 
     @Delegate
     JCRProperty innerProperty
 
     private final JCRNodeDecorator nodeOwner
 
-    JcrPropertyDecorator(JCRProperty property, JCRNodeDecorator nodeOwner) {
+
+    JCRPropertyDecorator(JCRProperty property, JCRNodeDecorator nodeOwner) {
         this.innerProperty = property
         this.nodeOwner = nodeOwner
     }
 
+
+    boolean isReferenceType() {
+        return type == REFERENCE || type == WEAKREFERENCE
+    }
+
+
     /**
      * Determines if JCR Property object can be "rewritten" to the JCR. For example, we can not rewrite a node's
      * primary type; That is forbidden by the JCR spec.
@@ -67,6 +78,13 @@ class JcrPropertyDecorator {
         return !definition.isProtected()
     }
 
+
+    @Override
+    Value[] getValues() {
+        return (multiple ? innerProperty.values : [innerProperty.value]) as Value[]
+    }
+
+
     /**
      * Marshalls current Jcr Property to a ProtoProperty
      */
@@ -81,7 +99,6 @@ class JcrPropertyDecorator {
         }
         else {
             //Other property types can potentially have multiple values
-            final Value[] values = multiple ? values : [value] as Value[]
             values.each { Value value ->
                 propertyBuilder.addValues(valueBuilder.setStringValue(value.string))
             }
diff --git a/src/main/groovy/com/twcable/grabbit/jcr/JcrUtil.groovy b/src/main/groovy/com/twcable/grabbit/jcr/JcrUtil.groovy
index 74eaad2..61c7837 100644
--- a/src/main/groovy/com/twcable/grabbit/jcr/JcrUtil.groovy
+++ b/src/main/groovy/com/twcable/grabbit/jcr/JcrUtil.groovy
@@ -18,6 +18,8 @@ package com.twcable.grabbit.jcr
 
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
+import javax.jcr.PathNotFoundException
+import javax.jcr.RepositoryException
 import org.apache.sling.api.resource.ResourceResolver
 import org.apache.sling.api.resource.ResourceResolverFactory
 import org.apache.sling.jcr.api.SlingRepository
@@ -31,7 +33,7 @@ import javax.jcr.SimpleCredentials
  */
 @Slf4j
 @CompileStatic
-public class JcrUtil {
+public class JCRUtil {
 
     /**
      * This creates a JCR Session with the rights of the given user (by default
@@ -64,7 +66,7 @@ public class JcrUtil {
      * This handles creating the ResourceResolver with the rights of the given user (by default
      * that is 'anonymous') and does the needed clean up when the code block is finished.
      * <p/>
-     * <code>use(JcrUtil) {<br/>
+     * <code>use(JCRUtil) {<br/>
      * &nbsp slingRepository.withSession{Session session -><br/>
      * &nbsp &nbsp // do something with the Session<br/>
      * &nbsp }<br/>
@@ -112,7 +114,7 @@ public class JcrUtil {
      * This handles creating the ResourceResolver with the rights of the given user (by default
      * that is 'anonymous') and does the needed clean up when the code block is finished.
      * <p/>
-     * <code>use(JcrUtil) {<br/>
+     * <code>use(JCRUtil) {<br/>
      * &nbsp resourceResolverFactory.withResourceResolver {ResourceResolver resourceResolver -><br/>
      * &nbsp &nbsp // do something with the ResourceResolver<br/>
      * &nbsp }<br/>
@@ -146,7 +148,7 @@ public class JcrUtil {
      * This handles creating the ResourceResolver with the rights of the given user (by default
      * that is 'anonymous') and does the needed clean up when the code block is finished.
      * <p/>
-     * <code>use(JcrUtil) {<br/>
+     * <code>use(JCRUtil) {<br/>
      * &nbsp resourceResolverFactory.manageResourceResolver {ResourceResolver resourceResolver -><br/>
      * &nbsp &nbsp // do something with the ResourceResolver<br/>
      * &nbsp }<br/>
@@ -164,4 +166,30 @@ public class JcrUtil {
         return withResourceResolver(resolverFactory, "admin", closure)
     }
 
+    /**
+     * @return true if the node at the path being written is being written to an existing node
+     */
+    static boolean writingToExistingNode(@Nonnull final String pathBeingWritten, @Nonnull final Session session) {
+        //For processing, remove trailing /
+        final String thePath = pathBeingWritten.replaceFirst(/\/$/, '')
+        //Get the parent's path (if applicable) and determine if it exists already
+        final parts = thePath.split('/')
+        //No parent, so nothing to worry about
+        if(parts.length <= 2) return true
+
+        final String parentPath = parts[0..-2].join('/')
+        try {
+            session.getNode(parentPath)
+        } catch(PathNotFoundException pathException) {
+            log.debug pathException.toString()
+            return false
+        }
+        catch(RepositoryException repoException) {
+            log.error "${RepositoryException.class.canonicalName} Something went wrong when accessing the repository at ${this.class.canonicalName} for path ${pathBeingWritten}!"
+            log.error repoException.toString()
+            return false
+        }
+        return true
+    }
+
 }
diff --git a/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy
index 9cd437d..059713f 100644
--- a/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy
+++ b/src/main/groovy/com/twcable/grabbit/jcr/ProtoNodeDecorator.groovy
@@ -18,7 +18,7 @@ package com.twcable.grabbit.jcr
 
 import com.twcable.grabbit.proto.NodeProtos.Node as ProtoNode
 import groovy.transform.CompileStatic
-
+import java.util.regex.Pattern
 import javax.annotation.Nonnull
 import javax.jcr.Session
 
@@ -69,6 +69,17 @@ abstract class ProtoNodeDecorator {
         protoProperties.find { it.name == propertyName }.stringValue
     }
 
+
+    protected Collection<String> getStringValuesFrom(String propertyName) {
+        protoProperties.find { it.name == propertyName }.valuesList.collect { it.stringValue }
+    }
+
+
+    protected String getID() {
+        return innerProtoNode.getIdentifier()
+    }
+
+
     protected String getParentPath() {
         final pathTokens = getName().tokenize('/')
         //remove last index, as this is the Authorizable node name
@@ -76,6 +87,23 @@ abstract class ProtoNodeDecorator {
         return "/${pathTokens.join('/')}"
     }
 
+
+    protected Collection<JCRNodeDecorator> writeMandatoryPieces(final Session session, final String pathOverride) {
+        final Collection<JCRNodeDecorator> mandatoryPieces = innerProtoNode.mandatoryChildNodeList.collect {
+            //Mandatory nodes, if children of this node, must inherit any name overrides (if they exist)
+            _createFrom(it, it.getName().replaceFirst(Pattern.quote(getName()), pathOverride)).writeToJcr(session)
+        }
+        session.save()
+        return mandatoryPieces
+    }
+
+
+    //An instance wrapper for ease of mocking
+    ProtoNodeDecorator _createFrom(ProtoNode node, String nameOverride) {
+        return createFrom(node, nameOverride)
+    }
+
+
     @Override
     String getName() {
         nameOverride ?: innerProtoNode.getName()
diff --git a/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy b/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy
index ab809a5..b6568de 100644
--- a/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy
+++ b/src/main/groovy/com/twcable/grabbit/jcr/ProtoPropertyDecorator.groovy
@@ -28,6 +28,8 @@ import javax.jcr.ValueFormatException
 import org.apache.jackrabbit.value.ValueFactoryImpl
 
 
+import static javax.jcr.PropertyType.REFERENCE
+import static javax.jcr.PropertyType.WEAKREFERENCE
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE
 import static org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants.AC_NODETYPE_NAMES
@@ -52,13 +54,18 @@ class ProtoPropertyDecorator {
 
 
     void writeToNode(@Nonnull JCRNode node) {
+        writeToNode(node, getPropertyValues())
+    }
+
+
+    void writeToNode(final JCRNode node, Value[] values) {
         if(primaryType || mixinType) throw new IllegalStateException("Refuse to write jcr:primaryType or jcr:mixinType as normal properties.  These are not allowed")
         try {
             if (multiple) {
-                node.setProperty(this.name, getPropertyValues(), this.type)
+                node.setProperty(this.name, values, this.type)
             }
             else {
-                node.setProperty(this.name, getPropertyValue(), this.type)
+                node.setProperty(this.name, values.first(), this.type)
             }
         }
         catch (ValueFormatException ex) {
@@ -71,7 +78,7 @@ class ProtoPropertyDecorator {
             if(existingProperty.type != this.type || existingProperty.multiple ^ this.multiple) {
                 existingProperty.remove()
                 node.session.save()
-                this.writeToNode(node)
+                this.writeToNode(node, values)
                 log.debug "Resolve successful..."
             }
             else {
@@ -141,18 +148,13 @@ class ProtoPropertyDecorator {
     }
 
 
-    String getStringValue() {
-        getValue().stringValue
-    }
-
-
-    private ProtoValue getValue() {
-        innerProtoProperty.valuesList.first()
+    boolean isReferenceType() {
+        innerProtoProperty.type == REFERENCE || innerProtoProperty.type == WEAKREFERENCE
     }
 
 
     Value getPropertyValue() throws ValueFormatException {
-        getJCRValueFromProtoValue(getValue())
+        getPropertyValues().first()
     }
 
 
@@ -161,6 +163,16 @@ class ProtoPropertyDecorator {
     }
 
 
+    String getStringValue() {
+        getPropertyValue().string
+    }
+
+
+    Collection<String> getStringValues() {
+        getPropertyValues().collect { Value value -> value.string }
+    }
+
+
     private Value getJCRValueFromProtoValue(ProtoValue value) throws ValueFormatException {
 
         final valueFactory = ValueFactoryImpl.getInstance()
diff --git a/src/main/groovy/com/twcable/grabbit/server/GrabbitContentPullServlet.groovy b/src/main/groovy/com/twcable/grabbit/server/GrabbitContentPullServlet.groovy
index 4b1455a..bda4892 100644
--- a/src/main/groovy/com/twcable/grabbit/server/GrabbitContentPullServlet.groovy
+++ b/src/main/groovy/com/twcable/grabbit/server/GrabbitContentPullServlet.groovy
@@ -82,7 +82,10 @@ class GrabbitContentPullServlet extends SlingSafeMethodsServlet {
         //This user will be used to connect to JCR.
         //If the User is null, 'anonymous' will be used to connect to JCR.
         final serverUsername = request.remoteUser
-        serverService.getContentForRootPath(serverUsername, decodedPath, decodedExcludePaths ?: null,
-                afterDateString ?: null, response.outputStream)
+        serverService.getContentForRootPath(serverUsername,
+                                            decodedPath,
+                                            decodedExcludePaths ?: null,
+                                            afterDateString ?: null,
+                                            response.outputStream)
     }
 }
diff --git a/src/main/groovy/com/twcable/grabbit/server/batch/ServerBatchJob.groovy b/src/main/groovy/com/twcable/grabbit/server/batch/ServerBatchJob.groovy
index 91e5705..6e23152 100644
--- a/src/main/groovy/com/twcable/grabbit/server/batch/ServerBatchJob.groovy
+++ b/src/main/groovy/com/twcable/grabbit/server/batch/ServerBatchJob.groovy
@@ -75,7 +75,8 @@ class ServerBatchJob {
 
 
         PathBuilder andConfiguration(Iterator<Map.Entry<String, String>> namespacesIterator,
-                                     Iterator<JcrNode> nodeIterator, ServletOutputStream servletOutputStream) {
+                                     Iterator<JcrNode> nodeIterator,
+                                     ServletOutputStream servletOutputStream) {
             if (namespacesIterator == null) throw new IllegalArgumentException("namespacesIterator == null")
             if (nodeIterator == null) throw new IllegalArgumentException("nodeIterator == null")
             if (servletOutputStream == null) throw new IllegalArgumentException("servletOutputStream == null")
diff --git a/src/main/groovy/com/twcable/grabbit/server/batch/steps/jcrnodes/JcrNodesProcessor.groovy b/src/main/groovy/com/twcable/grabbit/server/batch/steps/jcrnodes/JcrNodesProcessor.groovy
index 42814c3..06f6867 100644
--- a/src/main/groovy/com/twcable/grabbit/server/batch/steps/jcrnodes/JcrNodesProcessor.groovy
+++ b/src/main/groovy/com/twcable/grabbit/server/batch/steps/jcrnodes/JcrNodesProcessor.groovy
@@ -35,10 +35,12 @@ class JcrNodesProcessor implements ItemProcessor<JcrNode, ProtoNode> {
 
     private String contentAfterDate
 
+
     void setContentAfterDate(String contentAfterDate) {
         this.contentAfterDate = contentAfterDate
     }
 
+
     /**
      * Converts a JCR Node to a {@link ProtoNode} object.
      * Returns null if current node does not need to be processed
diff --git a/src/main/groovy/com/twcable/grabbit/server/services/ServerService.groovy b/src/main/groovy/com/twcable/grabbit/server/services/ServerService.groovy
index 5bcf9f4..b368e17 100644
--- a/src/main/groovy/com/twcable/grabbit/server/services/ServerService.groovy
+++ b/src/main/groovy/com/twcable/grabbit/server/services/ServerService.groovy
@@ -25,5 +25,9 @@ interface ServerService {
      * @param path
      * @param servletOutputStream
      */
-    void getContentForRootPath(String serverUsername, String path, Collection<String> excludePaths, String afterDateString, ServletOutputStream servletOutputStream)
+    void getContentForRootPath(String serverUsername,
+                               String path,
+                               Collection<String> excludePaths,
+                               String afterDateString,
+                               ServletOutputStream servletOutputStream)
 }
diff --git a/src/main/groovy/com/twcable/grabbit/server/services/impl/DefaultServerService.groovy b/src/main/groovy/com/twcable/grabbit/server/services/impl/DefaultServerService.groovy
index acbae61..f154569 100644
--- a/src/main/groovy/com/twcable/grabbit/server/services/impl/DefaultServerService.groovy
+++ b/src/main/groovy/com/twcable/grabbit/server/services/impl/DefaultServerService.groovy
@@ -16,7 +16,7 @@
 
 package com.twcable.grabbit.server.services.impl
 
-import com.twcable.grabbit.jcr.JcrUtil
+import com.twcable.grabbit.jcr.JCRUtil
 import com.twcable.grabbit.server.batch.ServerBatchJob
 import com.twcable.grabbit.server.services.ExcludePathNodeIterator
 import com.twcable.grabbit.server.services.RootNodeWithMandatoryIterator
@@ -51,17 +51,19 @@ class DefaultServerService implements ServerService {
     ConfigurableApplicationContext configurableApplicationContext
 
 
+    @Override
     void getContentForRootPath(
             @Nullable String serverUsername,
             @Nonnull String path,
             @Nullable Collection<String> excludePaths,
-            @Nullable String afterDateString, @Nonnull ServletOutputStream servletOutputStream) {
+            @Nullable String afterDateString,
+            @Nonnull ServletOutputStream servletOutputStream) {
 
         if (path == null) throw new IllegalStateException("path == null")
         if (excludePaths == null) excludePaths = (Collection<String>) Collections.EMPTY_LIST
         if (servletOutputStream == null) throw new IllegalStateException("servletOutputStream == null")
 
-        JcrUtil.withSession(slingRepository, serverUsername) { Session session ->
+        JCRUtil.withSession(slingRepository, serverUsername) { Session session ->
             Iterator<JcrNode> nodeIterator
 
             //If the path is of type "/a/b/.", that means we should not do a recursive search of b's children
diff --git a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDao.groovy b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDao.groovy
index f12e06a..90d6bf9 100644
--- a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDao.groovy
+++ b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDao.groovy
@@ -16,7 +16,7 @@
 
 package com.twcable.grabbit.spring.batch.repository
 
-import com.twcable.grabbit.jcr.JcrUtil
+import com.twcable.grabbit.jcr.JCRUtil
 import com.twcable.grabbit.util.CryptoUtil
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
@@ -159,7 +159,7 @@ class JcrGrabbitExecutionContextDao extends AbstractJcrDao implements GrabbitExe
      */
     @Override
     protected void ensureRootResource() {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             if (!getOrCreateResource(resolver, JOB_EXECUTION_CONTEXT_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)) {
                 //create the Root Resource
                 throw new IllegalStateException("Cannot get or create RootResource for : ${JOB_EXECUTION_CONTEXT_ROOT}")
@@ -190,7 +190,7 @@ class JcrGrabbitExecutionContextDao extends AbstractJcrDao implements GrabbitExe
         if (!executionId) throw new IllegalArgumentException("executionId == null")
         if (!executionContext) throw new IllegalArgumentException("executionContext == null")
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final rootResource = getOrCreateResource(resolver, rootResourceName, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
 
             final existingResource = rootResource.children.asList().find { Resource resource ->
@@ -258,7 +258,7 @@ class JcrGrabbitExecutionContextDao extends AbstractJcrDao implements GrabbitExe
         if (!rootResourceName) throw new IllegalArgumentException("rootResourceName == null")
         if (!executionId) throw new IllegalArgumentException("executionId == null")
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final rootResource = getOrCreateResource(resolver, rootResourceName, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
 
             //find resource from the "rootResource" where the executionId property matches "executionid"
@@ -307,7 +307,7 @@ class JcrGrabbitExecutionContextDao extends AbstractJcrDao implements GrabbitExe
 
     @Override
     Collection<String> getJobExecutionContextPaths(Collection<String> jobExecutionResourcePaths) {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             Collection<String> jobExecutionContextPathsToRemove = []
             jobExecutionResourcePaths.each { String jobExecutionResourcePath ->
                 Resource jobExecutionResource = resolver.getResource(jobExecutionResourcePath)
@@ -332,7 +332,7 @@ class JcrGrabbitExecutionContextDao extends AbstractJcrDao implements GrabbitExe
 
     @Override
     Collection<String> getStepExecutionContextPaths(Collection<String> stepExecutionResourcePaths) {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             Collection<String> stepExecutionContextPathsToRemove = []
             stepExecutionResourcePaths.each { String stepExecutionResourcePath ->
                 Resource stepExecutionResource = resolver.getResource(stepExecutionResourcePath)
diff --git a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDao.groovy b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDao.groovy
index a0d4be8..9f12a2f 100644
--- a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDao.groovy
+++ b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDao.groovy
@@ -18,7 +18,7 @@ package com.twcable.grabbit.spring.batch.repository
 
 import com.twcable.grabbit.DateUtil
 import com.twcable.grabbit.client.batch.ClientBatchJob
-import com.twcable.grabbit.jcr.JcrUtil
+import com.twcable.grabbit.jcr.JCRUtil
 import com.twcable.grabbit.util.CryptoUtil
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
@@ -75,7 +75,7 @@ class JcrGrabbitJobExecutionDao extends AbstractJcrDao implements GrabbitJobExec
 
         //Create a new resource for the jobExecution (with the id)
         jobExecution.incrementVersion()
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final id = CryptoUtil.generateNextId()
             jobExecution.id = id
             Resource rootResource = getOrCreateResource(resolver, JOB_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
@@ -126,7 +126,7 @@ class JcrGrabbitJobExecutionDao extends AbstractJcrDao implements GrabbitJobExec
         if (!jobExecution) throw new IllegalArgumentException("jobExecution == null")
         if (!jobExecution.id) throw new IllegalArgumentException("jobExecution must have an id")
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final rootResource = getOrCreateResource(resolver, JOB_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
 
             //Get the Execution with jobExecution.id from jobExecution root resource
@@ -157,7 +157,7 @@ class JcrGrabbitJobExecutionDao extends AbstractJcrDao implements GrabbitJobExec
     List<JobExecution> findJobExecutions(@Nonnull final JobInstance jobInstance) {
         if (!jobInstance) throw new IllegalArgumentException("jobInstance == null")
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final Resource jobExecutionRootResource = getOrCreateResource(resolver, JOB_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
             List<Resource> resources = jobExecutionRootResource?.children?.asList()
             if (!resources) return Collections.EMPTY_LIST
@@ -255,7 +255,7 @@ class JcrGrabbitJobExecutionDao extends AbstractJcrDao implements GrabbitJobExec
     Set<JobExecution> findRunningJobExecutions(@Nonnull final String jobName) {
         if (!jobName) throw new IllegalArgumentException("jobName == null")
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final jobExecutionRoot = getOrCreateResource(resolver, JOB_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
 
             //find jobExecution root, then find all jobExecutions, then find the jobexecution
@@ -290,7 +290,7 @@ class JcrGrabbitJobExecutionDao extends AbstractJcrDao implements GrabbitJobExec
         if (!executionId) throw new IllegalArgumentException("executionId == null")
 
         //find jobExecution root, then find jobExecution with node name : "jobExecution${executionId}"
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final jobExecutionRoot = getOrCreateResource(resolver, JOB_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
             final jobExecutionResource = jobExecutionRoot?.children?.asList()?.find { Resource resource ->
                 final properties = resource.adaptTo(ValueMap)
@@ -370,7 +370,7 @@ class JcrGrabbitJobExecutionDao extends AbstractJcrDao implements GrabbitJobExec
      */
     @Override
     protected void ensureRootResource() {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             if (!getOrCreateResource(resolver, JOB_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)) {
                 //create the Root Resource
                 throw new IllegalStateException("Cannot get or create RootResource for : ${JOB_EXECUTION_ROOT}")
@@ -385,7 +385,7 @@ class JcrGrabbitJobExecutionDao extends AbstractJcrDao implements GrabbitJobExec
     @Override
     Collection<String> getJobExecutions(Collection<BatchStatus> batchStatuses) {
         String statusPredicate = batchStatuses.collect { "s.status = '${it}'" }.join(' or ')
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             String jobExecutionsQuery = "select * from [nt:unstructured] as s where " +
                     "ISDESCENDANTNODE(s,'${JOB_EXECUTION_ROOT}') AND ( ${statusPredicate} )"
             Collection<String> jobExecutions = resolver.findResources(jobExecutionsQuery, "JCR-SQL2")
@@ -400,7 +400,7 @@ class JcrGrabbitJobExecutionDao extends AbstractJcrDao implements GrabbitJobExec
 
     @Override
     Collection<String> getJobExecutions(int hours, Collection<String> jobExecutions) {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             //Create a Date object that is "hours" ago from now
             Calendar olderThanHours = Calendar.getInstance()
             log.info "Current time: ${olderThanHours.time}"
diff --git a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDao.groovy b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDao.groovy
index 160e253..7a90a10 100644
--- a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDao.groovy
+++ b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDao.groovy
@@ -16,7 +16,7 @@
 
 package com.twcable.grabbit.spring.batch.repository
 
-import com.twcable.grabbit.jcr.JcrUtil
+import com.twcable.grabbit.jcr.JCRUtil
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
 import org.apache.sling.api.resource.Resource
@@ -69,7 +69,7 @@ class JcrGrabbitJobInstanceDao extends AbstractJcrDao implements GrabbitJobInsta
         if (!jobParameters) throw new IllegalArgumentException("jobParameters == null")
         if (getJobInstance(jobName, jobParameters)) throw new IllegalStateException("A JobInstance for jobName: ${jobName} must not already exist")
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
 
             //TODO : This will need to be a "incrementing ID" after all and NOT use a UUID (for other APIs like
             //getJobInstances which require result to be sorted backwards by "id". If we use UUID, then the possibility of
@@ -115,7 +115,7 @@ class JcrGrabbitJobInstanceDao extends AbstractJcrDao implements GrabbitJobInsta
 
         final jobKey = new DefaultJobKeyGenerator().generateKey(jobParameters)
         //Find a resource under "/jobInstances" for the jobKey above
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final rootResource = getOrCreateResource(resolver, JOB_INSTANCE_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
             final jobInstanceResource = rootResource?.children?.asList()?.find { Resource resource ->
                 final properties = resource.adaptTo(ValueMap)
@@ -141,7 +141,7 @@ class JcrGrabbitJobInstanceDao extends AbstractJcrDao implements GrabbitJobInsta
     JobInstance getJobInstance(@Nonnull final Long instanceId) {
         if (!instanceId) throw new IllegalArgumentException("instanceId == null")
         //Get the "instanceId" node from JOB_INSTANCE_ROOT
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final rootResource = getOrCreateResource(resolver, JOB_INSTANCE_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
             final jobInstanceResource = rootResource?.children?.asList()?.find { Resource resource ->
                 final properties = resource.adaptTo(ValueMap)
@@ -184,7 +184,7 @@ class JcrGrabbitJobInstanceDao extends AbstractJcrDao implements GrabbitJobInsta
 
         //Get All jobInstances in JOB_INSTANCE_ROOT with jobName property = $jobName
         //Map jobInstances nodes to JobInstance object
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final rootResource = getOrCreateResource(resolver, JOB_INSTANCE_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
             final jobInstanceResource = rootResource?.children?.asList()?.findAll { Resource resource ->
                 final properties = resource.adaptTo(ValueMap)
@@ -222,7 +222,7 @@ class JcrGrabbitJobInstanceDao extends AbstractJcrDao implements GrabbitJobInsta
      */
     @Override
     List<String> getJobNames() {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final jobInstanceResources = getOrCreateResource(resolver, JOB_INSTANCE_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)?.children?.asList()
             if (!jobInstanceResources) return Collections.EMPTY_LIST
 
@@ -240,7 +240,7 @@ class JcrGrabbitJobInstanceDao extends AbstractJcrDao implements GrabbitJobInsta
      */
     @Override
     protected void ensureRootResource() {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             if (!getOrCreateResource(resolver, JOB_INSTANCE_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)) {
                 //create the Root Resource
                 throw new IllegalStateException("Cannot get or create RootResource for : ${JOB_INSTANCE_ROOT}")
@@ -276,7 +276,7 @@ class JcrGrabbitJobInstanceDao extends AbstractJcrDao implements GrabbitJobInsta
 
     @Override
     Collection<String> getJobInstancePaths(Collection<String> jobExecutionResourcePaths) {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             Collection<String> jobInstancesToRemove = []
             jobExecutionResourcePaths.each { String jobExecutionResourcePath ->
                 Resource jobExecutionResource = resolver.getResource(jobExecutionResourcePath)
diff --git a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDao.groovy b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDao.groovy
index d8b56e7..779b83e 100644
--- a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDao.groovy
+++ b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDao.groovy
@@ -17,7 +17,7 @@
 package com.twcable.grabbit.spring.batch.repository
 
 import com.twcable.grabbit.DateUtil
-import com.twcable.grabbit.jcr.JcrUtil
+import com.twcable.grabbit.jcr.JCRUtil
 import com.twcable.grabbit.util.CryptoUtil
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
@@ -129,7 +129,7 @@ public class JcrGrabbitStepExecutionDao extends AbstractJcrDao implements Grabbi
         if (!jobExecution) throw new IllegalArgumentException("jobExecution == null")
         if (!stepExecutionId) throw new IllegalArgumentException("stepExecutionId == null")
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final Resource rootResource = getOrCreateResource(resolver, STEP_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
             final stepExecutionResource = rootResource?.children?.asList()?.find { Resource resource ->
                 final properties = resource.adaptTo(ValueMap)
@@ -156,7 +156,7 @@ public class JcrGrabbitStepExecutionDao extends AbstractJcrDao implements Grabbi
         if (!jobExecution) throw new IllegalArgumentException("jobExecution == null")
         //TODO : JOB_EXECUTION's ID must exist
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final rootResource = getOrCreateResource(resolver, STEP_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
             final stepExecutionResources = rootResource.children.asList().findAll { Resource resource ->
                 final properties = resource.adaptTo(ValueMap)
@@ -189,7 +189,7 @@ public class JcrGrabbitStepExecutionDao extends AbstractJcrDao implements Grabbi
         if (!executionId) throw new IllegalArgumentException("executionId == null")
         if (!execution) throw new IllegalArgumentException("execution == null")
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             final rootResource = getOrCreateResource(resolver, STEP_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)
             final existingResource = resolver.getResource(rootResource, executionId)
 
@@ -286,7 +286,7 @@ public class JcrGrabbitStepExecutionDao extends AbstractJcrDao implements Grabbi
      */
     @Override
     protected void ensureRootResource() {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             //ResourceUtil.getOrCreateResource()
             if (!getOrCreateResource(resolver, STEP_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)) {
                 //create the Root Resource
@@ -301,7 +301,7 @@ public class JcrGrabbitStepExecutionDao extends AbstractJcrDao implements Grabbi
 
     @Override
     Collection<String> getStepExecutionPaths(Collection<String> jobExecutionResourcePaths) {
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
             Collection<String> stepExecutionsToRemove = []
             jobExecutionResourcePaths.each { String jobExecutionResourcePath ->
                 Resource jobExecutionResource = resolver.getResource(jobExecutionResourcePath)
diff --git a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/impl/DefaultCleanJobRepository.groovy b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/impl/DefaultCleanJobRepository.groovy
index 1de38ae..2d18288 100644
--- a/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/impl/DefaultCleanJobRepository.groovy
+++ b/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/impl/DefaultCleanJobRepository.groovy
@@ -16,7 +16,7 @@
 
 package com.twcable.grabbit.spring.batch.repository.services.impl
 
-import com.twcable.grabbit.jcr.JcrUtil
+import com.twcable.grabbit.jcr.JCRUtil
 import com.twcable.grabbit.spring.batch.repository.JcrJobRepositoryFactoryBean
 import com.twcable.grabbit.spring.batch.repository.services.CleanJobRepository
 import groovy.transform.CompileStatic
@@ -66,7 +66,7 @@ class DefaultCleanJobRepository implements CleanJobRepository {
         Collection<String> jobExecutionContextsToRemove = jobRepositoryFactoryBean.executionContextDao.getJobExecutionContextPaths(olderThanHoursJobExecutions)
         Collection<String> stepExecutionContextsToRemove = jobRepositoryFactoryBean.executionContextDao.getStepExecutionContextPaths(stepExecutionsToRemove)
 
-        JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+        JCRUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
 
             log.debug "jobInstancesToRemove: $jobInstancesToRemove, size: ${jobInstancesToRemove.size()}"
             log.debug "jobExecutionsToRemove: $olderThanHoursJobExecutions, size: ${olderThanHoursJobExecutions.size()}"
diff --git a/src/main/proto/node.proto b/src/main/proto/node.proto
index eecb447..a419d18 100644
--- a/src/main/proto/node.proto
+++ b/src/main/proto/node.proto
@@ -7,6 +7,7 @@ message Node {
     required string name = 1;
     repeated Property properties = 2;
     repeated Node mandatoryChildNode = 3;
+    optional string identifier = 4;
 }
 
 message Property {
diff --git a/src/test/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriterSpec.groovy b/src/test/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriterSpec.groovy
index 09742e4..4491b0e 100644
--- a/src/test/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriterSpec.groovy
+++ b/src/test/groovy/com/twcable/grabbit/client/batch/steps/jcrnodes/JcrNodesWriterSpec.groovy
@@ -17,7 +17,7 @@
 package com.twcable.grabbit.client.batch.steps.jcrnodes
 
 import com.twcable.grabbit.client.batch.ClientBatchJobContext
-import com.twcable.grabbit.jcr.JcrUtil
+import com.twcable.grabbit.jcr.JCRUtil
 import com.twcable.grabbit.proto.NodeProtos
 import com.twcable.grabbit.proto.NodeProtos.Node as ProtoNode
 import com.twcable.grabbit.proto.NodeProtos.Node.Builder as ProtoNodeBuilder
@@ -88,7 +88,7 @@ class JcrNodesWriterSpec extends Specification {
 
         NodeProtos.Node nodeProto = nodeBuilder.build()
 
-        Session session = JcrUtil.getSession(repository().build(), "admin")
+        Session session = JCRUtil.getSession(repository().build(), "admin")
 
         when:
         ClientBatchJobContext.setSession(session)
@@ -133,7 +133,7 @@ class JcrNodesWriterSpec extends Specification {
 
         ProtoNode protoNode = nodeBuilder.build()
 
-        Session session = JcrUtil.getSession(repository().build(), "admin")
+        Session session = JCRUtil.getSession(repository().build(), "admin")
 
         when:
         ClientBatchJobContext.setSession(session)
@@ -155,7 +155,7 @@ class JcrNodesWriterSpec extends Specification {
             getNodeProto("/foo/bar/foo", "jcr:primaryType", "nt:file")
         ]
 
-        Session session = JcrUtil.getSession(repository().build(), "admin")
+        Session session = JCRUtil.getSession(repository().build(), "admin")
 
         when:
         ClientBatchJobContext.setSession(session)
diff --git a/src/test/groovy/com/twcable/grabbit/jcr/AuthorizableProtoNodeDecoratorSpec.groovy b/src/test/groovy/com/twcable/grabbit/jcr/AuthorizableProtoNodeDecoratorSpec.groovy
index 0486a54..5b9b32d 100644
--- a/src/test/groovy/com/twcable/grabbit/jcr/AuthorizableProtoNodeDecoratorSpec.groovy
+++ b/src/test/groovy/com/twcable/grabbit/jcr/AuthorizableProtoNodeDecoratorSpec.groovy
@@ -42,16 +42,17 @@ import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE
 
 class AuthorizableProtoNodeDecoratorSpec extends Specification {
 
-    AuthorizableProtoNodeDecorator theProtoNodeDecorator(boolean forUser, boolean hasProfile, boolean hasPreferences, Closure configuration = null){
+
+    AuthorizableProtoNodeDecorator theProtoNodeDecoratorForUser(boolean hasProfile, boolean hasPreferences, String id, Closure configuration = null){
         ProtoNodeBuilder nodeBuilder = ProtoNode.newBuilder()
-        nodeBuilder.setName(forUser ? "/home/users/u/user1" : "/home/groups/g/group1")
+        nodeBuilder.setName('/home/users/u/user1')
 
         ProtoProperty primaryTypeProperty = ProtoProperty
                 .newBuilder()
                 .setName(JCR_PRIMARYTYPE)
                 .setType(STRING)
                 .setMultiple(false)
-                .addValues(ProtoValue.newBuilder().setStringValue(forUser ? 'rep:User' : 'rep:Group'))
+                .addValues(ProtoValue.newBuilder().setStringValue('rep:User'))
                 .build()
         nodeBuilder.addProperties(primaryTypeProperty)
 
@@ -69,7 +70,7 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
                 .setName('rep:authorizableId')
                 .setType(STRING)
                 .setMultiple(false)
-                .addValues(ProtoValue.newBuilder().setStringValue('authorizableID'))
+                .addValues(ProtoValue.newBuilder().setStringValue(id))
                 .build()
         nodeBuilder.addProperties(authorizableIdProperty)
 
@@ -89,30 +90,85 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
                 .setMultiple(false)
                 .addValues(ProtoValue.newBuilder().setStringValue('nt:unstructured'))
                 .build()
-        nodeBuilder.addProperties(authorizableCategory)
+
         if(hasPreferences) {
-            ProtoNode preferenceNode = ProtoNode.newBuilder()
-                .setName("${nodeBuilder.getName()}/preferences")
-                .addProperties(simplePrimaryType)
-                .build()
+            ProtoNode preferenceNode = ProtoNode
+                    .newBuilder()
+                    .setName("${nodeBuilder.getName()}/preferences")
+                    .addProperties(simplePrimaryType)
+                    .build()
             nodeBuilder.addMandatoryChildNode(preferenceNode)
         }
         if(hasProfile) {
             ProtoNode profileNode = ProtoNode
-                .newBuilder()
-                .setName("${nodeBuilder.getName()}/profile")
-                .addProperties(simplePrimaryType)
-                .build()
+                    .newBuilder()
+                    .setName("${nodeBuilder.getName()}/profile")
+                    .addProperties(simplePrimaryType)
+                    .build()
             nodeBuilder.addMandatoryChildNode(profileNode)
         }
+
         final properties = [new ProtoPropertyDecorator(primaryTypeProperty), new ProtoPropertyDecorator(disabledProperty), new ProtoPropertyDecorator(authorizableIdProperty), new ProtoPropertyDecorator(authorizableCategory)]
         return GroovySpy(AuthorizableProtoNodeDecorator, constructorArgs: [nodeBuilder.build(), properties], configuration)
     }
 
 
+    AuthorizableProtoNodeDecorator theProtoNodeDecoratorForGroup(Closure configuration = null){
+        ProtoNodeBuilder nodeBuilder = ProtoNode.newBuilder()
+        nodeBuilder.setName('/home/groups/g/group1')
+
+        ProtoProperty primaryTypeProperty = ProtoProperty
+                .newBuilder()
+                .setName(JCR_PRIMARYTYPE)
+                .setType(STRING)
+                .setMultiple(false)
+                .addValues(ProtoValue.newBuilder().setStringValue('rep:Group'))
+                .build()
+        nodeBuilder.addProperties(primaryTypeProperty)
+
+        ProtoProperty authorizableIdProperty = ProtoProperty
+                .newBuilder()
+                .setName('rep:authorizableId')
+                .setType(STRING)
+                .setMultiple(false)
+                .addValues(ProtoValue.newBuilder().setStringValue('authorizableID'))
+                .build()
+        nodeBuilder.addProperties(authorizableIdProperty)
+
+        ProtoProperty membershipProperty = ProtoProperty
+                .newBuilder()
+                .setName('rep:members')
+                .setType(STRING)
+                .setMultiple(false)
+                .addValues(ProtoValue.newBuilder().setStringValue('member-group-id'))
+                .build()
+        nodeBuilder.addProperties(membershipProperty)
+
+
+        ProtoNodeBuilder memberNodeBuilder = ProtoNode.newBuilder()
+        memberNodeBuilder.setName('/home/groups/g/anothergroup')
+
+        ProtoProperty userPrimaryTypeProperty = ProtoProperty
+                .newBuilder()
+                .setName(JCR_PRIMARYTYPE)
+                .setType(STRING)
+                .setMultiple(false)
+                .addValues(ProtoValue.newBuilder().setStringValue('rep:Group'))
+                .build()
+        memberNodeBuilder.addProperties(userPrimaryTypeProperty)
+
+        memberNodeBuilder.setIdentifier('member-group-id')
+
+        nodeBuilder.addMandatoryChildNode(memberNodeBuilder.build())
+
+        final properties = [new ProtoPropertyDecorator(primaryTypeProperty), new ProtoPropertyDecorator(authorizableIdProperty), new ProtoPropertyDecorator(membershipProperty)]
+        return GroovySpy(AuthorizableProtoNodeDecorator, constructorArgs: [nodeBuilder.build(), properties], configuration)
+    }
+
+
     def "Throws an InsufficientGrabbitPrivilegeException if JVM permissions are not present"() {
         when:
-        final protoNodeDecorator = theProtoNodeDecorator(false, false, false) {
+        final protoNodeDecorator = theProtoNodeDecoratorForGroup {
             it.getSecurityManager() >> Mock(SecurityManager) {
                 it.checkPermission(permission) >> {
                     throw new SecurityException()
@@ -130,6 +186,42 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
     }
 
 
+    def "Does not attempt to modify the administrator"() {
+        when:
+        final adminNode = Mock(Node) {
+            getProperty(JCR_PRIMARYTYPE) >> Mock(Property) {
+                it.getString() >> 'rep:User'
+            }
+            getProperties() >> Mock(PropertyIterator) {
+                it.toList() >> []
+            }
+            it.getPrimaryNodeType() >> Mock(NodeType) {
+                it.canSetProperty(_, _) >> false
+            }
+        }
+        final session = Mock(Session) {
+            it.getNode('/home/users/m/a') >> adminNode
+        }
+        final protoNodeDecorator = theProtoNodeDecoratorForUser(false, false, 'admin') {
+            it.getSecurityManager() >> Mock(SecurityManager) {
+                it.checkPermission(_) >> {
+                    return
+                }
+            }
+            it.getUserManager(session) >> Mock(UserManager) {
+                it.getAuthorizable('admin') >> Mock(Authorizable) {
+                    it.getPath() >> '/home/users/m/a'
+                }
+            }
+        }
+
+        final JCRNodeDecorator resultNode = protoNodeDecorator.writeToJcr(session)
+
+        then:
+        (resultNode as Node) == adminNode
+    }
+
+
     def "Passes security check if all JVM permissions are present"() {
         when:
         final session = Mock(Session) {
@@ -145,7 +237,7 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
                 }
             }
         }
-        final protoNodeDecorator = theProtoNodeDecorator(false, false, false) {
+        final protoNodeDecorator = theProtoNodeDecoratorForGroup {
             it.getSecurityManager() >> Mock(SecurityManager) {
                 it.checkPermission(permission) >> {
                     return
@@ -156,6 +248,9 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
                     it.getPath() >> 'authorizablePath'
                 }
             }
+            it.writeMandatoryPieces(_, _) >> [
+                Mock(JCRNodeDecorator)
+            ]
         }
 
         protoNodeDecorator.writeToJcr(session)
@@ -183,13 +278,16 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
                 }
             }
         }
-        final protoNodeDecorator = theProtoNodeDecorator(false, false, false) {
+        final protoNodeDecorator = theProtoNodeDecoratorForGroup {
             it.getSecurityManager() >> null
             it.getUserManager(session) >> Mock(UserManager) {
                 it.createGroup(_, _, _) >> Mock(Group) {
                     it.getPath() >> 'authorizablePath'
                 }
             }
+            it.writeMandatoryPieces(_, _) >> [
+                    Mock(JCRNodeDecorator)
+            ]
         }
 
         protoNodeDecorator.writeToJcr(session)
@@ -201,7 +299,7 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
 
     def "getSecurityManager() will retrieve the JVM's security manager"() {
         given:
-        final protoNodeDecorator = theProtoNodeDecorator(false, false, false)
+        final protoNodeDecorator = theProtoNodeDecoratorForGroup()
 
         expect:
         System.getSecurityManager() == protoNodeDecorator.getSecurityManager()
@@ -229,7 +327,7 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
             1 * it.setProperty('cq:authorizableCategory', new StringValue('mcm'))
             it.getPath() >> 'newUserPath'
         }
-        final protoNodeDecorator = theProtoNodeDecorator(true, false, false) {
+        final protoNodeDecorator = theProtoNodeDecoratorForUser(false, false, 'authorizableID') {
             it.getName() >> '/home/users/auth_folder/user'
             it.getSecurityManager() >> null
             it.setPasswordForUser(newUser, session) >> {
@@ -265,16 +363,25 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
         final session = Mock(Session) {
             it.getNode('newGroupPath') >> node
         }
+        final member = Mock(Authorizable)
         final newGroup = Mock(Group) {
             it.getPath() >> 'newGroupPath'
+            1 * it.addMember(member)
         }
-        final protoNodeDecorator = theProtoNodeDecorator(false, false, false) {
+        final protoNodeDecorator = theProtoNodeDecoratorForGroup {
             it.getName() >> '/home/groups/auth_folder/group'
             it.getSecurityManager() >> null
             it.getUserManager(session) >> Mock(UserManager) {
                 it.getAuthorizable('authorizableID') >> null
                 1 * it.createGroup('authorizableID', new AuthorizablePrincipal('authorizableID'), '/home/groups/auth_folder') >> newGroup
             }
+            it.writeMandatoryPieces(session, 'newGroupPath') >> [
+                Mock(JCRNodeDecorator) {
+                    it.isAuthorizableType() >> true
+                    it.getTransferredID() >> 'member-group-id'
+                    it.asType(Authorizable) >> member
+                }
+            ]
         }
 
         when:
@@ -301,15 +408,18 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
         final session = Mock(Session) {
             it.getNode('/home/users/u/newuser') >> node
         }
-        final protoNodeDecorator = theProtoNodeDecorator(false, exists, false) {
+        final protoNodeDecorator = theProtoNodeDecoratorForUser(exists, false, 'authorizableID') {
             it.getSecurityManager() >> null
             it.getUserManager(session) >> Mock(UserManager) {
-                it.getAuthorizable('authorizableID') >> Mock(Authorizable)
-                it.createGroup('authorizableID', _, _) >> Mock(Group) {
+                it.getAuthorizable('authorizableID') >> Mock(Authorizable) {
+                    it.declaredMemberOf() >> [].iterator()
+                }
+                it.createUser('authorizableID', _, _, _) >> Mock(User) {
                     it.getPath() >> '/home/users/u/newuser'
+                    it.declaredMemberOf() >> [].iterator()
                 }
             }
-            (exists ? 1 : 0) * it.createFrom(_ as ProtoNode, '/home/users/u/newuser/profile')  >> Mock(ProtoNodeDecorator)
+            (exists ? 1 : 0) * it._createFrom(_ as ProtoNode, '/home/users/u/newuser/profile')  >> Mock(ProtoNodeDecorator)
         }
 
         then:
@@ -337,15 +447,18 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
         final session = Mock(Session) {
             it.getNode('/home/users/u/newuser') >> node
         }
-        final protoNodeDecorator = theProtoNodeDecorator(false, false, exists) {
+        final protoNodeDecorator = theProtoNodeDecoratorForUser(false, exists, 'authorizableID') {
             it.getSecurityManager() >> null
             it.getUserManager(session) >> Mock(UserManager) {
-                it.getAuthorizable('authorizableID') >> Mock(Authorizable)
-                it.createGroup('authorizableID', _, _) >> Mock(Group) {
+                it.getAuthorizable('authorizableID') >> Mock(Authorizable) {
+                    it.declaredMemberOf() >> [].iterator()
+                }
+                it.createUser('authorizableID', _, _, _) >> Mock(User) {
                     it.getPath() >> '/home/users/u/newuser'
+                    it.declaredMemberOf() >> [].iterator()
                 }
             }
-            (exists ? 1 : 0) * it.createFrom(_ as ProtoNode, '/home/users/u/newuser/preferences')  >> Mock(ProtoNodeDecorator)
+            (exists ? 1 : 0) * it._createFrom(_ as ProtoNode, '/home/users/u/newuser/preferences')  >> Mock(ProtoNodeDecorator)
         }
 
         then:
@@ -355,4 +468,41 @@ class AuthorizableProtoNodeDecoratorSpec extends Specification {
         where:
         exists << [false, true]
     }
+
+    def "When updating an authorizable, remove old authorizable from declared groups, and add updated authorizable back to groups"() {
+        when:
+        final node = Mock(Node) {
+            getProperty(JCR_PRIMARYTYPE) >> Mock(Property) {
+                it.getString() >> 'rep:User'
+            }
+            getProperties() >> Mock(PropertyIterator) {
+                it.toList() >> []
+            }
+            it.getPrimaryNodeType() >> Mock(NodeType) {
+                it.canSetProperty(_, _) >> false
+            }
+        }
+        final session = Mock(Session) {
+            it.getNode('/home/users/u/newuser') >> node
+        }
+        final group = Mock(Group) {
+            1 * it.removeMember(_)
+            1 * it.addMember(_)
+        }
+        final protoNodeDecorator = theProtoNodeDecoratorForUser(false, false, 'authorizableID') {
+            it.getUserManager(session) >> Mock(UserManager) {
+                it.getAuthorizable('authorizableID') >> Mock(Authorizable) {
+                    it.declaredMemberOf() >> [group].iterator()
+                }
+                it.createUser('authorizableID', _, _, _) >> Mock(User) {
+                    it.getPath() >> '/home/users/u/newuser'
+                    it.declaredMemberOf() >> [].iterator()
+                }
+            }
+        }
+
+        then:
+        protoNodeDecorator.writeToJcr(session)
+    }
+
 }
diff --git a/src/test/groovy/com/twcable/grabbit/jcr/DefaultProtoNodeDecoratorSpec.groovy b/src/test/groovy/com/twcable/grabbit/jcr/DefaultProtoNodeDecoratorSpec.groovy
index 07e9ec9..def8131 100644
--- a/src/test/groovy/com/twcable/grabbit/jcr/DefaultProtoNodeDecoratorSpec.groovy
+++ b/src/test/groovy/com/twcable/grabbit/jcr/DefaultProtoNodeDecoratorSpec.groovy
@@ -20,62 +20,81 @@ import com.twcable.grabbit.proto.NodeProtos
 import com.twcable.grabbit.proto.NodeProtos.Node as ProtoNode
 import com.twcable.grabbit.proto.NodeProtos.Node.Builder as ProtoNodeBuilder
 import com.twcable.grabbit.proto.NodeProtos.Property as ProtoProperty
-import javax.jcr.nodetype.NodeType
-import spock.lang.Specification
-
 import javax.jcr.Node
 import javax.jcr.Property
 import javax.jcr.PropertyIterator
 import javax.jcr.Session
+import javax.jcr.nodetype.NodeType
+import spock.lang.Specification
+
 
+import static javax.jcr.PropertyType.REFERENCE
 import static javax.jcr.PropertyType.STRING
+import static javax.jcr.PropertyType.WEAKREFERENCE
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE
 
-
 class DefaultProtoNodeDecoratorSpec extends Specification {
 
     ProtoNode decoratedProtoNode
     ProtoProperty mixinProperty
     ProtoProperty someOtherProperty
+    ProtoProperty referenceProperty
+    ProtoProperty referencePropertyTwo
 
-    def setup() {
-        ProtoNodeBuilder nodeBuilder = ProtoNode.newBuilder()
-        nodeBuilder.setName("somenode")
 
+    def setup() {
         ProtoProperty primaryTypeProperty = NodeProtos.Property
-                .newBuilder()
-                .setName(JCR_PRIMARYTYPE)
-                .setType(STRING)
-                .setMultiple(false)
-                .addValues(NodeProtos.Value.newBuilder().setStringValue(JcrConstants.NT_UNSTRUCTURED))
-                .build()
-        nodeBuilder.addProperties(primaryTypeProperty)
+            .newBuilder()
+            .setName(JCR_PRIMARYTYPE)
+            .setType(STRING)
+            .setMultiple(false)
+            .addValues(NodeProtos.Value.newBuilder().setStringValue(JcrConstants.NT_UNSTRUCTURED))
+            .build()
 
         mixinProperty = NodeProtos.Property
-                .newBuilder()
-                .setName(JCR_MIXINTYPES)
-                .setType(STRING)
-                .setMultiple(true)
-                .addAllValues(
+            .newBuilder()
+            .setName(JCR_MIXINTYPES)
+            .setType(STRING)
+            .setMultiple(true)
+            .addAllValues(
                 [
-                        NodeProtos.Value.newBuilder().setStringValue("somemixintype").build(),
-                        NodeProtos.Value.newBuilder().setStringValue("unwritablemixin").build()
+                    NodeProtos.Value.newBuilder().setStringValue("somemixintype").build(),
+                    NodeProtos.Value.newBuilder().setStringValue("unwritablemixin").build()
                 ]
-        )
-                .build()
-        nodeBuilder.addProperties(mixinProperty)
-
+            ).build()
 
         someOtherProperty = NodeProtos.Property
+            .newBuilder()
+            .setName("someproperty")
+            .setType(STRING)
+            .setMultiple(false)
+            .addValues(NodeProtos.Value.newBuilder().setStringValue("somevalue"))
+            .build()
+
+        referenceProperty = NodeProtos.Property
+            .newBuilder()
+            .setName('jcr:uuid')
+            .setType(WEAKREFERENCE)
+            .setMultiple(false)
+            .addValues(NodeProtos.Value.newBuilder().setStringValue('21232f29-7a57-35a7-8389-4a0e4a801fc3'))
+            .build()
+
+        referencePropertyTwo = NodeProtos.Property
                 .newBuilder()
-                .setName("someproperty")
-                .setType(STRING)
+                .setName('jcr:uuid')
+                .setType(REFERENCE)
                 .setMultiple(false)
-                .addValues(NodeProtos.Value.newBuilder().setStringValue("somevalue"))
+                .addValues(NodeProtos.Value.newBuilder().setStringValue('41232f29-7a57-35a7-8389-4a0e4a801fc6'))
                 .build()
-        nodeBuilder.addProperties(someOtherProperty)
 
+        ProtoNodeBuilder nodeBuilder = ProtoNode.newBuilder()
+        nodeBuilder.setName("somenode")
+        nodeBuilder.addProperties(primaryTypeProperty)
+        nodeBuilder.addProperties(mixinProperty)
+        nodeBuilder.addProperties(someOtherProperty)
+        nodeBuilder.addProperties(referenceProperty)
+        nodeBuilder.addProperties(referencePropertyTwo)
         decoratedProtoNode = nodeBuilder.build()
     }
 
@@ -110,8 +129,7 @@ class DefaultProtoNodeDecoratorSpec extends Specification {
         final Collection<ProtoPropertyDecorator> properties = protoNodeDecorator.getWritableProperties()
 
         then:
-        properties.size() == 1
-        properties[0].stringValue == "somevalue"
+        properties.size() == 3
     }
 
     def "Can write this ProtoNodeDecorator to the JCR"() {
@@ -133,12 +151,21 @@ class DefaultProtoNodeDecoratorSpec extends Specification {
         }
         final protoPropertyDecorators = [
                 new ProtoPropertyDecorator(mixinProperty),
-                new ProtoPropertyDecorator(someOtherProperty)
+                new ProtoPropertyDecorator(someOtherProperty),
+                new ProtoPropertyDecorator(referenceProperty),
+                new ProtoPropertyDecorator(referencePropertyTwo)
         ]
         final protoNodeDecorator = Spy(DefaultProtoNodeDecorator, constructorArgs: [decoratedProtoNode, protoPropertyDecorators, null]) {
             getOrCreateNode(session) >>  {
                 return jcrNodeRepresentation
             }
+            writeMandatoryPieces(session, 'somenode') >> [
+                Mock(JCRNodeDecorator) {
+                    isReferenceable() >> true
+                    getTransferredID() >> '21232f29-7a57-35a7-8389-4a0e4a801fc3'
+                    getIdentifier() >> '31232f29-7a57-35a7-8389-4a0e4a801fc4'
+                }
+            ]
         }
 
         final jcrNodeDecorator = protoNodeDecorator.writeToJcr(session)
diff --git a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy b/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy
index 5d886a7..04b05c0 100644
--- a/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy
+++ b/src/test/groovy/com/twcable/grabbit/jcr/JCRNodeDecoratorSpec.groovy
@@ -23,11 +23,14 @@ import javax.jcr.NodeIterator
 import javax.jcr.Property
 import javax.jcr.PropertyIterator
 import javax.jcr.RepositoryException
+import javax.jcr.Session
 import javax.jcr.Value
 import javax.jcr.nodetype.ItemDefinition
 import javax.jcr.nodetype.NodeDefinition
 import javax.jcr.nodetype.NodeType
 import javax.jcr.nodetype.PropertyDefinition
+import org.apache.jackrabbit.api.security.user.Authorizable
+import org.apache.jackrabbit.api.security.user.UserManager
 import org.apache.jackrabbit.commons.iterator.PropertyIteratorAdapter
 import spock.lang.Shared
 import spock.lang.Specification
@@ -37,9 +40,12 @@ import spock.lang.Unroll
 import static com.twcable.grabbit.jcr.JCRNodeDecorator.NoRootInclusionPolicy
 import static com.twcable.grabbit.testutil.StubInputStream.inputStream
 import static javax.jcr.PropertyType.BINARY
+import static javax.jcr.PropertyType.REFERENCE
+import static javax.jcr.PropertyType.WEAKREFERENCE
 import static org.apache.jackrabbit.JcrConstants.JCR_CREATED
 import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE
+import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE
 import static org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants.NT_REP_ACL
 import static org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants.NT_REP_GRANT_ACE
 
@@ -94,6 +100,8 @@ class JCRNodeDecoratorSpec extends Specification {
                         }
                     }
             }
+            isNodeType(MIX_REFERENCEABLE) >> true
+            getIdentifier() >> "node_id"
             getProperty(JCR_PRIMARYTYPE) >> Mock(Property) {
                 getString() >> "rep:SystemUser"
             }
@@ -149,6 +157,7 @@ class JCRNodeDecoratorSpec extends Specification {
 
         then:
         protoNode.getName() == '/some/path'
+        protoNode.getIdentifier() == "node_id"
         protoNode.getPropertiesCount() == 1
     }
 
@@ -278,7 +287,7 @@ class JCRNodeDecoratorSpec extends Specification {
     }
 
 
-    def "getRequiredChildNodes()"() {
+    def "getRequiredChildNodes() when the node has mandatory children"() {
         given:
         Node nodeWithMandatoryChildren = Mock(Node) {
             getNodes() >> Mock(NodeIterator) {
@@ -303,16 +312,7 @@ class JCRNodeDecoratorSpec extends Specification {
             }
         }
 
-        Node authorizableNode = Mock(Node) {
-            getProperty(JCR_PRIMARYTYPE) >> Mock(Property) {
-                getString() >> 'rep:User'
-            }
-            getProperties() >> Mock(PropertyIterator) {
-                toList() >> []
-            }
-        }
-
-        when: "The node has mandatory children"
+        when:
         final nodeDecorator = Spy(JCRNodeDecorator, constructorArgs: [nodeWithMandatoryChildren]) {
             hasMandatoryChildNodes() >> true
             isAuthorizableType() >> false
@@ -320,11 +320,22 @@ class JCRNodeDecoratorSpec extends Specification {
 
         then:
         nodeDecorator.getRequiredChildNodes().size() == 1
+    }
+
 
-        and: "The node has authorizable pieces"
+    def "getRequiredChildNodes() when the node has authorizable pieces"() {
+        given:
+        Node authorizableNode = Mock(Node) {
+            getProperty(JCR_PRIMARYTYPE) >> Mock(Property) {
+                getString() >> 'rep:User'
+            }
+            getProperties() >> Mock(PropertyIterator) {
+                toList() >> []
+            }
+        }
 
         when:
-        final otherNodeDecorator = Spy(JCRNodeDecorator, constructorArgs: [authorizableNode]) {
+        final nodeDecorator = Spy(JCRNodeDecorator, constructorArgs: [authorizableNode]) {
             hasMandatoryChildNodes() >> false
             isAuthorizableType() >> true
             getChildNodeIterator() >> Mock(Iterator) {
@@ -362,7 +373,7 @@ class JCRNodeDecoratorSpec extends Specification {
                         getProperties() >> Mock(PropertyIterator) {
                             toList() >> []
                         }
-                    }  >>
+                    } >>
                     Mock(Node) {
                         getName() >> "/home/users/u/user/rep:policy"
                         getProperty(JCR_PRIMARYTYPE) >> Mock(Property) {
@@ -385,13 +396,22 @@ class JCRNodeDecoratorSpec extends Specification {
         }
 
         then:
-        otherNodeDecorator.getRequiredChildNodes().size() == 2
+        nodeDecorator.getRequiredChildNodes().size() == 2
+    }
+
 
-        and: "If no child nodes, getRequiredChildNodes() returns an empty collection"
+    def "getRequiredChildNodes() if no child nodes, returns an empty collection"() {
+        given:
+        final node = Mock(Node) {
+            getProperties() >> Mock(PropertyIterator) {
+                toList() >> []
+            }
+        }
 
         when:
-        final yetAnotherNodeDecorator = Spy(JCRNodeDecorator, constructorArgs: [nodeWithMandatoryChildren]) {
+        final yetAnotherNodeDecorator = Spy(JCRNodeDecorator, constructorArgs: [node]) {
             hasMandatoryChildNodes() >> false
+            isRepACLType() >> false
             isAuthorizableType() >> false
         }
 
@@ -400,6 +420,97 @@ class JCRNodeDecoratorSpec extends Specification {
     }
 
 
+    def "getRequiredChildNodes() returns referenced nodes"() {
+        given:
+        final referenceNode = Mock(Node) {
+            getProperties() >> Mock(PropertyIterator) {
+                toList() >> []
+            }
+        }
+        final node = Mock(Node) {
+            getPath() >> "/some/node/path"
+            getSession() >> Mock(Session) {
+                getNodeByIdentifier({["reference_uuid_one", "reference_uuid_two", "reference_uuid_four"].contains(it)}) >> referenceNode
+                getNodeByIdentifier({!["reference_uuid_one", "reference_uuid_two", "reference_uuid_four"].contains(it)}) >> {
+                    throw new ItemNotFoundException("Node not found")
+                }
+            }
+            getProperty(JCR_PRIMARYTYPE) >> Mock(Property) {
+                getString() >> 'nt:unstructured'
+            }
+            getPrimaryNodeType() >> Mock(NodeType) {
+                getChildNodeDefinitions() >> [
+                        Mock(NodeDefinition) {
+                            isMandatory() >> true
+                        }
+                ].toArray()
+            }
+            getProperties() >> Mock(PropertyIterator) {
+                hasNext() >>> true >> true >> false
+                next() >>
+                Mock(Property) {
+                    getType() >> WEAKREFERENCE
+                    isMultiple() >> true
+                    getDefinition() >> Mock(PropertyDefinition) {
+                        isProtected() >> false
+                    }
+                    getValues() >> ([
+                        Mock(Value) {
+                            getString() >> "reference_uuid_one"
+                        },
+                        Mock(Value) {
+                            getString() >> "reference_uuid_two"
+                        },
+                        Mock(Value) {
+                            getString() >> "reference_uuid_three"
+                        }
+                    ].toArray() as Value[])
+                } >>
+                Mock(Property) {
+                    getType() >> REFERENCE
+                    isMultiple() >> false
+                    getDefinition() >> Mock(PropertyDefinition) {
+                        isProtected() >> true
+                    }
+                    getValue() >> Mock(Value) {
+                        getString() >> "reference_uuid_five"
+                    }
+                }
+            }
+            getNodes() >> Mock(NodeIterator) {
+                hasNext() >>> true >> false
+                next() >> Mock(Node) {
+                    getProperty(JCR_PRIMARYTYPE) >> Mock(Property) {
+                        getString() >> 'nt:unstructured'
+                    }
+                    getProperties() >> Mock(PropertyIterator) {
+                        hasNext() >>> true >> false
+                        next() >> Mock(Property) {
+                            getType() >> REFERENCE
+                            isMultiple() >> false
+                            getDefinition() >> Mock(PropertyDefinition) {
+                                isProtected() >> false
+                            }
+                            getValue() >> Mock(Value) {
+                                getString() >> "reference_uuid_four"
+                            }
+                        }
+                    }
+                    getDefinition() >> Mock(NodeDefinition) {
+                        isMandatory() >> true
+                    }
+                }
+            }
+        }
+
+        when:
+        final nodeDecorator = new JCRNodeDecorator(node)
+
+        then:
+        nodeDecorator.getRequiredChildNodes().size() == 4
+    }
+
+
     def "Can adapt the decorator back to the wrapped node"() {
         given:
         final node = Mock(Node) {
@@ -417,6 +528,30 @@ class JCRNodeDecoratorSpec extends Specification {
         (nodeDecorator as JCRNodeDecorator) == nodeDecorator
     }
 
+
+    def "Can adapt the decorator to an authorizable if appropriate"() {
+        given:
+        final node = Mock(Node) {
+            getProperty(JCR_PRIMARYTYPE) >> Mock(Property) {
+                getString() >> 'rep:User'
+            }
+            getProperties() >> Mock(PropertyIterator) {
+                toList() >> []
+            }
+            getPath() >> '/home/users/user'
+        }
+        final returnedAuthorizable = Mock(Authorizable)
+        final nodeDecorator = Spy(JCRNodeDecorator, constructorArgs: [node]) {
+            getUserManager(_) >> Mock(UserManager) {
+                1 * getAuthorizableByPath('/home/users/user') >> returnedAuthorizable
+            }
+        }
+
+        expect:
+        (nodeDecorator as Authorizable) == returnedAuthorizable
+    }
+
+
     def "Get modified date for a node"() {
         given:
         final node = Mock(Node) {
diff --git a/src/test/groovy/com/twcable/grabbit/jcr/JcrPropertyDecoratorSpec.groovy b/src/test/groovy/com/twcable/grabbit/jcr/JcrPropertyDecoratorSpec.groovy
index 8b031d4..40e87f3 100644
--- a/src/test/groovy/com/twcable/grabbit/jcr/JcrPropertyDecoratorSpec.groovy
+++ b/src/test/groovy/com/twcable/grabbit/jcr/JcrPropertyDecoratorSpec.groovy
@@ -16,23 +16,26 @@
 
 package com.twcable.grabbit.jcr
 
-import javax.jcr.Property
+import javax.jcr.Property as JCRProperty
 import javax.jcr.nodetype.PropertyDefinition
 import spock.lang.Specification
 import spock.lang.Unroll
 
 
+import static javax.jcr.PropertyType.BINARY
+import static javax.jcr.PropertyType.REFERENCE
+import static javax.jcr.PropertyType.WEAKREFERENCE
 import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE
 
 @SuppressWarnings("GroovyAssignabilityCheck")
-class JcrPropertyDecoratorSpec extends Specification {
+class JCRPropertyDecoratorSpec extends Specification {
 
     @Unroll
     def "check if property is transferable"() {
         given:
-        Property property = Mock(Property) {
+        JCRProperty property = Mock(JCRProperty) {
             getName() >> propertyName
             getDefinition() >> Mock(PropertyDefinition) {
                 isProtected() >> protectedFlag
@@ -44,7 +47,7 @@ class JcrPropertyDecoratorSpec extends Specification {
         }
 
         when:
-        final propertyDecorator = new JcrPropertyDecorator(property, nodeOwner)
+        final propertyDecorator = new JCRPropertyDecorator(property, nodeOwner)
 
         then:
         expectedOutput == propertyDecorator.isTransferable()
@@ -61,4 +64,22 @@ class JcrPropertyDecoratorSpec extends Specification {
         'rep:privileges'    | true          | true           | false             | true
 
     }
+
+    def "isReferenceType()"() {
+        when:
+        final JCRProperty property = Mock(JCRProperty) {
+            getType() >> type
+        }
+
+        final jcrPropertyDecorator = new JCRPropertyDecorator(property, Mock(JCRNodeDecorator))
+
+        then:
+        jcrPropertyDecorator.isReferenceType() == expectedValue
+
+        where:
+        type            | expectedValue
+        REFERENCE       | true
+        WEAKREFERENCE   | true
+        BINARY          | false
+    }
 }