diff --git a/packages/component-invite/config/authsome-helpers.js b/packages/component-invite/config/authsome-helpers.js
index e30375101e82bc13c9d464ec8c4be74686c6c7d9..b5f42492b077cee12d5a09d97404fb559e601f5e 100644
--- a/packages/component-invite/config/authsome-helpers.js
+++ b/packages/component-invite/config/authsome-helpers.js
@@ -6,23 +6,78 @@ const statuses = config.get('statuses')
 
 const publicStatusesPermissions = ['author', 'reviewer']
 
-module.exports = {
-  parseAuthorsData: (coll, matchingCollPerm) => {
+const parseAuthorsData = (coll, matchingCollPerm) => {
+  if (['reviewer'].includes(matchingCollPerm.permission)) {
+    coll.authors = coll.authors.map(a => omit(a, ['email']))
+  }
+}
+
+const setPublicStatuses = (coll, matchingCollPerm) => {
+  const status = get(coll, 'status') || 'draft'
+  coll.visibleStatus = statuses[status].public
+  if (!publicStatusesPermissions.includes(matchingCollPerm.permission)) {
+    coll.visibleStatus = statuses[coll.status].private
+  }
+}
+
+const filterRefusedInvitations = (coll, user) => {
+  const matchingInv = coll.invitations.find(inv => inv.userId === user.id)
+  if (matchingInv === undefined) return null
+  if (matchingInv.hasAnswer === true && !matchingInv.isAccepted) return null
+  return coll
+}
+
+const filterObjectData = (
+  collectionsPermissions = [],
+  object = {},
+  user = {},
+) => {
+  if (object.type === 'fragment') {
+    const matchingCollPerm = collectionsPermissions.find(
+      collPerm => object.id === collPerm.fragmentId,
+    )
+    if (matchingCollPerm === undefined) return null
     if (['reviewer'].includes(matchingCollPerm.permission)) {
-      coll.authors = coll.authors.map(a => omit(a, ['email']))
-    }
-  },
-  setPublicStatuses: (coll, matchingCollPerm) => {
-    const status = get(coll, 'status') || 'draft'
-    coll.visibleStatus = statuses[status].public
-    if (!publicStatusesPermissions.includes(matchingCollPerm.permission)) {
-      coll.visibleStatus = statuses[coll.status].private
+      object.files = omit(object.files, ['coverLetter'])
+      if (object.recommendations)
+        object.recommendations = object.recommendations.filter(
+          rec => rec.userId === user.id,
+        )
     }
-  },
-  filterRefusedInvitations: (coll, user) => {
-    const matchingInv = coll.invitations.find(inv => inv.userId === user.id)
-    if (matchingInv === undefined) return null
-    if (matchingInv.hasAnswer === true && !matchingInv.isAccepted) return null
-    return coll
-  },
+
+    return object
+  }
+  const matchingCollPerm = collectionsPermissions.find(
+    collPerm => object.id === collPerm.id,
+  )
+  if (matchingCollPerm === undefined) return null
+  setPublicStatuses(object, matchingCollPerm)
+  parseAuthorsData(object, matchingCollPerm)
+  if (['reviewer', 'handlingEditor'].includes(matchingCollPerm.permission)) {
+    return filterRefusedInvitations(object, user)
+  }
+
+  return object
+}
+
+const getTeamsByPermissions = async (teamIds, permissions, TeamModel) => {
+  const teams = await Promise.all(
+    teamIds.map(async teamId => {
+      const team = await TeamModel.find(teamId)
+      if (permissions.includes(team.teamType.permissions)) {
+        return team
+      }
+      return null
+    }),
+  )
+
+  return teams.filter(Boolean)
+}
+
+module.exports = {
+  parseAuthorsData,
+  setPublicStatuses,
+  filterRefusedInvitations,
+  filterObjectData,
+  getTeamsByPermissions,
 }
diff --git a/packages/component-invite/config/authsome-mode.js b/packages/component-invite/config/authsome-mode.js
index 2e3d8ea7faf8d5e86169de321d922bbc25c9a56d..3498bc042c01679ecc1e75f8a783628e63cd153c 100644
--- a/packages/component-invite/config/authsome-mode.js
+++ b/packages/component-invite/config/authsome-mode.js
@@ -5,52 +5,47 @@ const helpers = require('./authsome-helpers')
 
 async function teamPermissions(user, operation, object, context) {
   const permissions = ['handlingEditor', 'author', 'reviewer']
-  const teams = await Promise.all(
-    user.teams.map(async teamId => {
-      const team = await context.models.Team.find(teamId)
-      if (permissions.includes(team.teamType.permissions)) {
-        return team
+  const teams = await helpers.getTeamsByPermissions(
+    user.teams,
+    permissions,
+    context.models.Team,
+  )
+
+  const collectionsPermissions = await Promise.all(
+    teams.map(async team => {
+      const collection = await context.models.Collection.find(team.object.id)
+      const collPerm = {
+        id: collection.id,
+        permission: team.teamType.permissions,
       }
-      return null
+      const objectType = get(object, 'type')
+      if (objectType === 'fragment' && collection.fragments.includes(object.id))
+        collPerm.fragmentId = object.id
+
+      return collPerm
     }),
   )
 
-  const collectionsPermissions = teams.filter(Boolean).map(team => ({
-    id: team.object.id,
-    permission: team.teamType.permissions,
-  }))
+  if (collectionsPermissions.length === 0) return {}
 
-  if (collectionsPermissions.length > 0) {
-    return {
-      filter: filterParam => {
-        if (!filterParam.length) return filterParam
-
-        const collections = filterParam
-          .map(coll => {
-            const matchingCollPerm = collectionsPermissions.find(
-              collPerm => coll.id === collPerm.id,
-            )
-            if (matchingCollPerm === undefined) {
-              return null
-            }
-            helpers.setPublicStatuses(coll, matchingCollPerm)
-            helpers.parseAuthorsData(coll, matchingCollPerm)
-            if (
-              ['reviewer', 'handlingEditor'].includes(
-                matchingCollPerm.permission,
-              )
-            ) {
-              return helpers.filterRefusedInvitations(coll, user)
-            }
-            return coll
-          })
-          .filter(Boolean)
-        return collections
-      },
-    }
-  }
+  return {
+    filter: filterParam => {
+      if (!filterParam.length) {
+        return helpers.filterObjectData(
+          collectionsPermissions,
+          filterParam,
+          user,
+        )
+      }
 
-  return {}
+      const collections = filterParam
+        .map(coll =>
+          helpers.filterObjectData(collectionsPermissions, coll, user),
+        )
+        .filter(Boolean)
+      return collections
+    },
+  }
 }
 
 function unauthenticatedUser(operation, object) {
@@ -153,7 +148,7 @@ async function authenticatedUser(user, operation, object, context) {
     }
   }
 
-  // only allow the HE to create, delete an invitation, or get inv details`
+  // only allow the HE to create, delete an invitation, or get invitation details
   if (
     ['POST', 'GET', 'DELETE'].includes(operation) &&
     get(object.collection, 'type') === 'collection' &&
@@ -162,9 +157,29 @@ async function authenticatedUser(user, operation, object, context) {
     const collection = await context.models.Collection.find(
       get(object.collection, 'id'),
     )
-    if (collection.handlingEditor.id === user.id) {
-      return true
-    }
+    const handlingEditor = get(collection, 'handlingEditor')
+    if (!handlingEditor) return false
+    if (handlingEditor.id === user.id) return true
+    return false
+  }
+
+  // only allow a reviewer to submit and to modify a recommendation
+  if (
+    ['POST', 'PATCH'].includes(operation) &&
+    get(object.collection, 'type') === 'collection' &&
+    object.path.includes('recommendations')
+  ) {
+    const collection = await context.models.Collection.find(
+      get(object.collection, 'id'),
+    )
+    const teams = await helpers.getTeamsByPermissions(
+      user.teams,
+      ['reviewer'],
+      context.models.Team,
+    )
+    if (teams.length === 0) return false
+    const matchingTeam = teams.find(team => team.object.id === collection.id)
+    if (matchingTeam) return true
     return false
   }
 
diff --git a/packages/component-manuscript-manager/config/authsome-helpers.js b/packages/component-manuscript-manager/config/authsome-helpers.js
new file mode 100644
index 0000000000000000000000000000000000000000..30c00fdbe00f4f00c34324a81d363191da6d12a5
--- /dev/null
+++ b/packages/component-manuscript-manager/config/authsome-helpers.js
@@ -0,0 +1,83 @@
+const omit = require('lodash/omit')
+const config = require('config')
+const get = require('lodash/get')
+
+const statuses = config.get('statuses')
+
+const publicStatusesPermissions = ['author', 'reviewer']
+
+const parseAuthorsData = (coll, matchingCollPerm) => {
+  if (['reviewer'].includes(matchingCollPerm.permission)) {
+    coll.authors = coll.authors.map(a => omit(a, ['email']))
+  }
+}
+
+const setPublicStatuses = (coll, matchingCollPerm) => {
+  const status = get(coll, 'status') || 'draft'
+  coll.visibleStatus = statuses[status].public
+  if (!publicStatusesPermissions.includes(matchingCollPerm.permission)) {
+    coll.visibleStatus = statuses[coll.status].private
+  }
+}
+
+const filterRefusedInvitations = (coll, user) => {
+  const matchingInv = coll.invitations.find(inv => inv.userId === user.id)
+  if (matchingInv === undefined) return null
+  if (matchingInv.hasAnswer === true && !matchingInv.isAccepted) return null
+  return coll
+}
+
+const filterObjectData = (
+  collectionsPermissions = [],
+  object = {},
+  user = {},
+) => {
+  if (object.type === 'fragment') {
+    const matchingCollPerm = collectionsPermissions.find(
+      collPerm => object.id === collPerm.fragmentId,
+    )
+    if (matchingCollPerm === undefined) return null
+    if (['reviewer'].includes(matchingCollPerm.permission)) {
+      object.files = omit(object.files, ['coverLetter'])
+      if (object.recommendations)
+        object.recommendations = object.recommendations.filter(
+          rec => rec.userId === user.id,
+        )
+    }
+
+    return object
+  }
+  const matchingCollPerm = collectionsPermissions.find(
+    collPerm => object.id === collPerm.id,
+  )
+  if (matchingCollPerm === undefined) return null
+  setPublicStatuses(object, matchingCollPerm)
+  parseAuthorsData(object, matchingCollPerm)
+  if (['reviewer', 'handlingEditor'].includes(matchingCollPerm.permission)) {
+    return filterRefusedInvitations(object, user)
+  }
+
+  return object
+}
+
+const getTeamsByPermissions = async (teamIds = [], permissions, TeamModel) => {
+  const teams = await Promise.all(
+    teamIds.map(async teamId => {
+      const team = await TeamModel.find(teamId)
+      if (permissions.includes(team.teamType.permissions)) {
+        return team
+      }
+      return null
+    }),
+  )
+
+  return teams.filter(Boolean)
+}
+
+module.exports = {
+  parseAuthorsData,
+  setPublicStatuses,
+  filterRefusedInvitations,
+  filterObjectData,
+  getTeamsByPermissions,
+}
diff --git a/packages/component-manuscript-manager/config/authsome-mode.js b/packages/component-manuscript-manager/config/authsome-mode.js
new file mode 100644
index 0000000000000000000000000000000000000000..3498bc042c01679ecc1e75f8a783628e63cd153c
--- /dev/null
+++ b/packages/component-manuscript-manager/config/authsome-mode.js
@@ -0,0 +1,245 @@
+const get = require('lodash/get')
+const pickBy = require('lodash/pickBy')
+const omit = require('lodash/omit')
+const helpers = require('./authsome-helpers')
+
+async function teamPermissions(user, operation, object, context) {
+  const permissions = ['handlingEditor', 'author', 'reviewer']
+  const teams = await helpers.getTeamsByPermissions(
+    user.teams,
+    permissions,
+    context.models.Team,
+  )
+
+  const collectionsPermissions = await Promise.all(
+    teams.map(async team => {
+      const collection = await context.models.Collection.find(team.object.id)
+      const collPerm = {
+        id: collection.id,
+        permission: team.teamType.permissions,
+      }
+      const objectType = get(object, 'type')
+      if (objectType === 'fragment' && collection.fragments.includes(object.id))
+        collPerm.fragmentId = object.id
+
+      return collPerm
+    }),
+  )
+
+  if (collectionsPermissions.length === 0) return {}
+
+  return {
+    filter: filterParam => {
+      if (!filterParam.length) {
+        return helpers.filterObjectData(
+          collectionsPermissions,
+          filterParam,
+          user,
+        )
+      }
+
+      const collections = filterParam
+        .map(coll =>
+          helpers.filterObjectData(collectionsPermissions, coll, user),
+        )
+        .filter(Boolean)
+      return collections
+    },
+  }
+}
+
+function unauthenticatedUser(operation, object) {
+  // Public/unauthenticated users can GET /collections, filtered by 'published'
+  if (operation === 'GET' && object && object.path === '/collections') {
+    return {
+      filter: collections =>
+        collections.filter(collection => collection.published),
+    }
+  }
+
+  // Public/unauthenticated users can GET /collections/:id/fragments, filtered by 'published'
+  if (
+    operation === 'GET' &&
+    object &&
+    object.path === '/collections/:id/fragments'
+  ) {
+    return {
+      filter: fragments => fragments.filter(fragment => fragment.published),
+    }
+  }
+
+  // and filtered individual collection's properties: id, title, source, content, owners
+  if (operation === 'GET' && object && object.type === 'collection') {
+    if (object.published) {
+      return {
+        filter: collection =>
+          pickBy(collection, (_, key) =>
+            ['id', 'title', 'owners'].includes(key),
+          ),
+      }
+    }
+  }
+
+  if (operation === 'GET' && object && object.type === 'fragment') {
+    if (object.published) {
+      return {
+        filter: fragment =>
+          pickBy(fragment, (_, key) =>
+            ['id', 'title', 'source', 'presentation', 'owners'].includes(key),
+          ),
+      }
+    }
+  }
+
+  return false
+}
+
+async function authenticatedUser(user, operation, object, context) {
+  // Allow the authenticated user to POST a collection (but not with a 'filtered' property)
+  if (operation === 'POST' && object.path === '/collections') {
+    return {
+      filter: collection => omit(collection, 'filtered'),
+    }
+  }
+
+  // Allow the authenticated user to GET collections they own
+  if (operation === 'GET' && object === '/collections/') {
+    return {
+      filter: collection => collection.owners.includes(user.id),
+    }
+  }
+
+  // Allow owners of a collection to GET its teams, e.g.
+  // GET /api/collections/1/teams
+  if (operation === 'GET' && get(object, 'path') === '/teams') {
+    const collectionId = get(object, 'params.collectionId')
+    if (collectionId) {
+      const collection = await context.models.Collection.find(collectionId)
+      if (collection.owners.includes(user.id)) {
+        return true
+      }
+    }
+  }
+
+  if (
+    operation === 'GET' &&
+    get(object, 'type') === 'team' &&
+    get(object, 'object.type') === 'collection'
+  ) {
+    const collection = await context.models.Collection.find(
+      get(object, 'object.id'),
+    )
+    if (collection.owners.includes(user.id)) {
+      return true
+    }
+  }
+
+  // Advanced example
+  // Allow authenticated users to create a team based around a collection
+  // if they are one of the owners of this collection
+  if (['POST', 'PATCH'].includes(operation) && get(object, 'type') === 'team') {
+    if (get(object, 'object.type') === 'collection') {
+      const collection = await context.models.Collection.find(
+        get(object, 'object.id'),
+      )
+      if (collection.owners.includes(user.id)) {
+        return true
+      }
+    }
+  }
+
+  // only allow the HE to create, delete an invitation, or get invitation details
+  if (
+    ['POST', 'GET', 'DELETE'].includes(operation) &&
+    get(object.collection, 'type') === 'collection' &&
+    object.path.includes('invitations')
+  ) {
+    const collection = await context.models.Collection.find(
+      get(object.collection, 'id'),
+    )
+    const handlingEditor = get(collection, 'handlingEditor')
+    if (!handlingEditor) return false
+    if (handlingEditor.id === user.id) return true
+    return false
+  }
+
+  // only allow a reviewer to submit and to modify a recommendation
+  if (
+    ['POST', 'PATCH'].includes(operation) &&
+    get(object.collection, 'type') === 'collection' &&
+    object.path.includes('recommendations')
+  ) {
+    const collection = await context.models.Collection.find(
+      get(object.collection, 'id'),
+    )
+    const teams = await helpers.getTeamsByPermissions(
+      user.teams,
+      ['reviewer'],
+      context.models.Team,
+    )
+    if (teams.length === 0) return false
+    const matchingTeam = teams.find(team => team.object.id === collection.id)
+    if (matchingTeam) return true
+    return false
+  }
+
+  if (user.teams.length !== 0) {
+    const permissions = await teamPermissions(user, operation, object, context)
+
+    if (permissions) {
+      return permissions
+    }
+  }
+
+  if (get(object, 'type') === 'fragment') {
+    const fragment = object
+
+    if (fragment.owners.includes(user.id)) {
+      return true
+    }
+  }
+
+  if (get(object, 'type') === 'collection') {
+    if (['GET', 'DELETE'].includes(operation)) {
+      return true
+    }
+
+    // Only allow filtered updating (mirroring filtered creation) for non-admin users)
+    if (operation === 'PATCH') {
+      return {
+        filter: collection => omit(collection, 'filtered'),
+      }
+    }
+  }
+
+  // A user can GET, DELETE and PATCH itself
+  if (get(object, 'type') === 'user' && get(object, 'id') === user.id) {
+    if (['GET', 'DELETE', 'PATCH'].includes(operation)) {
+      return true
+    }
+  }
+  // If no individual permissions exist (above), fallback to unauthenticated
+  // user's permission
+  return unauthenticatedUser(operation, object)
+}
+
+const authsomeMode = async (userId, operation, object, context) => {
+  if (!userId) {
+    return unauthenticatedUser(operation, object)
+  }
+
+  // It's up to us to retrieve the relevant models for our
+  // authorization/authsome mode, e.g.
+  const user = await context.models.User.find(userId)
+
+  // Admins and editor in chiefs can do anything
+  if (user && (user.admin === true || user.editorInChief === true)) return true
+
+  if (user) {
+    return authenticatedUser(user, operation, object, context)
+  }
+
+  return false
+}
+
+module.exports = authsomeMode
diff --git a/packages/component-manuscript-manager/config/default.js b/packages/component-manuscript-manager/config/default.js
new file mode 100644
index 0000000000000000000000000000000000000000..7afbb2f22c26d8ae4d9f314989bc4a02189360f7
--- /dev/null
+++ b/packages/component-manuscript-manager/config/default.js
@@ -0,0 +1,58 @@
+const path = require('path')
+
+module.exports = {
+  authsome: {
+    mode: path.resolve(__dirname, 'authsome-mode.js'),
+    teams: {
+      handlingEditor: {
+        name: 'Handling Editors',
+      },
+      reviewer: {
+        name: 'Reviewer',
+      },
+    },
+  },
+  mailer: {
+    from: 'test@example.com',
+  },
+  'invite-reset-password': {
+    url:
+      process.env.PUBSWEET_INVITE_PASSWORD_RESET_URL ||
+      'http://localhost:3000/invite',
+  },
+  roles: {
+    global: ['admin', 'editorInChief', 'author', 'handlingEditor'],
+    collection: ['handlingEditor', 'reviewer', 'author'],
+    inviteRights: {
+      admin: ['admin', 'editorInChief', 'author'],
+      editorInChief: ['handlingEditor'],
+      handlingEditor: ['reviewer'],
+    },
+  },
+  statuses: {
+    draft: {
+      public: 'Draft',
+      private: 'Draft',
+    },
+    submitted: {
+      public: 'Submitted',
+      private: 'Submitted',
+    },
+    heInvited: {
+      public: 'Submitted',
+      private: 'HE Invited',
+    },
+    heAssigned: {
+      public: 'HE Assigned',
+      private: 'HE Assigned',
+    },
+    reviewersInvited: {
+      public: 'Reviewers Invited',
+      private: 'Reviewers Invited',
+    },
+    underReview: {
+      public: 'Under Review',
+      private: 'Under Review',
+    },
+  },
+}
diff --git a/packages/component-manuscript-manager/config/test.js b/packages/component-manuscript-manager/config/test.js
new file mode 100644
index 0000000000000000000000000000000000000000..0eb54780a931f66f1b611d9a4d51552908ece2c3
--- /dev/null
+++ b/packages/component-manuscript-manager/config/test.js
@@ -0,0 +1,59 @@
+const path = require('path')
+
+module.exports = {
+  authsome: {
+    mode: path.resolve(__dirname, 'authsome-mode.js'),
+    teams: {
+      handlingEditor: {
+        name: 'Handling Editors',
+      },
+      reviewer: {
+        name: 'Reviewer',
+      },
+    },
+  },
+  mailer: {
+    from: 'test@example.com',
+  },
+  'invite-reset-password': {
+    url:
+      process.env.PUBSWEET_INVITE_PASSWORD_RESET_URL ||
+      'http://localhost:3000/invite',
+  },
+  roles: {
+    global: ['admin', 'editorInChief', 'author', 'handlingEditor'],
+    collection: ['handlingEditor', 'reviewer', 'author'],
+    inviteRights: {
+      admin: ['admin', 'editorInChief', 'author', 'handlingEditor', 'author'],
+      editorInChief: ['handlingEditor'],
+      handlingEditor: ['reviewer'],
+      author: ['author'],
+    },
+  },
+  statuses: {
+    draft: {
+      public: 'Draft',
+      private: 'Draft',
+    },
+    submitted: {
+      public: 'Submitted',
+      private: 'Submitted',
+    },
+    heInvited: {
+      public: 'Submitted',
+      private: 'HE Invited',
+    },
+    heAssigned: {
+      public: 'HE Assigned',
+      private: 'HE Assigned',
+    },
+    reviewersInvited: {
+      public: 'Reviewers Invited',
+      private: 'Reviewers Invited',
+    },
+    underReview: {
+      public: 'Under Review',
+      private: 'Under Review',
+    },
+  },
+}
diff --git a/packages/component-manuscript-manager/src/helpers/Collection.js b/packages/component-manuscript-manager/src/helpers/Collection.js
new file mode 100644
index 0000000000000000000000000000000000000000..4949969b040748ff54163782eda0155acd6ec789
--- /dev/null
+++ b/packages/component-manuscript-manager/src/helpers/Collection.js
@@ -0,0 +1,13 @@
+const config = require('config')
+
+const statuses = config.get('statuses')
+
+const updateStatus = async (collection, newStatus) => {
+  collection.status = newStatus
+  collection.visibleStatus = statuses[collection.status].private
+  await collection.save()
+}
+
+module.exports = {
+  updateStatus,
+}
diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/patch.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/patch.js
index 2e4ee8ae1fd06f711b803bd0af93dcbad6aa6f71..9c1b974768e0c4e9a009cce1f858dc9f1ea02864 100644
--- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/patch.js
+++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/patch.js
@@ -1,5 +1,6 @@
 const helpers = require('../../helpers/helpers')
 const authsomeHelper = require('../../helpers/authsome')
+const collectionHelper = require('../../helpers/Collection')
 
 module.exports = models => async (req, res) => {
   const { collectionId, fragmentId, recommendationId } = req.params
@@ -15,8 +16,8 @@ module.exports = models => async (req, res) => {
       collection,
       path: req.route.path,
     }
-    const canPost = await authsome.can(req.user, 'PATCH', target)
-    if (!canPost)
+    const canPatch = await authsome.can(req.user, 'PATCH', target)
+    if (!canPatch)
       return res.status(403).json({
         error: 'Unauthorized.',
       })
@@ -32,6 +33,8 @@ module.exports = models => async (req, res) => {
       })
     Object.assign(recommendation, req.body)
     recommendation.updatedOn = Date.now()
+    if (req.body.submittedOn !== undefined)
+      await collectionHelper.updateStatus(collection, 'reviewCompleted')
     await fragment.save()
     return res.status(200).json(recommendation)
   } catch (e) {
diff --git a/packages/component-manuscript-manager/src/tests/fixtures/fixtures.js b/packages/component-manuscript-manager/src/tests/fixtures/fixtures.js
index 4ca540342b93acc22bf7903e6f5f8251481bc6ca..cbb5c85cbe056c7dc633db935bf5707764ac40bd 100644
--- a/packages/component-manuscript-manager/src/tests/fixtures/fixtures.js
+++ b/packages/component-manuscript-manager/src/tests/fixtures/fixtures.js
@@ -1,9 +1,11 @@
 const users = require('./users')
 const collections = require('./collections')
 const fragments = require('./fragments')
+const teams = require('./teams')
 
 module.exports = {
   users,
   collections,
   fragments,
+  teams,
 }
diff --git a/packages/component-manuscript-manager/src/tests/fixtures/fragments.js b/packages/component-manuscript-manager/src/tests/fixtures/fragments.js
index c64478c3390cb63db38602cced003cf97087a32f..0bc2a06b2cacf0a2a2dcb83ee5202cf9059f3618 100644
--- a/packages/component-manuscript-manager/src/tests/fixtures/fragments.js
+++ b/packages/component-manuscript-manager/src/tests/fixtures/fragments.js
@@ -1,4 +1,5 @@
 const Chance = require('chance')
+const { recReviewer } = require('./userData')
 
 const chance = new Chance()
 const fragments = {
@@ -9,6 +10,29 @@ const fragments = {
       abstract: chance.paragraph(),
     },
     save: jest.fn(),
+    recommendations: [
+      {
+        recommendation: 'accept',
+        recommendationType: 'review',
+        comments: [
+          {
+            content: chance.paragraph(),
+            public: chance.bool(),
+            files: [
+              {
+                id: chance.guid(),
+                name: 'file.pdf',
+                size: chance.natural(),
+              },
+            ],
+          },
+        ],
+        id: chance.guid(),
+        userId: recReviewer.id,
+        createdOn: chance.timestamp(),
+        updatedOn: chance.timestamp(),
+      },
+    ],
   },
 }
 
diff --git a/packages/component-manuscript-manager/src/tests/fixtures/teamIDs.js b/packages/component-manuscript-manager/src/tests/fixtures/teamIDs.js
new file mode 100644
index 0000000000000000000000000000000000000000..607fd6661b1e7c9848bf13257a0d198f230fab00
--- /dev/null
+++ b/packages/component-manuscript-manager/src/tests/fixtures/teamIDs.js
@@ -0,0 +1,10 @@
+const Chance = require('chance')
+
+const chance = new Chance()
+const heID = chance.guid()
+const revId = chance.guid()
+
+module.exports = {
+  heTeamID: heID,
+  revTeamID: revId,
+}
diff --git a/packages/component-manuscript-manager/src/tests/fixtures/teams.js b/packages/component-manuscript-manager/src/tests/fixtures/teams.js
new file mode 100644
index 0000000000000000000000000000000000000000..fb2a14eb33ff92d6e39b4763a7ebe89f46028d5c
--- /dev/null
+++ b/packages/component-manuscript-manager/src/tests/fixtures/teams.js
@@ -0,0 +1,25 @@
+const users = require('./users')
+const collections = require('./collections')
+const { revTeamID } = require('./teamIDs')
+
+const { collection } = collections
+const { reviewer } = users
+const teams = {
+  revTeam: {
+    teamType: {
+      name: 'reviewer',
+      permissions: 'reviewer',
+    },
+    group: 'reviewer',
+    name: 'reviewer',
+    object: {
+      type: 'collection',
+      id: collection.id,
+    },
+    members: [reviewer.id],
+    save: jest.fn(() => teams.revTeam),
+    updateProperties: jest.fn(() => teams.revTeam),
+    id: revTeamID,
+  },
+}
+module.exports = teams
diff --git a/packages/component-manuscript-manager/src/tests/fixtures/userData.js b/packages/component-manuscript-manager/src/tests/fixtures/userData.js
index 546e2d867998c6de1cab8e10a4df20fb74d5288d..4e3b994a70b782f25ec85e0f41410824dd4307c4 100644
--- a/packages/component-manuscript-manager/src/tests/fixtures/userData.js
+++ b/packages/component-manuscript-manager/src/tests/fixtures/userData.js
@@ -15,4 +15,5 @@ module.exports = {
   author: generateUserData(),
   reviewer: generateUserData(),
   answerReviewer: generateUserData(),
+  recReviewer: generateUserData(),
 }
diff --git a/packages/component-manuscript-manager/src/tests/fixtures/users.js b/packages/component-manuscript-manager/src/tests/fixtures/users.js
index f3ede318fb34ae24db90440959bd3822f186fbf6..8ac951e6a00bfa0a4be5d6584a0eca881560cda3 100644
--- a/packages/component-manuscript-manager/src/tests/fixtures/users.js
+++ b/packages/component-manuscript-manager/src/tests/fixtures/users.js
@@ -1,4 +1,6 @@
-const { reviewer } = require('./userData')
+const { reviewer, author, recReviewer } = require('./userData')
+const { revTeamID } = require('./teamIDs')
+
 const Chance = require('chance')
 
 const chance = new Chance()
@@ -16,7 +18,36 @@ const users = {
     title: 'Mr',
     save: jest.fn(() => users.reviewer),
     isConfirmed: true,
-    invitationToken: 'inv-token-123',
+    teams: [revTeamID],
+  },
+  author: {
+    type: 'user',
+    username: chance.word(),
+    email: author.email,
+    password: 'password',
+    admin: false,
+    id: author.id,
+    firstName: author.firstName,
+    lastName: author.lastName,
+    affiliation: chance.company(),
+    title: 'Mr',
+    save: jest.fn(() => users.author),
+    isConfirmed: true,
+  },
+  recReviewer: {
+    type: 'user',
+    username: chance.word(),
+    email: recReviewer.email,
+    password: 'password',
+    admin: false,
+    id: recReviewer.id,
+    firstName: recReviewer.firstName,
+    lastName: recReviewer.lastName,
+    affiliation: chance.company(),
+    title: 'Mr',
+    save: jest.fn(() => users.recReviewer),
+    isConfirmed: true,
+    teams: [revTeamID],
   },
 }
 
diff --git a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/patch.test.js b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/patch.test.js
index 840d74cc57229a4e604ecf3d10e1f6c9f5c30470..773188df8be57312ea9ab5e83b3c724db224065c 100644
--- a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/patch.test.js
+++ b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/patch.test.js
@@ -27,7 +27,11 @@ const reqBody = {
 }
 
 const path = '../../routes/fragmentsRecommendations/patch'
-describe('Patch collections invitations route handler', () => {
+const route = {
+  path:
+    '/api/collections/:collectionId/fragments/:fragmentId/recommendations/:recommendationId',
+}
+describe('Patch fragments recommendations route handler', () => {
   let testFixtures = {}
   let body = {}
   let models
@@ -36,30 +40,16 @@ describe('Patch collections invitations route handler', () => {
     body = cloneDeep(reqBody)
     models = Model.build(testFixtures)
   })
-  it('should return an error when params are missing', async () => {
-    const { reviewer } = testFixtures.users
-    delete body.comments
-    const res = await requests.sendRequest({
-      body,
-      userId: reviewer.id,
-      models,
-      path,
-    })
-
-    expect(res.statusCode).toBe(400)
-    const data = JSON.parse(res._getData())
-    expect(data.error).toEqual('Parameters are missing.')
-  })
   it('should return success when the parameters are correct', async () => {
-    const { reviewer } = testFixtures.users
+    const { recReviewer } = testFixtures.users
     const { collection } = testFixtures.collections
     const { fragment } = testFixtures.fragments
     const recommendation = fragment.recommendations[0]
-
     const res = await requests.sendRequest({
       body,
-      userId: reviewer.id,
+      userId: recReviewer.id,
       models,
+      route,
       path,
       params: {
         collectionId: collection.id,
@@ -70,7 +60,7 @@ describe('Patch collections invitations route handler', () => {
 
     expect(res.statusCode).toBe(200)
     const data = JSON.parse(res._getData())
-    expect(data.userId).toEqual(reviewer.id)
+    expect(data.userId).toEqual(recReviewer.id)
   })
   it('should return an error when the fragmentId does not match the collectionId', async () => {
     const { reviewer } = testFixtures.users
@@ -83,6 +73,7 @@ describe('Patch collections invitations route handler', () => {
       body,
       userId: reviewer.id,
       models,
+      route,
       path,
       params: {
         collectionId: collection.id,
@@ -103,6 +94,7 @@ describe('Patch collections invitations route handler', () => {
       body,
       userId: reviewer.id,
       models,
+      route,
       path,
       params: {
         collectionId: 'invalid-id',
@@ -117,12 +109,13 @@ describe('Patch collections invitations route handler', () => {
   })
   it('should return an error when the recommendation does not exist', async () => {
     const { reviewer } = testFixtures.users
-    const { collection } = testFixtures.collection
+    const { collection } = testFixtures.collections
     const { fragment } = testFixtures.fragments
     const res = await requests.sendRequest({
       body,
       userId: reviewer.id,
       models,
+      route,
       path,
       params: {
         collectionId: collection.id,
@@ -133,6 +126,27 @@ describe('Patch collections invitations route handler', () => {
 
     expect(res.statusCode).toBe(404)
     const data = JSON.parse(res._getData())
-    expect(data.error).toEqual('Item not found')
+    expect(data.error).toEqual('Recommendation not found.')
+  })
+  it('should return an error when the request user is not a reviewer', async () => {
+    const { author } = testFixtures.users
+    const { collection } = testFixtures.collections
+    const { fragment } = testFixtures.fragments
+
+    const res = await requests.sendRequest({
+      body,
+      userId: author.id,
+      models,
+      route,
+      path,
+      params: {
+        collectionId: collection.id,
+        fragmentId: fragment.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(403)
+    const data = JSON.parse(res._getData())
+    expect(data.error).toEqual('Unauthorized.')
   })
 })
diff --git a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js
index 1bc3506019b290db9b0dea571f22a454e18002f2..ca11f8fa76ea5cd757abfd6710fc2482f9d33981 100644
--- a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js
+++ b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js
@@ -27,7 +27,10 @@ const reqBody = {
 }
 
 const path = '../../routes/fragmentsRecommendations/post'
-describe('Post collections invitations route handler', () => {
+const route = {
+  path: '/api/collections/:collectionId/fragments/:fragmentId/recommendations',
+}
+describe('Post fragments recommendations route handler', () => {
   let testFixtures = {}
   let body = {}
   let models
@@ -38,17 +41,18 @@ describe('Post collections invitations route handler', () => {
   })
   it('should return an error when params are missing', async () => {
     const { reviewer } = testFixtures.users
-    delete body.comments
+    delete body.recommendationType
     const res = await requests.sendRequest({
       body,
       userId: reviewer.id,
+      route,
       models,
       path,
     })
 
     expect(res.statusCode).toBe(400)
     const data = JSON.parse(res._getData())
-    expect(data.error).toEqual('Parameters are missing.')
+    expect(data.error).toEqual('Recommendation type is required.')
   })
   it('should return success when the parameters are correct', async () => {
     const { reviewer } = testFixtures.users
@@ -59,6 +63,7 @@ describe('Post collections invitations route handler', () => {
       body,
       userId: reviewer.id,
       models,
+      route,
       path,
       params: {
         collectionId: collection.id,
@@ -79,6 +84,7 @@ describe('Post collections invitations route handler', () => {
       body,
       userId: reviewer.id,
       models,
+      route,
       path,
       params: {
         collectionId: collection.id,
@@ -97,6 +103,7 @@ describe('Post collections invitations route handler', () => {
       body,
       userId: reviewer.id,
       models,
+      route,
       path,
       params: {
         collectionId: 'invalid-id',
@@ -108,4 +115,25 @@ describe('Post collections invitations route handler', () => {
     const data = JSON.parse(res._getData())
     expect(data.error).toEqual('Item not found')
   })
+  it('should return an error when the request user is not a reviewer', async () => {
+    const { author } = testFixtures.users
+    const { collection } = testFixtures.collections
+    const { fragment } = testFixtures.fragments
+
+    const res = await requests.sendRequest({
+      body,
+      userId: author.id,
+      models,
+      route,
+      path,
+      params: {
+        collectionId: collection.id,
+        fragmentId: fragment.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(403)
+    const data = JSON.parse(res._getData())
+    expect(data.error).toEqual('Unauthorized.')
+  })
 })
diff --git a/packages/component-manuscript-manager/src/tests/helpers/Model.js b/packages/component-manuscript-manager/src/tests/helpers/Model.js
index ce46f395b170438c22d8e7c6be2a8e0fd7fabba7..3d6ae0871452e134c63f65913af6b9de4b210f8a 100644
--- a/packages/component-manuscript-manager/src/tests/helpers/Model.js
+++ b/packages/component-manuscript-manager/src/tests/helpers/Model.js
@@ -15,6 +15,9 @@ const build = fixtures => {
     Fragment: {
       find: jest.fn(id => findMock(id, 'fragments', fixtures)),
     },
+    Team: {
+      find: jest.fn(id => findMock(id, 'teams', fixtures)),
+    },
   }
   UserMock.find = jest.fn(id => findMock(id, 'users', fixtures))
   models.User = UserMock
diff --git a/packages/xpub-faraday/config/authsome-helpers.js b/packages/xpub-faraday/config/authsome-helpers.js
index b5f42492b077cee12d5a09d97404fb559e601f5e..30c00fdbe00f4f00c34324a81d363191da6d12a5 100644
--- a/packages/xpub-faraday/config/authsome-helpers.js
+++ b/packages/xpub-faraday/config/authsome-helpers.js
@@ -60,7 +60,7 @@ const filterObjectData = (
   return object
 }
 
-const getTeamsByPermissions = async (teamIds, permissions, TeamModel) => {
+const getTeamsByPermissions = async (teamIds = [], permissions, TeamModel) => {
   const teams = await Promise.all(
     teamIds.map(async teamId => {
       const team = await TeamModel.find(teamId)
diff --git a/packages/xpub-faraday/config/default.js b/packages/xpub-faraday/config/default.js
index a773b41f2bd0746604c0ca261d1b0aa01fe5267d..4edb74bf17a47ed1c72ed63d7420dbe2276aed9f 100644
--- a/packages/xpub-faraday/config/default.js
+++ b/packages/xpub-faraday/config/default.js
@@ -114,5 +114,9 @@ module.exports = {
       public: 'Under Review',
       private: 'Under Review',
     },
+    reviewCompleted: {
+      public: 'Under Review',
+      private: 'Review Completed',
+    },
   },
 }