diff --git a/README.md b/README.md
index 7099c5b1b78c887d30e06463b54698871abdc115..ca0f91f81e9a6abe154cc83c6bc3f4ddef5ddb21 100644
--- a/README.md
+++ b/README.md
@@ -47,3 +47,9 @@ Contact us at technology@hindawi.com for help getting setup.
 ## Community
 
 Join [the Mattermost channel](https://mattermost.coko.foundation/coko/channels/xpub) for discussion of xpub.
+
+
+## Migrations
+
+1. use folder `./packages/xpub-faraday/migrations`
+2. add file named `${number}-${name}(.sql/.js)` e.g. `001-user-add-name-field.sql`
diff --git a/packages/component-faraday-selectors/src/index.js b/packages/component-faraday-selectors/src/index.js
index 5801110f0164d57e8d2e4cf366f20b639fed611c..0ab630ff6cb341f42ab8850b631ba4d270f26f10 100644
--- a/packages/component-faraday-selectors/src/index.js
+++ b/packages/component-faraday-selectors/src/index.js
@@ -1,5 +1,5 @@
-import { get, has, last, chain, some } from 'lodash'
 import { selectCurrentUser } from 'xpub-selectors'
+import { get, has, last, chain, some } from 'lodash'
 
 export const isHEToManuscript = (state, collectionId = '') => {
   const { id = '', isAccepted = false } = chain(state)
@@ -199,9 +199,7 @@ export const getHERecommendation = (state, collectionId, fragmentId) => {
 }
 
 const canMakeDecisionStatuses = ['submitted', 'pendingApproval']
-export const canMakeDecision = (state, collection = {}, fragment = {}) => {
-  if (get(fragment, 'id', '') !== last(get(collection, 'fragments', [])))
-    return false
+export const canMakeDecision = (state, collection = {}) => {
   const status = get(collection, 'status', 'draft')
 
   const isEIC = currentUserIs(state, 'adminEiC')
@@ -256,11 +254,11 @@ export const currentUserIsAuthor = (state, id) => {
     .includes(id)
 }
 
-export const getUserPermissions = ({ currentUser }) =>
-  get(currentUser, 'user.teams', []).map(t => ({
-    objectId: t.object.id,
-    objectType: t.object.type,
-    role: t.teamType.permissions,
+export const getUserPermissions = ({ teams = [] }) =>
+  teams.map(t => ({
+    objectId: get(t, 'object.id', ''),
+    objectType: get(t, 'object.type', ''),
+    role: get(t, 'teamType.permissions', ''),
   }))
 
 export const userNotConfirmed = ({ currentUser }) =>
@@ -412,18 +410,6 @@ export const getOwnSubmittedRecommendation = (state, fragmentId) =>
     )
     .value()
 
-const canMakeRecommendationStatuses = [
-  'heAssigned',
-  'underReview',
-  'reviewCompleted',
-]
-export const canMakeRecommendation = (state, collection, fragment = {}) => {
-  if (fragment.id !== last(get(collection, 'fragments', []))) return false
-  const isHE = isHEToManuscript(state, get(collection, 'id', ''))
-  const status = get(collection, 'status', 'draft')
-  return isHE && canMakeRecommendationStatuses.includes(status)
-}
-
 export const canSubmitRevision = (state, fragment = {}) => {
   const userId = get(state, 'currentUser.user.id')
   const fragmentAuthors = chain(fragment)
@@ -453,3 +439,14 @@ export const getVersionOptions = (state, collection = {}) => {
     .reverse()
     .value()
 }
+
+export const canReview = (state, collection = {}, fragment = {}) => {
+  const fragmentId = get(fragment, 'id', false)
+
+  if (!fragmentId) return false
+
+  const isReviewer = currentUserIsReviewer(state, fragmentId)
+  if (!isReviewer) return false
+
+  return get(collection, 'status', 'draft') === 'underReview'
+}
diff --git a/packages/component-faraday-ui/src/ReviewerReportAuthor.js b/packages/component-faraday-ui/src/ReviewerReportAuthor.js
index 297653497f8a77be8c9bf20135ca64c7c21a54a4..4df5745b8ce86a109bad547466f3fe5ff57f94de 100644
--- a/packages/component-faraday-ui/src/ReviewerReportAuthor.js
+++ b/packages/component-faraday-ui/src/ReviewerReportAuthor.js
@@ -1,16 +1,24 @@
 import React, { Fragment } from 'react'
 import { get } from 'lodash'
-import { withProps } from 'recompose'
+import { withProps, compose } from 'recompose'
 import styled from 'styled-components'
 import { th } from '@pubsweet/ui-toolkit'
 import { DateParser } from '@pubsweet/ui'
 
-import { Label, Item, FileItem, Row, Text } from './'
+import {
+  Label,
+  Item,
+  FileItem,
+  Row,
+  Text,
+  withFilePreview,
+  withFileDownload,
+} from './'
 
 const ReviewerReportAuthor = ({
-  onPreview,
-  onDownload,
   reviewFile,
+  previewFile,
+  downloadFile,
   publicReport,
   reviewerName,
   reviewerIndex,
@@ -45,8 +53,8 @@ const ReviewerReportAuthor = ({
           <Item flex={0} mr={1}>
             <FileItem
               item={reviewFile}
-              onDownload={onDownload}
-              onPreview={onPreview}
+              onDownload={downloadFile}
+              onPreview={previewFile}
             />
           </Item>
         </Row>
@@ -55,20 +63,24 @@ const ReviewerReportAuthor = ({
   </Root>
 )
 
-export default withProps(({ report, journal: { recommendations = [] } }) => ({
-  recommendation: get(
-    recommendations.find(r => r.value === report.recommendation),
-    'label',
-  ),
-  reviewFile: get(report, 'comments.0.files.0'),
-  publicReport: get(report, 'comments.0.content'),
-  reviewerName: `${get(report, 'reviewer.firstName', '')} ${get(
-    report,
-    'reviewer.lastName',
-    '',
-  )}`,
-  reviewerIndex: get(report, 'reviewerIndex', ''),
-}))(ReviewerReportAuthor)
+export default compose(
+  withFilePreview,
+  withFileDownload,
+  withProps(({ report, journal: { recommendations = [] } }) => ({
+    recommendation: get(
+      recommendations.find(r => r.value === report.recommendation),
+      'label',
+    ),
+    reviewFile: get(report, 'comments.0.files.0'),
+    publicReport: get(report, 'comments.0.content'),
+    reviewerName: `${get(report, 'reviewer.firstName', '')} ${get(
+      report,
+      'reviewer.lastName',
+      '',
+    )}`,
+    reviewerIndex: get(report, 'reviewerIndex', ''),
+  })),
+)(ReviewerReportAuthor)
 
 // #region styles
 const Root = styled.div`
diff --git a/packages/component-faraday-ui/src/Tag.js b/packages/component-faraday-ui/src/Tag.js
index 856a69c88fb0f25ed6a64ed3368221239d961d81..fd6ce0316577b29f1ca95619cdd180a860209c54 100644
--- a/packages/component-faraday-ui/src/Tag.js
+++ b/packages/component-faraday-ui/src/Tag.js
@@ -1,27 +1,41 @@
-import styled, { css } from 'styled-components'
+import { has } from 'lodash'
 import { th } from '@pubsweet/ui-toolkit'
+import styled, { css } from 'styled-components'
 
 import { marginHelper } from './styledHelpers'
 
-export const tagCSS = ({ status }) =>
-  status
-    ? css`
-        padding: calc(${th('gridUnit')} / 4) ${th('gridUnit')};
-        height: 24px;
-        font-family: ${th('fontHeading')};
-      `
-    : css`
-        height: 14px;
-        font-size: 85%;
-        padding: calc(${th('gridUnit')} / 4) calc(${th('gridUnit')} / 4) 0px;
-        margin-right: 1px;
-        font-family: ${th('fontInterface')};
-      `
+const tagCSS = props => {
+  if (has(props, 'oldStatus')) {
+    return css`
+      background-color: ${th('colorFurnitureHue')};
+      height: calc(${th('gridUnit')} * 3)
+      font-weight: ${th('tag.fontWeight')};
+      padding: calc(${th('gridUnit')} / 2) ${th('gridUnit')} 0px
+        ${th('gridUnit')};
+    `
+  }
+
+  if (has(props, `status`)) {
+    return css`
+      background-color: ${th('tag.statusBackgroundColor')};
+      padding: calc(${th('gridUnit')} / 4) ${th('gridUnit')};
+      height: 24px;
+      font-family: ${th('fontHeading')};
+    `
+  }
+
+  return css`
+    background-color: ${th('tag.backgroundColor')};
+    height: 14px;
+    font-size: 85%;
+    padding: calc(${th('gridUnit')} / 4) calc(${th('gridUnit')} / 4) 0px;
+    margin-right: 1px;
+    font-family: ${th('fontInterface')};
+  `
+}
 
 /** @component */
 export default styled.div`
-  background-color: ${({ status }) =>
-    status ? th('tag.statusBackgroundColor') : th('tag.backgroundColor')};
   border-radius: ${th('tag.borderRadius')
     ? th('tag.borderRadius')
     : th('borderRadius')};
diff --git a/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js b/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js
index 105b76fc04c6a4046c794398157ee770135ad538..5518b3ebfa9c3803816c871f4f8b32b717c468d3 100644
--- a/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js
+++ b/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js
@@ -15,7 +15,14 @@ const SubmittedReportsNumberForAuthorReviews = ({ reports }) => (
   </Row>
 )
 
-const AuthorReviews = ({ invitations, journal, reports, fragment }) =>
+const AuthorReviews = ({
+  invitations,
+  journal,
+  reports,
+  fragment,
+  token,
+  getSignedUrl,
+}) =>
   reports.length > 0 && (
     <ContextualBox
       label="Reviewer Reports"
@@ -24,11 +31,13 @@ const AuthorReviews = ({ invitations, journal, reports, fragment }) =>
         <SubmittedReportsNumberForAuthorReviews reports={reports.length} />
       }
     >
-      {reports.map((r, i) => (
+      {reports.map(r => (
         <ReviewerReportAuthor
+          getSignedUrl={getSignedUrl}
           journal={journal}
           key={r.id}
-          report={reports[i]}
+          report={r}
+          token={token}
         />
       ))}
     </ContextualBox>
diff --git a/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js
index 487d83cb1fa6c387883a108fd1f8644897711ce9..4d3d4b181d864cd2b5c829ad06902b058a3c09ec 100644
--- a/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js
+++ b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js
@@ -5,8 +5,8 @@ import { ContextualBox, AuthorReply } from '../'
 const ResponseToRevisionRequest = ({
   fragment,
   authorReply,
-  expanded,
   toggle,
+  expanded,
 }) => (
   <ContextualBox
     expanded={expanded}
diff --git a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js
index efa929afe32fd35476948eca48e366414aaa3c15..d8a41b821abe0639bbb6f9cfbe6ffe17b9f75189 100644
--- a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js
+++ b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js
@@ -40,6 +40,7 @@ const ReviewerDetails = ({
   highlight,
   canViewReviewersDetails,
   authorCanViewReportsDetails,
+  isLatestVersion,
   ...rest
 }) => (
   <ContextualBox
@@ -62,17 +63,18 @@ const ReviewerDetails = ({
             >
               <H4>Reviewer Details</H4>
             </TabButton>
-            {canInviteReviewers && (
-              <TabButton
-                data-test-id="reviewer-tab-suggestions"
-                ml={1}
-                mr={1}
-                onClick={() => changeTab(2)}
-                selected={selectedTab === 2}
-              >
-                <H4>Reviewer Suggestions</H4>
-              </TabButton>
-            )}
+            {canInviteReviewers &&
+              isLatestVersion && (
+                <TabButton
+                  data-test-id="reviewer-tab-suggestions"
+                  ml={1}
+                  mr={1}
+                  onClick={() => changeTab(2)}
+                  selected={selectedTab === 2}
+                >
+                  <H4>Reviewer Suggestions</H4>
+                </TabButton>
+              )}
             <TabButton
               data-test-id="reviewer-tab-reports"
               ml={1}
@@ -87,12 +89,13 @@ const ReviewerDetails = ({
           <TabContent>
             {selectedTab === 0 && (
               <Fragment>
-                {canInviteReviewers && (
-                  <InviteReviewers
-                    modalKey="invite-reviewers"
-                    onInvite={onInviteReviewer}
-                  />
-                )}
+                {canInviteReviewers &&
+                  isLatestVersion && (
+                    <InviteReviewers
+                      modalKey="invite-reviewers"
+                      onInvite={onInviteReviewer}
+                    />
+                  )}
 
                 <ReviewersTable
                   invitations={invitations}
@@ -101,14 +104,15 @@ const ReviewerDetails = ({
                 />
               </Fragment>
             )}
-            {selectedTab === 2 && (
-              <PublonsTable
-                onInvite={onInvitePublonReviewer}
-                publonsError={fetchingError}
-                publonsFetching={isFetching}
-                reviewers={publonReviewers}
-              />
-            )}
+            {selectedTab === 2 &&
+              isLatestVersion && (
+                <PublonsTable
+                  onInvite={onInvitePublonReviewer}
+                  publonsError={fetchingError}
+                  publonsFetching={isFetching}
+                  reviewers={publonReviewers}
+                />
+              )}
             {selectedTab === 1 && (
               <Fragment>
                 {reports.length === 0 && (
diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js
index b7e6f5389f196f87344e2b5f35a2f0630117c644..f93e6c4c396f67836c8d1142000cc05682aac647 100644
--- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js
+++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js
@@ -23,6 +23,7 @@ const ManuscriptHeader = ({
   manuscriptType = {},
   editorInChief = 'Unassigned',
   collection: { visibleStatus = 'Draft', customId, handlingEditor },
+  isLatestVersion,
 }) => {
   const { authors = [], metadata = {}, submitted = null } = fragment
   const { title = 'No title', journal = '', type = '' } = metadata
@@ -34,9 +35,13 @@ const ManuscriptHeader = ({
         justify="space-between"
       >
         <H2 mb={1}>{title}</H2>
-        <Tag data-test-id="fragment-status" status>
-          {visibleStatus}
-        </Tag>
+        {isLatestVersion ? (
+          <Tag data-test-id="fragment-status" status>
+            {visibleStatus}
+          </Tag>
+        ) : (
+          <Tag oldStatus>Viewing an Older Version</Tag>
+        )}
       </Row>
       {authors.length > 0 && (
         <Row
diff --git a/packages/component-fixture-manager/src/fixtures/collectionIDs.js b/packages/component-fixture-manager/src/fixtures/collectionIDs.js
index b76d29095f8be6cef5c9076d692ca9f46f00fab0..5b0da41bf1758f75c2b1394ca7f42ef812761ccc 100644
--- a/packages/component-fixture-manager/src/fixtures/collectionIDs.js
+++ b/packages/component-fixture-manager/src/fixtures/collectionIDs.js
@@ -6,4 +6,5 @@ module.exports = {
   standardCollID: chance.guid(),
   collectionReviewCompletedID: chance.guid(),
   collectionNoInvitesID: chance.guid(),
+  twoVersionsCollectionId: chance.guid(),
 }
diff --git a/packages/component-fixture-manager/src/fixtures/collections.js b/packages/component-fixture-manager/src/fixtures/collections.js
index 42ad95ce500baa7a635cf2897de350c1c8908b1d..c0e6b797fa5259fffc927c1be6b11664cd6f5e59 100644
--- a/packages/component-fixture-manager/src/fixtures/collections.js
+++ b/packages/component-fixture-manager/src/fixtures/collections.js
@@ -10,12 +10,14 @@ const {
   standardCollID,
   collectionReviewCompletedID,
   collectionNoInvitesID,
+  twoVersionsCollectionId,
 } = require('./collectionIDs')
 
 const chance = new Chance()
 const collections = {
   collection: {
     id: standardCollID,
+    delete: jest.fn(),
     title: chance.sentence(),
     type: 'collection',
     fragments: [fragment.id],
@@ -58,6 +60,7 @@ const collections = {
   },
   collection1: {
     id: standardCollID,
+    delete: jest.fn(),
     title: chance.sentence(),
     type: 'collection',
     fragments: [fragment.id],
@@ -142,6 +145,7 @@ const collections = {
   },
   collectionReviewCompleted: {
     id: collectionReviewCompletedID,
+    delete: jest.fn(),
     type: 'collection',
     owners: [user.id],
     status: 'reviewCompleted',
@@ -171,6 +175,36 @@ const collections = {
     },
     technicalChecks: {},
   },
+  twoVersionsCollection: {
+    id: twoVersionsCollectionId,
+    title: chance.sentence(),
+    type: 'collection',
+    fragments: [fragment.id, reviewCompletedFragment.id],
+    owners: [user.id],
+    save: jest.fn(() => collections.collection),
+    invitations: [
+      {
+        id: chance.guid(),
+        role: 'handlingEditor',
+        hasAnswer: true,
+        isAccepted: false,
+        userId: handlingEditor.id,
+        invitedOn: chance.timestamp(),
+        respondedOn: null,
+      },
+    ],
+    handlingEditor: {
+      id: handlingEditor.id,
+      hasAnswer: false,
+      isAccepted: false,
+      email: handlingEditor.email,
+      invitedOn: chance.timestamp(),
+      respondedOn: null,
+      name: `${handlingEditor.firstName} ${handlingEditor.lastName}`,
+    },
+    status: 'revisionRequested',
+    customId: chance.natural({ min: 999999, max: 9999999 }),
+  },
 }
 
 module.exports = collections
diff --git a/packages/component-fixture-manager/src/fixtures/fragments.js b/packages/component-fixture-manager/src/fixtures/fragments.js
index d2321b0a8571ed9c31d94d59cd47b4db3a010fe0..9fca41e0ffba404be7fd612dd6feb483e6a23763 100644
--- a/packages/component-fixture-manager/src/fixtures/fragments.js
+++ b/packages/component-fixture-manager/src/fixtures/fragments.js
@@ -20,6 +20,12 @@ const chance = new Chance()
 const fragments = {
   fragment: {
     id: chance.guid(),
+    delete: jest.fn(),
+    files: {
+      manuscripts: [{ id: chance.guid() }],
+      coverLetter: [],
+      supplementary: [],
+    },
     collectionId: standardCollID,
     metadata: {
       title: chance.sentence(),
@@ -182,6 +188,12 @@ const fragments = {
   },
   noParentFragment: {
     id: chance.guid(),
+    delete: jest.fn(),
+    files: {
+      manuscripts: [{ id: chance.guid() }],
+      coverLetter: [],
+      supplementary: [],
+    },
     collectionId: '',
     metadata: {
       title: chance.sentence(),
@@ -201,9 +213,9 @@ const fragments = {
   },
   reviewCompletedFragment: {
     id: chance.guid(),
+    delete: jest.fn(),
     type: 'fragment',
     files: {
-      coverLetter: [],
       manuscripts: [
         {
           id:
@@ -213,6 +225,7 @@ const fragments = {
           originalName: 'LinkedInProfileDemystified.pdf',
         },
       ],
+      coverLetter: [],
       supplementary: [],
     },
     owners: [user.id],
diff --git a/packages/component-fixture-manager/src/fixtures/teams.js b/packages/component-fixture-manager/src/fixtures/teams.js
index 630a5f045ae2ab6a0635273f21580e5cfde7cf66..370a9c0e988c6c886454314b76173613d898bf25 100644
--- a/packages/component-fixture-manager/src/fixtures/teams.js
+++ b/packages/component-fixture-manager/src/fixtures/teams.js
@@ -35,6 +35,7 @@ const teams = {
     },
     members: [handlingEditor.id],
     save: jest.fn(() => teams.heTeam),
+    delete: jest.fn(),
     updateProperties: jest.fn(() => teams.heTeam),
     id: heTeamID,
   },
@@ -51,6 +52,7 @@ const teams = {
     },
     members: [reviewer.id, inactiveReviewer.id, answerReviewer.id],
     save: jest.fn(() => teams.revTeam),
+    delete: jest.fn(),
     updateProperties: jest.fn(() => teams.revTeam),
     id: revTeamID,
   },
@@ -67,6 +69,7 @@ const teams = {
     },
     members: [reviewer.id, answerReviewer.id, recReviewer.id],
     save: jest.fn(() => teams.revRecommendationTeam),
+    delete: jest.fn(),
     updateProperties: jest.fn(() => teams.revRecommendationTeam),
     id: revRecommendationTeamID,
   },
@@ -99,6 +102,7 @@ const teams = {
     },
     members: [submittingAuthor.id],
     save: jest.fn(() => teams.authorTeam),
+    delete: jest.fn(),
     updateProperties: jest.fn(() => teams.authorTeam),
     id: authorTeamID,
   },
diff --git a/packages/component-helper-service/src/services/User.js b/packages/component-helper-service/src/services/User.js
index 18239d17471a296a3497b3ee2747dc370fcda20e..dbd0eb1f2bf7b6e5995a27df258efbb6a532fb3d 100644
--- a/packages/component-helper-service/src/services/User.js
+++ b/packages/component-helper-service/src/services/User.js
@@ -9,7 +9,14 @@ class User {
 
   async createUser({ role, body }) {
     const { UserModel } = this
-    const { email, firstName, lastName, affiliation, title, country } = body
+    const {
+      email,
+      firstName,
+      lastName,
+      affiliation,
+      title = 'Dr',
+      country,
+    } = body
     const username = email
     const password = uuid.v4()
     const userBody = {
@@ -33,7 +40,7 @@ class User {
         },
       },
       accessTokens: {
-        invitation: role === 'reviewer' ? services.generateHash() : undefined,
+        invitation: role === 'reviewer' ? services.generateHash() : null,
         unsubscribe: services.generateHash(),
         passwordReset: services.generateHash(),
       },
diff --git a/packages/component-invite/src/routes/fragmentsInvitations/post.js b/packages/component-invite/src/routes/fragmentsInvitations/post.js
index 2eab3d2d1642e1aed6f2a9384bbf11b9058fd993..43504b33418afb1807932ac303c275d65a291f84 100644
--- a/packages/component-invite/src/routes/fragmentsInvitations/post.js
+++ b/packages/component-invite/src/routes/fragmentsInvitations/post.js
@@ -1,5 +1,3 @@
-const logger = require('@pubsweet/logger')
-
 const {
   Team,
   User,
@@ -11,12 +9,22 @@ const {
 
 const emailInvitations = require('./emails/invitations')
 
-module.exports = models => async (req, res) => {
-  const { email, role } = req.body
+const { last } = require('lodash')
 
-  if (!services.checkForUndefinedParams(email, role)) {
-    res.status(400).json({ error: 'Email and role are required.' })
-    logger.error('User ID and role are missing')
+module.exports = models => async (req, res) => {
+  const { email, role, firstName, lastName, affiliation, country } = req.body
+
+  if (
+    !services.checkForUndefinedParams(
+      email,
+      role,
+      firstName,
+      lastName,
+      affiliation,
+      country,
+    )
+  ) {
+    res.status(400).json({ error: 'Missing parameters.' })
     return
   }
 
@@ -40,6 +48,10 @@ module.exports = models => async (req, res) => {
       return res.status(400).json({
         error: `Fragment ${fragmentId} does not match collection ${collectionId}.`,
       })
+    if (last(collection.fragments) !== fragmentId)
+      return res.status(400).json({
+        error: `Fragment ${fragmentId} is an older version.`,
+      })
     fragment = await models.Fragment.find(fragmentId)
   } catch (e) {
     const notFoundError = await services.handleNotFoundError(e, 'item')
@@ -124,7 +136,7 @@ module.exports = models => async (req, res) => {
     const userHelper = new User({ UserModel })
 
     const userData = req.body
-    const { firstName = '', lastName = '', isPublons } = userData
+    const { firstName, lastName, isPublons } = userData
     if (!services.checkForUndefinedParams(firstName, lastName)) {
       return res
         .status(400)
diff --git a/packages/component-invite/src/tests/fragmentsInvitations/post.test.js b/packages/component-invite/src/tests/fragmentsInvitations/post.test.js
index ce8719050cf2d722720964548e817c814bf2db55..0683f0aaf927ed7e6b810bd1103aaa75b4267955 100644
--- a/packages/component-invite/src/tests/fragmentsInvitations/post.test.js
+++ b/packages/component-invite/src/tests/fragmentsInvitations/post.test.js
@@ -21,6 +21,7 @@ const reqBody = {
   title: 'Mr',
   affiliation: chance.company(),
   admin: false,
+  country: chance.country(),
 }
 const route = {
   path: '/api/collections/:collectionId/fragments/:fragmentId/invitations',
@@ -49,17 +50,18 @@ describe('Post fragments invitations route handler', () => {
 
     expect(res.statusCode).toBe(400)
     const data = JSON.parse(res._getData())
-    expect(data.error).toEqual('Email and role are required.')
+    expect(data.error).toEqual('Missing parameters.')
   })
   it('should return success when a reviewer is invited', async () => {
     const { user, editorInChief } = testFixtures.users
     const { collection } = testFixtures.collections
     const { fragment } = testFixtures.fragments
 
-    body = {
+    body = Object.assign(body, {
       email: user.email,
       role: 'reviewer',
-    }
+    })
+
     const res = await requests.sendRequest({
       body,
       userId: editorInChief.id,
@@ -109,10 +111,12 @@ describe('Post fragments invitations route handler', () => {
     const { answerReviewer, handlingEditor } = testFixtures.users
     const { collection } = testFixtures.collections
     const { fragment } = testFixtures.fragments
-    body = {
+
+    body = Object.assign(body, {
       email: answerReviewer.email,
       role: 'reviewer',
-    }
+    })
+
     const res = await requests.sendRequest({
       body,
       userId: handlingEditor.id,
@@ -155,10 +159,12 @@ describe('Post fragments invitations route handler', () => {
     const { inactiveUser, handlingEditor } = testFixtures.users
     const { collection } = testFixtures.collections
     const { fragment } = testFixtures.fragments
-    body = {
+
+    body = Object.assign(body, {
       email: inactiveUser.email,
       role: 'reviewer',
-    }
+    })
+
     const res = await requests.sendRequest({
       body,
       userId: handlingEditor.id,
diff --git a/packages/component-manuscript-manager/src/routes/collections/delete.js b/packages/component-manuscript-manager/src/routes/collections/delete.js
index 05b9e042f9c08c24f9367aea7f6db546e08e8b08..62ed1fc8c760f3f1c2aa0385e3a0db337dcb8be5 100644
--- a/packages/component-manuscript-manager/src/routes/collections/delete.js
+++ b/packages/component-manuscript-manager/src/routes/collections/delete.js
@@ -1,4 +1,4 @@
-const { get, remove, concat } = require('lodash')
+const { get, remove, concat, has } = require('lodash')
 const config = require('config')
 
 const {
@@ -19,6 +19,12 @@ module.exports = models => async (req, res) => {
   try {
     collection = await models.Collection.find(collectionId)
 
+    if (has(collection, 'status')) {
+      return res.status(400).json({
+        error: 'You can only delete manuscripts while in draft.',
+      })
+    }
+
     const fragmentId = collection.fragments[0]
     fragment = await models.Fragment.find(fragmentId)
 
@@ -48,17 +54,18 @@ module.exports = models => async (req, res) => {
             return user.save()
           }),
         )
-
         return team.delete()
       }),
     )
 
-    const fileKeys = concat(
+    let fileKeys = concat(
       fragment.files.manuscripts,
       fragment.files.coverLetter,
       fragment.files.supplementary,
       fragmentId,
-    ).map(file => file.id)
+    )
+
+    fileKeys = fileKeys.map(file => file.id)
 
     if (fileKeys.length > 1) {
       await deleteFilesS3({ fileKeys, s3Config })
diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js
index 55d54aa4274c9035da2fe92342ccab04929b6220..43206e0e19c9bb85290713f5eb829d04dd700df6 100644
--- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js
+++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js
@@ -1,5 +1,5 @@
 const uuid = require('uuid')
-const { pick, get, set, has, isEmpty } = require('lodash')
+const { pick, get, set, has, isEmpty, last } = require('lodash')
 const config = require('config')
 const { v4 } = require('uuid')
 
@@ -69,6 +69,15 @@ module.exports = models => async (req, res) => {
       error: 'Unauthorized.',
     })
 
+  if (
+    recommendationType === recommendations.type.editor &&
+    last(collection.fragments) !== fragmentId
+  ) {
+    return res
+      .status(400)
+      .json({ error: 'Cannot make a recommendation on an older version.' })
+  }
+
   if (
     recommendation === recommendations.publish &&
     recommendationType === recommendations.type.editor &&
diff --git a/packages/component-manuscript-manager/src/tests/collections/delete.test.js b/packages/component-manuscript-manager/src/tests/collections/delete.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..cee28293a8b2143164d5697c09d49d50762200f5
--- /dev/null
+++ b/packages/component-manuscript-manager/src/tests/collections/delete.test.js
@@ -0,0 +1,65 @@
+process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
+process.env.SUPPRESS_NO_CONFIG_WARNING = true
+
+const { cloneDeep } = require('lodash')
+const fixturesService = require('pubsweet-component-fixture-service')
+const requests = require('../requests')
+
+const { Model, fixtures } = fixturesService
+
+jest.mock('pubsweet-component-mts-package/src/PackageManager', () => ({
+  deleteFilesS3: jest.fn(),
+}))
+jest.mock('@pubsweet/component-send-email', () => ({
+  send: jest.fn(),
+}))
+
+const path = '../routes/collections/delete'
+const route = {
+  path: '/api/collections/:collectionId/',
+}
+describe('Delete collections route handler', () => {
+  let testFixtures = {}
+  let models
+  beforeEach(() => {
+    testFixtures = cloneDeep(fixtures)
+    models = Model.build(testFixtures)
+  })
+
+  it('should return an error when deleting a collection which is not in draft', async () => {
+    const { admin } = testFixtures.users
+    const { collection } = testFixtures.collections
+
+    const res = await requests.sendRequest({
+      userId: admin.id,
+      route,
+      models,
+      path,
+      params: {
+        collectionId: collection.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(400)
+    const data = JSON.parse(res._getData())
+    expect(data.error).toBe('You can only delete manuscripts while in draft.')
+  })
+
+  it('should return success when deleting a draft collection', async () => {
+    const { admin } = testFixtures.users
+    const { collection } = testFixtures.collections
+    delete collection.status
+
+    const res = await requests.sendRequest({
+      userId: admin.id,
+      route,
+      models,
+      path,
+      params: {
+        collectionId: collection.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(204)
+  })
+})
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 b090a9cb6fc1ae464488560f7032b0ff97388dea..867d1ed0d05986fd03e389da064d08e4a19dfc77 100644
--- a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js
+++ b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js
@@ -357,4 +357,58 @@ describe('Post fragments recommendations route handler', () => {
       'Cannot publish without at least one reviewer report.',
     )
   })
+
+  it('should return an error when a HE makes a recommendation on an older version of a manuscript', async () => {
+    const { handlingEditor } = testFixtures.users
+    const { twoVersionsCollection } = testFixtures.collections
+    const { fragment } = testFixtures.fragments
+    body.recommendation = 'publish'
+    body.recommendationType = 'editorRecommendation'
+
+    const res = await requests.sendRequest({
+      body,
+      userId: handlingEditor.id,
+      models,
+      route,
+      path,
+      params: {
+        collectionId: twoVersionsCollection.id,
+        fragmentId: fragment.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(400)
+    const data = JSON.parse(res._getData())
+
+    expect(data.error).toEqual(
+      'Cannot make a recommendation on an older version.',
+    )
+  })
+
+  it('should return an error when an EiC makes a decision on an older version of a manuscript', async () => {
+    const { editorInChief } = testFixtures.users
+    const { twoVersionsCollection } = testFixtures.collections
+    const { fragment } = testFixtures.fragments
+    body.recommendation = 'publish'
+    body.recommendationType = 'editorRecommendation'
+
+    const res = await requests.sendRequest({
+      body,
+      userId: editorInChief.id,
+      models,
+      route,
+      path,
+      params: {
+        collectionId: twoVersionsCollection.id,
+        fragmentId: fragment.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(400)
+    const data = JSON.parse(res._getData())
+
+    expect(data.error).toEqual(
+      'Cannot make a recommendation on an older version.',
+    )
+  })
 })
diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js
index 9c39e9a6c7c722d76d281c73ebc0adb3ac8e777a..fd01d44a1b4009c558fb8900d8991e9bc47f7b04 100644
--- a/packages/component-manuscript/src/components/ManuscriptLayout.js
+++ b/packages/component-manuscript/src/components/ManuscriptLayout.js
@@ -50,6 +50,7 @@ const ManuscriptLayout = ({
   heResponseExpanded,
   toggleReviewerResponse,
   invitationsWithReviewers,
+  responseToRevisionRequest,
   publonReviewers,
   reviewerResponseExpanded,
   pendingOwnRecommendation,
@@ -64,6 +65,7 @@ const ManuscriptLayout = ({
   reviewerRecommendations,
   toggleReviewerDetails,
   reviewerDetailsExpanded,
+  toggleResponseToRevisionRequest,
   editorialCommentsExpanded,
   toggleEditorialComments,
   submitRevision,
@@ -72,6 +74,7 @@ const ManuscriptLayout = ({
   inviteHandlingEditor,
 
   versions,
+  isLatestVersion,
 }) => (
   <Root pb={30}>
     {!isEmpty(collection) && !isEmpty(fragment) ? (
@@ -92,6 +95,7 @@ const ManuscriptLayout = ({
           handlingEditors={handlingEditors}
           inviteHE={toggleAssignHE}
           isFetching={isFetchingData.editorsFetching}
+          isLatestVersion={isLatestVersion}
           journal={journal}
           resendInvitation={inviteHandlingEditor.assignHE}
           revokeInvitation={inviteHandlingEditor.revokeHE}
@@ -117,8 +121,10 @@ const ManuscriptLayout = ({
         {get(currentUser, 'permissions.authorCanViewReportsDetails', false) && (
           <AuthorReviews
             currentUser={currentUser}
+            getSignedUrl={getSignedUrl}
             journal={journal}
             reports={reviewerReports}
+            token={get(currentUser, 'token')}
           />
         )}
 
@@ -131,16 +137,16 @@ const ManuscriptLayout = ({
           />
         )}
 
-        {authorResponseToRevisonRequest.content && (
+        {get(authorResponseToRevisonRequest, 'content', false) && (
           <ResponseToRevisionRequest
-            authorReply={authorResponseToRevisonRequest.content}
-            expanded={responseToRevisionRequestExpanded}
+            authorReply={get(authorResponseToRevisonRequest, 'content', '')}
+            expanded={responseToRevisionRequest}
             fragment={fragment}
-            toggle={toggleResponeToRevisionRequest}
+            toggle={toggleResponseToRevisionRequest}
           />
         )}
 
-        {shouldReview && (
+        {get(currentUser, 'permissions.canReview', false) && (
           <ReviewerReportForm
             changeForm={changeForm}
             expanded={reviewerRecommendationExpanded}
@@ -200,23 +206,26 @@ const ManuscriptLayout = ({
             }
             invitations={invitationsWithReviewers}
             isFetching={isFetchingData.publonsFetching}
+            isLatestVersion={isLatestVersion}
             journal={journal}
             mb={2}
             publonReviewers={publonReviewers}
             reviewerReports={reviewerReports}
             scrollIntoView
             toggle={toggleReviewerDetails}
+            token={get(currentUser, 'token')}
             {...inviteReviewer}
           />
         )}
 
-        {get(currentUser, 'permissions.canSubmitRevision', false) && (
-          <SubmitRevision {...submitRevision} />
-        )}
+        {isLatestVersion &&
+          get(currentUser, 'permissions.canSubmitRevision', false) && (
+            <SubmitRevision {...submitRevision} />
+          )}
 
-        {get(currentUser, 'permissions.canMakeHERecommendation', false) &&
-          (!invitationsWithReviewers.length ||
-            reviewerRecommendations.length > 0) && (
+        {isLatestVersion &&
+          get(currentUser, 'permissions.canMakeHERecommendation', false) &&
+          reviewerRecommendations.length > 0 && (
             <HERecommendation
               formValues={get(formValues, 'editorialRecommendation', {})}
               hasReviewerReports={reviewerRecommendations.length > 0}
@@ -228,16 +237,17 @@ const ManuscriptLayout = ({
             />
           )}
 
-        {get(currentUser, 'permissions.canMakeDecision', false) && (
-          <ManuscriptEicDecision
-            collection={collection}
-            formValues={get(formValues, 'eicDecision')}
-            highlight={editorialRecommendations.length > 0}
-            messagesLabel={messagesLabel}
-            mt={2}
-            submitDecision={recommendationHandler.createRecommendation}
-          />
-        )}
+        {isLatestVersion &&
+          get(currentUser, 'permissions.canMakeDecision', false) && (
+            <ManuscriptEicDecision
+              collection={collection}
+              formValues={get(formValues, 'eicDecision')}
+              highlight={editorialRecommendations.length > 0}
+              messagesLabel={messagesLabel}
+              mt={2}
+              submitDecision={recommendationHandler.createRecommendation}
+            />
+          )}
       </Fragment>
     ) : (
       <Text>Loading...</Text>
diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js
index f51c7f7ab0af1a3571d4cec79743232981fce08f..84d6059a9c3187ed2c5c5c648a1f4fe33af233a4 100644
--- a/packages/component-manuscript/src/components/ManuscriptPage.js
+++ b/packages/component-manuscript/src/components/ManuscriptPage.js
@@ -31,6 +31,7 @@ import {
   selectEditorialRecommendations,
 } from 'pubsweet-components-faraday/src/redux/recommendations'
 import {
+  canReview,
   getUserToken,
   currentUserIs,
   canViewReports,
@@ -73,6 +74,7 @@ import {
   redirectToError,
   parseSearchParams,
   getPublonsReviewers,
+  isLatestVersion,
 } from './utils'
 
 import {
@@ -93,6 +95,7 @@ export default compose(
     actions.getCollection({ id: match.params.project }),
     actions.getFragments({ id: match.params.project }),
     actions.getUsers(),
+    actions.getTeams(),
   ]),
   connect(
     (state, { match }) => ({
@@ -165,6 +168,7 @@ export default compose(
         isReviewer: currentUserIsReviewer(state, get(fragment, 'id', '')),
         isHEToManuscript: isHEToManuscript(state, get(collection, 'id', '')),
         permissions: {
+          canReview: canReview(state, collection, fragment),
           canSubmitRevision: canSubmitRevision(state, fragment),
           canMakeHERecommendation: canMakeHERecommendation(state, {
             collection,
@@ -180,7 +184,7 @@ export default compose(
           canInviteReviewers: canInviteReviewers(state, collection),
           canMakeRecommendation: !isUndefined(pendingOwnRecommendation),
           canMakeRevision: canMakeRevision(state, collection, fragment),
-          canMakeDecision: canMakeDecision(state, collection, fragment),
+          canMakeDecision: canMakeDecision(state, collection),
           canEditManuscript: canEditManuscript(state, collection, fragment),
           canViewReviewersDetails: canViewReviewersDetails(state, collection),
           authorCanViewReportsDetails: authorCanViewReportsDetails(
@@ -278,6 +282,10 @@ export default compose(
     toggleReviewerRecommendations: toggle,
     reviewerRecommendationExpanded: expanded,
   })),
+  fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
+    toggleResponseToRevisionRequest: toggle,
+    responseToRevisionRequest: expanded,
+  })),
   fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
     toggleReviewerDetails: toggle,
     reviewerDetailsExpanded: expanded,
@@ -286,15 +294,9 @@ export default compose(
     toggleEditorialComments: toggle,
     editorialCommentsExpanded: expanded,
   })),
-  fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
-    toggleResponeToRevisionRequest: toggle,
-    responseToRevisionRequestExpanded: expanded,
-  })),
-  withProps(({ currentUser, collection, submittedOwnRecommendation }) => ({
+  withProps(({ collection, fragment }) => ({
     getSignedUrl,
-    shouldReview:
-      get(currentUser, 'isReviewer', false) &&
-      isUndefined(submittedOwnRecommendation),
+    isLatestVersion: isLatestVersion(collection, fragment),
   })),
   withInviteHandlingEditor,
   withInviteReviewer,
@@ -307,7 +309,6 @@ export default compose(
         history,
         setError,
         location,
-        shouldReview,
         reviewerReports,
         setEditorInChief,
         clearCustomError,
@@ -315,13 +316,13 @@ export default compose(
         hasManuscriptFailure,
         fetchUpdatedCollection,
         editorialRecommendations,
-        authorResponseToRevisonRequest,
+        fragment,
         currentUser: {
           isEIC,
           isInvitedHE,
           isInvitedToReview,
           isHEToManuscript,
-          permissions: { canInviteReviewers, canSubmitRevision },
+          permissions: { canInviteReviewers, canSubmitRevision, canReview },
         },
       } = this.props
 
@@ -356,14 +357,14 @@ export default compose(
         this.props.toggleReviewerResponse()
       }
 
-      if (shouldReview && !authorResponseToRevisonRequest.content) {
+      if (canReview && !get(fragment, 'responseToReviewers.content', false)) {
         this.props.toggleReviewerRecommendations()
       }
-
       if (
         isHEToManuscript &&
         !!reviewerReports.length &&
-        editorialRecommendations.length === 0
+        editorialRecommendations.length === 0 &&
+        get(fragment, 'responseToReviewers.content', false)
       ) {
         this.props.toggleReviewerDetails()
       }
@@ -376,8 +377,8 @@ export default compose(
         this.props.toggleEditorialComments()
       }
 
-      if (authorResponseToRevisonRequest.content) {
-        this.props.toggleResponeToRevisionRequest()
+      if (get(fragment, 'responseToReviewers.content', false)) {
+        this.props.toggleResponseToRevisionRequest()
       }
     },
     componentDidUpdate(prevProps) {
diff --git a/packages/component-manuscript/src/components/utils.js b/packages/component-manuscript/src/components/utils.js
index e579d683636db3dfcb7917c961dd8d9f5a02eff8..f98db2189670e9dbb869bdc583cd6636ff3097e3 100644
--- a/packages/component-manuscript/src/components/utils.js
+++ b/packages/component-manuscript/src/components/utils.js
@@ -3,6 +3,7 @@ import {
   has,
   get,
   find,
+  last,
   omit,
   isEmpty,
   debounce,
@@ -74,6 +75,9 @@ export const parseVersion = version => ({
   abstract: get(version, 'metadata.abstract'),
 })
 
+export const isLatestVersion = (collection, fragment) =>
+  get(fragment, 'id', '') === last(get(collection, 'fragments', []))
+
 export const parseJournalIssue = (journal, metadata) =>
   journal.issueTypes.find(t => t.value === get(metadata, 'issue'))
 
diff --git a/packages/component-manuscript/src/submitRevision/withSubmitRevision.js b/packages/component-manuscript/src/submitRevision/withSubmitRevision.js
index 756551f82f57ab162c74915c3e47fca32701c4c5..57b8a4297065dd2efe876241e83e886a2b0eebbe 100644
--- a/packages/component-manuscript/src/submitRevision/withSubmitRevision.js
+++ b/packages/component-manuscript/src/submitRevision/withSubmitRevision.js
@@ -97,7 +97,7 @@ export default compose(
     },
     deleteResponseFile: ({ setError, changeForm, setFetching }) => file => {
       setFetching(true)
-      return deleteFile(file.id, 'responseToReviewers')
+      return deleteFile({ fileId: file.id }, 'responseToReviewers')
         .then(r => {
           setFetching(false)
           changeForm('revision', 'responseToReviewers.file', null)
diff --git a/packages/components-faraday/src/components/Dashboard/DashboardPage.js b/packages/components-faraday/src/components/Dashboard/DashboardPage.js
index 2aadccce522ce995b4387b64b0f1b891433befe9..7f96042f9cf5d84f6625ef6a1c912aa8cbf2d51b 100644
--- a/packages/components-faraday/src/components/Dashboard/DashboardPage.js
+++ b/packages/components-faraday/src/components/Dashboard/DashboardPage.js
@@ -17,7 +17,11 @@ import { Dashboard } from './'
 import { priorityFilter, orderFilter, withFiltersHOC } from '../Filters'
 
 export default compose(
-  ConnectPage(() => [actions.getCollections(), actions.getUsers()]),
+  ConnectPage(() => [
+    actions.getCollections(),
+    actions.getUsers(),
+    actions.getTeams(),
+  ]),
   connect(
     state => {
       const { collections, conversion } = state
@@ -34,6 +38,7 @@ export default compose(
       }
     },
     {
+      getCollections: actions.getCollections,
       deleteCollection: actions.deleteCollection,
     },
   ),
@@ -52,15 +57,17 @@ export default compose(
     ({ journal, currentUser }) => ({ journal, currentUser }),
   ),
   withHandlers({
-    deleteCollection: ({ setFetching, deleteCollection }) => collection => ({
-      hideModal,
-      setModalError,
-    }) => {
+    deleteCollection: ({
+      setFetching,
+      deleteCollection,
+      getCollections,
+    }) => collection => ({ hideModal, setModalError }) => {
       setFetching(true)
       deleteCollection(collection)
         .then(() => {
           setFetching(false)
           hideModal()
+          getCollections()
         })
         // again, the error is not being thrown from deleteCollection action and
         // the catch is never run
diff --git a/packages/xpub-faraday/app.js b/packages/xpub-faraday/app.js
index 5eefe950911e489d094e41831dbda8fd695e2881..0675af2b27052928c4924d673750f6548a9308f2 100644
--- a/packages/xpub-faraday/app.js
+++ b/packages/xpub-faraday/app.js
@@ -1,5 +1,5 @@
 const logger = require('@pubsweet/logger')
-const startServer = require('pubsweet-server')
+const { startServer } = require('pubsweet-server')
 require('dotenv').config()
 
 startServer().catch(err => {
diff --git a/packages/xpub-faraday/config/authsome-helpers.js b/packages/xpub-faraday/config/authsome-helpers.js
index de88ed38e85a7a4c68bd4c70e2c0fb0be4698d83..c43c00d912084c864261fd45e5c75fc05bd83a64 100644
--- a/packages/xpub-faraday/config/authsome-helpers.js
+++ b/packages/xpub-faraday/config/authsome-helpers.js
@@ -1,65 +1,11 @@
-const { omit, get, last, chain } = require('lodash')
 const config = require('config')
 const logger = require('@pubsweet/logger')
+const { omit, get, last, chain } = require('lodash')
 
 const statuses = config.get('statuses')
 
-const publicStatusesPermissions = ['author', 'reviewer']
 const authorAllowedStatuses = ['revisionRequested', 'rejected', 'accepted']
 
-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[status].public
-  }
-}
-
-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,
-        )
-    }
-    parseAuthorsData(object, matchingCollPerm)
-    if (['reviewer', 'handlingEditor'].includes(matchingCollPerm.permission)) {
-      return filterRefusedInvitations(object, user)
-    }
-    return object
-  }
-  const matchingCollPerm = collectionsPermissions.find(
-    collPerm => object.id === collPerm.id,
-  )
-  if (matchingCollPerm === undefined) return null
-  setPublicStatuses(object, matchingCollPerm)
-
-  return object
-}
-
 const getTeamsByPermissions = async (
   teamIds = [],
   permissions = [],
@@ -75,12 +21,6 @@ const getTeamsByPermissions = async (
     }),
   )).filter(Boolean)
 
-const heIsInvitedToFragment = async ({ user, Team, collectionId }) =>
-  (await getTeamsByPermissions(user.teams, ['handlingEditor'], Team)).some(
-    // user is a member of the team with access to the fragment's parent collection
-    t => t.members.includes(user.id) && t.object.id === collectionId,
-  )
-
 const getUserPermissions = async ({
   user,
   Team,
@@ -119,12 +59,6 @@ const isHandlingEditor = ({ user, object }) =>
 
 const isInDraft = fragment => !get(fragment, 'submitted')
 
-const hasFragmentInDraft = async ({ object, Fragment }) => {
-  const lastFragmentId = last(get(object, 'fragments'))
-  const fragment = await Fragment.find(lastFragmentId)
-  return isInDraft(fragment)
-}
-
 const filterAuthorRecommendations = (recommendations, status, isLast) => {
   const canViewRecommendations = authorAllowedStatuses.includes(status)
   if (canViewRecommendations || !isLast) {
@@ -236,20 +170,15 @@ const getCollections = async ({ user, models }) => {
       collection.visibleStatus = get(statuses, `${status}.${up.role}.label`)
 
       const role = get(up, 'role', 'author')
-
-      let visibleStatus = get(statuses, `${status}.${role}.label`)
-
-      if (role === 'reviewer' && status !== 'reviewersInvited') {
-        visibleStatus = await updateReviewerVisibleStatusByInvitation({
-          collection,
-          FragmentModel: models.Fragment,
-          user,
-        })
-      }
-
+      const parsedStatuses = await setCollectionStatus({
+        role,
+        user,
+        collection,
+        FragmentModel: models.Fragment,
+      })
       return {
         ...collection,
-        visibleStatus,
+        ...parsedStatuses,
       }
     }),
   )).filter(Boolean)
@@ -260,55 +189,91 @@ const getCollections = async ({ user, models }) => {
     .value()
 }
 
-async function updateReviewerVisibleStatusByInvitation({
+const reviewerActionStatuses = [
+  'underReview',
+  'reviewCompleted',
+  'reviewersInvited',
+]
+const setCollectionStatus = async ({
+  role,
+  user,
   collection,
   FragmentModel,
-  user,
-}) {
-  const fragmentId = last(collection.fragments)
-  const fragment = await FragmentModel.find(fragmentId)
-  const invitation = get(fragment, 'invitations', []).find(
-    inv => inv.userId === user.id,
-  )
-  const recommendationDone =
-    fragment.recommendations &&
-    fragment.recommendations.some(
-      rec =>
-        rec.recommendationType === 'review' &&
-        rec.userId === user.id &&
-        rec.submittedOn,
-    )
+}) => {
+  const status = get(collection, 'status', 'draft')
 
-  if (recommendationDone) {
-    return get(statuses, `${collection.status}.reviewer.label`)
+  if (role !== 'reviewer') {
+    return {
+      status,
+      visibleStatus: get(statuses, `${status}.${role}.label`),
+    }
   }
 
-  if (!invitation) {
-    return get(statuses, `reviewCompleted.reviewer.label`)
+  if (reviewerActionStatuses.includes(status)) {
+    const fragmentId = last(collection.fragments)
+    const fragment = await FragmentModel.find(fragmentId)
+
+    const hasPendingInvitation = !chain(fragment)
+      .get('invitations', [])
+      .find(i => i.userId === user.id && !i.hasAnswer)
+      .isUndefined()
+      .value()
+
+    if (hasPendingInvitation) {
+      return {
+        status: 'reviewersInvited',
+        visibleStatus: get(statuses, 'reviewersInvited.reviewer.label'),
+      }
+    }
+
+    const hasSubmittedReport = !chain(fragment)
+      .get('recommendations', [])
+      .find(
+        r =>
+          r.userId === user.id &&
+          r.recommendationType === 'review' &&
+          r.submittedOn,
+      )
+      .isUndefined()
+      .value()
+
+    if (hasSubmittedReport) {
+      return {
+        status: 'reviewCompleted',
+        visibleStatus: get(statuses, 'reviewCompleted.reviewer.label'),
+      }
+    }
+
+    const hasAcceptedInvitation = !chain(fragment)
+      .get('invitations', [])
+      .find(i => i.userId === user.id && i.hasAnswer && i.isAccepted)
+      .isUndefined()
+      .value()
+
+    if (hasAcceptedInvitation) {
+      return {
+        status: 'underReview',
+        visibleStatus: get(statuses, 'underReview.reviewer.label'),
+      }
+    }
   }
 
-  return get(invitation, 'hasAnswer', false) &&
-    get(invitation, 'isAccepted', false)
-    ? get(statuses, `underReview.reviewer.label`)
-    : get(statuses, `reviewersInvited.reviewer.label`)
+  return {
+    status,
+    visibleStatus: get(statuses, `${status}.reviewer.label`),
+  }
 }
 
 module.exports = {
-  filterObjectData,
-  parseAuthorsData,
-  setPublicStatuses,
-  getTeamsByPermissions,
-  filterRefusedInvitations,
   isOwner,
-  isHandlingEditor,
-  getUserPermissions,
-  heIsInvitedToFragment,
-  hasPermissionForObject,
   isInDraft,
-  hasFragmentInDraft,
-  stripeFragmentByRole,
-  getUsersList,
   parseUser,
+  getUsersList,
   getCollections,
-  updateReviewerVisibleStatusByInvitation,
+  isHandlingEditor,
+  getUserPermissions,
+  setCollectionStatus,
+  stripeFragmentByRole,
+  getTeamsByPermissions,
+  hasPermissionForObject,
 }
diff --git a/packages/xpub-faraday/config/authsome-mode.js b/packages/xpub-faraday/config/authsome-mode.js
index 2bb207ebd4264f3d3210d226bb0134e25e0b1bff..e4129023dccead41ff08fec5a1b33d2f24066e42 100644
--- a/packages/xpub-faraday/config/authsome-mode.js
+++ b/packages/xpub-faraday/config/authsome-mode.js
@@ -67,7 +67,6 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) {
     if (get(object, 'type') === 'collection') {
       return {
         filter: async collection => {
-          const status = get(collection, 'status', 'draft')
           const userPermissions = await helpers.getUserPermissions({
             user,
             Team: context.models.Team,
@@ -79,10 +78,6 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) {
             )
             .map(up => up.objectId)
 
-          // if (collection.owners.map(o => o.id).includes(user.id)) {
-          //   return collection
-          // }
-          // TODO: check why collPermission can be undefined
           const collPermission = userPermissions.find(
             p =>
               p.objectId === collection.id ||
@@ -90,27 +85,22 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) {
           )
           const role = get(collPermission, 'role', 'author')
 
-          let visibleStatus = get(statuses, `${status}.${role}.label`)
-
-          if (role === 'reviewer' && status !== 'reviewersInvited') {
-            visibleStatus = await helpers.updateReviewerVisibleStatusByInvitation(
-              {
-                collection,
-                FragmentModel: context.models.Fragment,
-                user,
-              },
-            )
-          }
+          const parsedStatuses = await helpers.setCollectionStatus({
+            role,
+            user,
+            collection,
+            FragmentModel: context.models.Fragment,
+          })
 
           return {
             ...collection,
+            ...parsedStatuses,
             fragments:
               role !== 'reviewer'
                 ? collection.fragments
                 : collection.fragments.filter(fragId =>
                     fragmentPermissions.includes(fragId),
                   ),
-            visibleStatus,
           }
         },
       }
@@ -168,6 +158,12 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) {
         models: context.models,
       })
     }
+
+    if (get(object, 'path', '') === '/teams') {
+      return {
+        filter: teams => teams.filter(t => user.teams.includes(t.id)),
+      }
+    }
   }
 
   if (operation === 'POST') {
@@ -207,12 +203,12 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) {
   }
 
   if (operation === 'PATCH') {
-    if (get(object, 'type') === 'collection') {
-      return helpers.isOwner({ user, object })
+    if (get(object.current, 'type') === 'collection') {
+      return helpers.isOwner({ user, object: object.current })
     }
 
-    if (get(object, 'type') === 'fragment') {
-      return helpers.isOwner({ user, object })
+    if (get(object.current, 'type') === 'fragment') {
+      return helpers.isOwner({ user, object: object.current })
     }
 
     // allow reviewer to patch (accept/decline) his invitation
diff --git a/packages/xpub-faraday/config/default.js b/packages/xpub-faraday/config/default.js
index 7cd9de3dbaab836663730ca2ed9942712d2d237b..4ac021c51ead4f114dd58b376a2619050fc5687d 100644
--- a/packages/xpub-faraday/config/default.js
+++ b/packages/xpub-faraday/config/default.js
@@ -35,6 +35,9 @@ module.exports = {
   pubsweet: {
     components,
   },
+  dbManager: {
+    migrationsPath: path.join(process.cwd(), 'migrations'),
+  },
   'pubsweet-server': {
     db: getDbConfig(),
     port: 3000,
diff --git a/packages/xpub-faraday/config/validations.js b/packages/xpub-faraday/config/validations.js
index 60cd146dec55f085d5535fc0eb934edfcfebc7da..6d1ac18d402b9baa6333ed22f7cfbe5d2f566cdf 100644
--- a/packages/xpub-faraday/config/validations.js
+++ b/packages/xpub-faraday/config/validations.js
@@ -166,10 +166,13 @@ module.exports = {
       confirmation: Joi.string().allow(''),
       passwordReset: Joi.string().allow(''),
       unsubscribe: Joi.string().allow(''),
-      invitation: Joi.string().allow(''),
+      invitation: Joi.string().allow(null),
     }),
   },
   team: {
+    name: Joi.string(),
+    type: Joi.string(),
     group: Joi.string(),
+    teamType: Joi.object(),
   },
 }
diff --git a/packages/xpub-faraday/migrations/.gitkeep b/packages/xpub-faraday/migrations/.gitkeep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/packages/xpub-faraday/package.json b/packages/xpub-faraday/package.json
index 4e30ddde8745944893f2ed9601603be229ba84e8..e426d3005c02ae80b2b97fb5e778d770d3ca164e 100644
--- a/packages/xpub-faraday/package.json
+++ b/packages/xpub-faraday/package.json
@@ -26,11 +26,11 @@
     "moment": "^2.18.1",
     "nodemailer-ses-transport": "^1.5.1",
     "prop-types": "^15.5.10",
-    "pubsweet": "^2.2.1",
+    "pubsweet": "3.0.6",
     "pubsweet-client": "^4.0.4",
     "pubsweet-component-login": "^1.1.0",
     "pubsweet-component-signup": "^1.0.0",
-    "pubsweet-server": "2.0.3",
+    "pubsweet-server": "10.0.1",
     "react": "^16.4.2",
     "react-dnd": "^2.5.4",
     "react-dnd-html5-backend": "^2.5.4",
@@ -81,8 +81,7 @@
     "start": "pubsweet start",
     "start:services": "docker-compose up postgres",
     "server": "pubsweet server",
-    "start-now":
-      "echo $secret > config/local-development.json && npm run server",
+    "start-now": "echo $secret > config/local-development.json && npm run server",
     "build": "NODE_ENV=production pubsweet build",
     "clean": "rm -rf node_modules",
     "debug": "pgrep -f startup/start.js | xargs kill -sigusr1",
diff --git a/packages/xpub-faraday/tests/config/authsome-helpers.test.js b/packages/xpub-faraday/tests/config/authsome-helpers.test.js
index 0e51ce6aed419d58cda2bf016f2bbc09d821e8b5..a15e1f9852337441114611dcc2a0e426bf904c5c 100644
--- a/packages/xpub-faraday/tests/config/authsome-helpers.test.js
+++ b/packages/xpub-faraday/tests/config/authsome-helpers.test.js
@@ -195,42 +195,4 @@ describe('Authsome Helpers', () => {
     expect(parsedUser).toHaveProperty('email')
     expect(parsedUser).toHaveProperty('username')
   })
-  describe('updateReviewerVisibleStatusByInvitation', () => {
-    it('should return the fragment status for reviewer when they have done the review', async () => {
-      const { answerReviewer } = testFixtures.users
-      const { collectionReviewCompleted } = testFixtures.collections
-
-      const visibleStatus = await ah.updateReviewerVisibleStatusByInvitation({
-        collection: collectionReviewCompleted,
-        FragmentModel: models.Fragment,
-        user: answerReviewer,
-      })
-
-      expect(visibleStatus).toEqual('Review Completed')
-    })
-    it('should return the underReview status for reviewer when they have accepted the review', async () => {
-      const { reviewer } = testFixtures.users
-      const { collectionReviewCompleted } = testFixtures.collections
-
-      const visibleStatus = await ah.updateReviewerVisibleStatusByInvitation({
-        collection: collectionReviewCompleted,
-        FragmentModel: models.Fragment,
-        user: reviewer,
-      })
-
-      expect(visibleStatus).toEqual('Complete Review')
-    })
-    it('should return the reviewersInvited status for reviewer when they have to accept the review', async () => {
-      const { recReviewer } = testFixtures.users
-      const { collectionReviewCompleted } = testFixtures.collections
-
-      const visibleStatus = await ah.updateReviewerVisibleStatusByInvitation({
-        collection: collectionReviewCompleted,
-        FragmentModel: models.Fragment,
-        user: recReviewer,
-      })
-
-      expect(visibleStatus).toEqual('Respond to Invite')
-    })
-  })
 })
diff --git a/yarn.lock b/yarn.lock
index f6c36cafc8383e67e1a308f0309d904df6e8e006..708053b3d33e89331cac4388464f0a2cc6bfd570 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -139,17 +139,19 @@
     aws-sdk "^2.185.0"
     nodemailer "^4.4.2"
 
-"@pubsweet/db-manager@^1.0.10":
-  version "1.0.10"
-  resolved "https://registry.yarnpkg.com/@pubsweet/db-manager/-/db-manager-1.0.10.tgz#88d9f935cb04943ea150ef3820810f792bb6308e"
-  integrity sha512-YCwBxnR4D6aZAsgWJUnP95X8ZmaKRqf375j12234Ui6iVqn2ZpS2fr3+qT/WSDTzFkVgs69waZ3Frdth63MJHg==
+"@pubsweet/db-manager@^2.0.6":
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/@pubsweet/db-manager/-/db-manager-2.0.6.tgz#75e5dbc3946c3211ff2146ef914884c3711bb92b"
+  integrity sha512-rheDnoOSVyuzlV63AfesAY/IDYHEkEMWxq1RUugtz22QzBLTeMaBQK7Sdp7xhuU7NK4t0kvoWuSo4QRvNgeUyQ==
   dependencies:
-    "@pubsweet/logger" "^0.2.2"
+    "@pubsweet/logger" "^0.2.7"
     fs-extra "^4.0.2"
     isomorphic-fetch "^2.2.1"
-    joi "^13.1.0"
+    joi "^13.6.0"
     pg "^7.4.1"
-    pubsweet-server "^6.1.0"
+    pubsweet-server "^10.0.1"
+    tmp "^0.0.33"
+    umzug "^2.1.0"
 
 "@pubsweet/default-theme@^3.0.0":
   version "3.0.0"
@@ -161,13 +163,13 @@
     typeface-noto-serif "^0.0.54"
     typeface-ubuntu-mono "^0.0.54"
 
-"@pubsweet/logger@^0.2.2":
-  version "0.2.2"
-  resolved "https://registry.yarnpkg.com/@pubsweet/logger/-/logger-0.2.2.tgz#ef5680c766226d4b25c5915859ea259b8c688db3"
-  integrity sha512-BmGOXiGu8PRPdRMSCTNd6dKAPDBPL7hjlWHcsI16Y7lzlJLCUUfUPSuq1FGq4ZoinekM/oUeUDpbhIr7FFY9EQ==
+"@pubsweet/logger@^0.2.7":
+  version "0.2.7"
+  resolved "https://registry.yarnpkg.com/@pubsweet/logger/-/logger-0.2.7.tgz#73e4b2a56c7d1145287da6081a0b6ede8abb4269"
+  integrity sha512-GSzvWWxkku12+HDJIFAfWSLM6/T342fX+ZAtUkTuXHu2cR3VVcJcgig2IxFfLXadFATDzSZAKJHanBOYjZYx4Q==
   dependencies:
-    config "^1.26.2"
-    joi "^13.1.0"
+    config "^2.0.1"
+    joi "^13.6.0"
     lodash "^4.17.4"
 
 "@pubsweet/styleguide@3.1.4":
@@ -275,11 +277,6 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.6.tgz#d8176d864ee48753d053783e4e463aec86b8d82e"
   integrity sha512-CTUtLb6WqCCgp6P59QintjHWqzf4VL1uPA27bipLAPxFqrtK1gEYllePzTICGqQ8rYsCbpnsNypXjjDzGAAjEQ==
 
-"@types/zen-observable@0.5.3":
-  version "0.5.3"
-  resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.5.3.tgz#91b728599544efbb7386d8b6633693a3c2e7ade5"
-  integrity sha512-aDvGDAHcVfUqNmd8q4//cHAP+HGxsbChbBbuk3+kMVk5TTxfWLpQWvVN3+UPjohLnwMYN7jr6BWNn2cYNqdm7g==
-
 "@types/zen-observable@^0.8.0":
   version "0.8.0"
   resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d"
@@ -433,6 +430,16 @@ ajv@^6.1.0:
     fast-json-stable-stringify "^2.0.0"
     json-schema-traverse "^0.3.0"
 
+ajv@^6.1.1:
+  version "6.5.4"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59"
+  integrity sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==
+  dependencies:
+    fast-deep-equal "^2.0.1"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.4.1"
+    uri-js "^4.2.2"
+
 align-text@^0.1.1, align-text@^0.1.3:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
@@ -489,6 +496,13 @@ ansi-styles@^3.2.0:
   dependencies:
     color-convert "^1.9.0"
 
+ansi-styles@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+  integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+  dependencies:
+    color-convert "^1.9.0"
+
 ansi-styles@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178"
@@ -615,14 +629,13 @@ apollo-link@^1.0.0, apollo-link@^1.2.1, apollo-link@^1.2.2:
     apollo-utilities "^1.0.0"
     zen-observable-ts "^0.8.9"
 
-apollo-link@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.1.0.tgz#9d573b16387ee0d8e147b1f319e42c8c562f18f7"
-  integrity sha512-8SP3GtYSMpLa6KJaGfgr3NO/wWmB7xLWASQt3Agf08SljGNx3SOt99Yv5VtM8FPs62BoQmESX73IRmtrD1exdA==
+apollo-link@^1.2.3:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.3.tgz#9bd8d5fe1d88d31dc91dae9ecc22474d451fb70d"
+  integrity sha512-iL9yS2OfxYhigme5bpTbmRyC+Htt6tyo2fRMHT3K1XRL/C5IQDDz37OjpPy4ndx7WInSvfSZaaOTKFja9VWqSw==
   dependencies:
-    "@types/zen-observable" "0.5.3"
     apollo-utilities "^1.0.0"
-    zen-observable "^0.7.0"
+    zen-observable-ts "^0.8.10"
 
 apollo-server-core@^1.3.2:
   version "1.3.2"
@@ -776,6 +789,11 @@ arr-union@^3.1.0:
   resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
   integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
 
+array-each@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f"
+  integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8=
+
 array-equal@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
@@ -829,6 +847,11 @@ array-reduce@~0.0.0:
   resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b"
   integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=
 
+array-slice@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4"
+  integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==
+
 array-union@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
@@ -979,11 +1002,6 @@ atob@^2.1.1:
   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a"
   integrity sha1-ri1acpR38onWDdf5amMUoi3Wwio=
 
-authsome@0.0.9:
-  version "0.0.9"
-  resolved "https://registry.yarnpkg.com/authsome/-/authsome-0.0.9.tgz#08b34f1797b3539e6a362f0fb11a01ae0613f928"
-  integrity sha512-orMHR7RqVuc0apo8reiwOiiC7ZoEOcBwZjVt6wko/uEjNK5Ti/ouvP5Huqja0CNzQxItZOn+c9XUJM27bfIJTw==
-
 authsome@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/authsome/-/authsome-0.1.0.tgz#4152e666afcaa7f7c51ddbed94145ad7105904d9"
@@ -1803,7 +1821,7 @@ babel-register@^6.26.0:
     mkdirp "^0.5.1"
     source-map-support "^0.4.15"
 
-babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.9.2:
+babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0, babel-runtime@^6.9.2:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
   integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
@@ -1857,6 +1875,11 @@ babylon@^6.18.0:
   resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
   integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
 
+backo2@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
+  integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
+
 bail@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.2.tgz#f7d6c1731630a9f9f0d4d35ed1f962e2074a1764"
@@ -1914,13 +1937,13 @@ bcrypt-pbkdf@^1.0.0:
   dependencies:
     tweetnacl "^0.14.3"
 
-bcrypt@^1.0.2:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-1.0.3.tgz#b02ddc6c0b52ea16b8d3cf375d5a32e780dab548"
-  integrity sha512-pRyDdo73C8Nim3jwFJ7DWe3TZCgwDfWZ6nHS5LSdU77kWbj1frruvdndP02AOavtD4y8v6Fp2dolbHgp4SDrfg==
+bcrypt@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-2.0.1.tgz#229c5afe09379789f918efe86e5e5b682e509f85"
+  integrity sha512-DwB7WgJPdskbR+9Y3OTJtwRq09Lmm7Na6b+4ewvXjkD0nfNRi1OozxljHm5ETlDCBq9DTy04lQz+rj+T2ztIJg==
   dependencies:
-    nan "2.6.2"
-    node-pre-gyp "0.6.36"
+    nan "2.10.0"
+    node-pre-gyp "0.9.1"
 
 big.js@^3.1.3:
   version "3.2.0"
@@ -1951,6 +1974,11 @@ bluebird@2.x:
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
   integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=
 
+bluebird@^3.4.1:
+  version "3.5.2"
+  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a"
+  integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==
+
 bluebird@^3.4.7, bluebird@^3.5.0, bluebird@^3.5.1:
   version "3.5.1"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
@@ -2401,6 +2429,15 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
     strip-ansi "^3.0.0"
     supports-color "^2.0.0"
 
+chalk@2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
+  integrity sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==
+  dependencies:
+    ansi-styles "^3.2.1"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.3.0"
+
 chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1:
   version "2.3.1"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796"
@@ -2815,6 +2852,11 @@ commander@2.14.x, commander@^2.11.0, commander@^2.9.0, commander@~2.14.1:
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa"
   integrity sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==
 
+commander@^2.16.0:
+  version "2.19.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
+  integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
+
 commander@~2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781"
@@ -2912,6 +2954,13 @@ config@^1.21.0, config@^1.26.2:
     json5 "0.4.0"
     os-homedir "1.0.2"
 
+config@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/config/-/config-2.0.1.tgz#995ccc8175460578d646ac0a2e4018ffa44ca046"
+  integrity sha512-aTaviJnC8ZjQYx8kQf4u6tWqIxWolyQQ3LqXgnCLAsIb78JrUshHG0YuzIarzTaVVe1Pazms3TXImfYra8UsyQ==
+  dependencies:
+    json5 "^1.0.1"
+
 connect-history-api-fallback@^1.3.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#b06873934bc5e344fef611a196a6faae0aee015a"
@@ -3591,7 +3640,7 @@ debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.
   dependencies:
     ms "2.0.0"
 
-debug@^3.0.0, debug@^3.0.1, debug@^3.1.0:
+debug@3.1.0, debug@^3.0.0, debug@^3.0.1, debug@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
   integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
@@ -3768,6 +3817,11 @@ destroy@~1.0.4:
   resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
   integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
 
+detect-file@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
+  integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
+
 detect-indent@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
@@ -4601,7 +4655,7 @@ eventemitter2@0.4.14:
   resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab"
   integrity sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=
 
-eventemitter3@^3.0.0:
+eventemitter3@^3.0.0, eventemitter3@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"
   integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==
@@ -4891,6 +4945,11 @@ fast-deep-equal@^1.0.0:
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
   integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=
 
+fast-deep-equal@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
+  integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
+
 fast-diff@^1.1.1:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
@@ -5075,6 +5134,16 @@ find-up@^2.0.0, find-up@^2.1.0:
   dependencies:
     locate-path "^2.0.0"
 
+findup-sync@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
+  integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=
+  dependencies:
+    detect-file "^1.0.0"
+    is-glob "^3.1.0"
+    micromatch "^3.0.4"
+    resolve-dir "^1.0.1"
+
 findup@^0.1.5:
   version "0.1.5"
   resolved "https://registry.yarnpkg.com/findup/-/findup-0.1.5.tgz#8ad929a3393bac627957a7e5de4623b06b0e2ceb"
@@ -5083,6 +5152,22 @@ findup@^0.1.5:
     colors "~0.6.0-1"
     commander "~2.1.0"
 
+fined@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476"
+  integrity sha1-s33IRLdqL15wgeiE98CuNE8VNHY=
+  dependencies:
+    expand-tilde "^2.0.2"
+    is-plain-object "^2.0.3"
+    object.defaults "^1.1.0"
+    object.pick "^1.2.0"
+    parse-filepath "^1.0.1"
+
+flagged-respawn@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7"
+  integrity sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=
+
 flat-cache@^1.2.1:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481"
@@ -5632,29 +5717,39 @@ graphql-extensions@^0.0.x:
     core-js "^2.5.3"
     source-map-support "^0.5.1"
 
+graphql-postgres-subscriptions@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/graphql-postgres-subscriptions/-/graphql-postgres-subscriptions-1.0.4.tgz#a8083b03cfb93feea4ecdf088b4dde5f0481b923"
+  integrity sha512-2cyyIwwjzspf6406GnTPTOFgYeEeO/Se5mAkdbbVdunVWHKtWdRAF25qRLJIdHLqrXhjkQtTue+2k7OMehW+cA==
+  dependencies:
+    graphql-subscriptions "^0.5.8"
+    iterall "^1.2.2"
+    pg "^7.4.1"
+    pg-ipc "^1.0.4"
+
+graphql-subscriptions@^0.5.8:
+  version "0.5.8"
+  resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-0.5.8.tgz#13a6143c546bce390404657dc73ca501def30aa7"
+  integrity sha512-0CaZnXKBw2pwnIbvmVckby5Ge5e2ecmjofhYCdyeACbCly2j3WXDP/pl+s+Dqd2GQFC7y99NB+53jrt55CKxYQ==
+  dependencies:
+    iterall "^1.2.1"
+
 graphql-tag@^2.7.3:
   version "2.9.1"
   resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.9.1.tgz#1ab090ef7d3518b06d8c97d1393672145fe91587"
   integrity sha512-JBLpagu/Xbb8N6xU6hZvBeHjdvnWb/GJnA/rrnBy3iSl0bcy+pjT5N1HctAsWNmGoAgY1+ilwv6JJqu0Tk2hHQ==
 
-graphql-tools@^2.18.0:
-  version "2.21.0"
-  resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-2.21.0.tgz#c0d0fbda6f40a87c8d267a2989ade2ae8b9a288e"
-  integrity sha512-AmG4WGdpL1OHwnA20ouP7BVB3KnvUOvsc7+4ULWRzEunyRFUYqxrgnEf20iZnYAha8JCb7AP4WPMwWKmGT91rg==
+graphql-tools@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-4.0.0.tgz#6ea01937c6f947212f83567ba687e97c22fdd2a6"
+  integrity sha512-WokvjkanuZwY4BZBS3SlkDjrjCPu7WlCtLB2i9JiiXembVEkNos3Rl90zf7sJu72zSidGzTXU63iXRO2Fg3TtA==
   dependencies:
-    apollo-link "^1.1.0"
+    apollo-link "^1.2.3"
     apollo-utilities "^1.0.1"
     deprecated-decorator "^0.1.6"
     iterall "^1.1.3"
     uuid "^3.1.0"
 
-graphql@^0.12.3:
-  version "0.12.3"
-  resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.12.3.tgz#11668458bbe28261c0dcb6e265f515ba79f6ce07"
-  integrity sha512-Hn9rdu4zacplKXNrLCvR8YFiTGnbM4Zw/UH8FDmzBDsH7ou40lSNH4tIlsxcYnz2TGNVJCpu1WxCM23yd6kzhA==
-  dependencies:
-    iterall "1.1.3"
-
 graphql@^0.13.0:
   version "0.13.2"
   resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.13.2.tgz#4c740ae3c222823e7004096f832e7b93b2108270"
@@ -5662,6 +5757,13 @@ graphql@^0.13.0:
   dependencies:
     iterall "^1.2.1"
 
+graphql@^14.0.2:
+  version "14.0.2"
+  resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.0.2.tgz#7dded337a4c3fd2d075692323384034b357f5650"
+  integrity sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==
+  dependencies:
+    iterall "^1.2.2"
+
 grid-styled@5.0.2:
   version "5.0.2"
   resolved "https://registry.yarnpkg.com/grid-styled/-/grid-styled-5.0.2.tgz#1e81d7d5bde50a9b43d81cf111b81399126fe595"
@@ -6272,7 +6374,7 @@ internal-ip@1.2.0:
   dependencies:
     meow "^3.3.0"
 
-interpret@^1.0.0:
+interpret@^1.0.0, interpret@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
   integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=
@@ -6316,6 +6418,14 @@ is-absolute-url@^2.0.0:
   resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
   integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=
 
+is-absolute@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576"
+  integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==
+  dependencies:
+    is-relative "^1.0.0"
+    is-windows "^1.0.1"
+
 is-accessor-descriptor@^0.1.6:
   version "0.1.6"
   resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
@@ -6624,6 +6734,13 @@ is-regexp@^1.0.0:
   resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
   integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
 
+is-relative@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d"
+  integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==
+  dependencies:
+    is-unc-path "^1.0.0"
+
 is-resolvable@^1.0.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
@@ -6683,6 +6800,13 @@ is-typedarray@~1.0.0:
   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
   integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
 
+is-unc-path@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d"
+  integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==
+  dependencies:
+    unc-path-regex "^0.1.2"
+
 is-utf8@^0.2.0:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
@@ -6840,17 +6964,12 @@ items@2.x.x:
   resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198"
   integrity sha1-i9FtnIOxlSneWuoyGsqtp4NkoZg=
 
-iterall@1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.3.tgz#1cbbff96204056dde6656e2ed2e2226d0e6d72c9"
-  integrity sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ==
-
 iterall@^1.1.3:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.0.tgz#434e9f41f0b99911ab9c3d49d95f0e079176a2a2"
   integrity sha512-FB8k5B8otDib0rFysEP5G/oOY6aBF48Y9crLxyZ43eHsk/SfMVH1JqvzU0badSu/WR5nkk3ihp8VQlyBP3SJxg==
 
-iterall@^1.2.1:
+iterall@^1.2.1, iterall@^1.2.2:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7"
   integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==
@@ -7183,10 +7302,10 @@ joi@^10.0.6:
     items "2.x.x"
     topo "2.x.x"
 
-joi@^13.1.0:
-  version "13.1.2"
-  resolved "https://registry.yarnpkg.com/joi/-/joi-13.1.2.tgz#b2db260323cc7f919fafa51e09e2275bd089a97e"
-  integrity sha512-bZZSQYW5lPXenOfENvgCBPb9+H6E6MeNWcMtikI04fKphj5tvFL9TOb+H2apJzbCrRw/jebjTH8z6IHLpBytGg==
+joi@^13.6.0:
+  version "13.7.0"
+  resolved "https://registry.yarnpkg.com/joi/-/joi-13.7.0.tgz#cfd85ebfe67e8a1900432400b4d03bbd93fb879f"
+  integrity sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q==
   dependencies:
     hoek "5.x.x"
     isemail "3.x.x"
@@ -7305,6 +7424,11 @@ json-schema-traverse@^0.3.0:
   resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
   integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=
 
+json-schema-traverse@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+  integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
 json-schema@0.2.3:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
@@ -7342,6 +7466,13 @@ json5@^0.5.0, json5@^0.5.1:
   resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
   integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
 
+json5@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
+  integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
+  dependencies:
+    minimist "^1.2.0"
+
 jsonfile@^3.0.0:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
@@ -7506,6 +7637,28 @@ kleur@^2.0.1:
   resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.1.tgz#7cc64b0d188d0dcbc98bdcdfdda2cc10619ddce8"
   integrity sha512-Zq/jyANIJ2uX8UZjWlqLwbyhcxSXJtT/Y89lClyeZd3l++3ztL1I5SSCYrbcbwSunTjC88N3WuMk0kRDQD6gzA==
 
+knex@^0.15.2:
+  version "0.15.2"
+  resolved "https://registry.yarnpkg.com/knex/-/knex-0.15.2.tgz#6059b87489605f4cc87599a6d2a9d265709e9340"
+  integrity sha1-YFm4dIlgX0zIdZmm0qnSZXCek0A=
+  dependencies:
+    babel-runtime "^6.26.0"
+    bluebird "^3.5.1"
+    chalk "2.3.2"
+    commander "^2.16.0"
+    debug "3.1.0"
+    inherits "~2.0.3"
+    interpret "^1.1.0"
+    liftoff "2.5.0"
+    lodash "^4.17.10"
+    minimist "1.2.0"
+    mkdirp "^0.5.1"
+    pg-connection-string "2.0.0"
+    tarn "^1.1.4"
+    tildify "1.2.0"
+    uuid "^3.3.2"
+    v8flags "^3.1.1"
+
 known-css-properties@^0.5.0:
   version "0.5.0"
   resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.5.0.tgz#6ff66943ed4a5b55657ee095779a91f4536f8084"
@@ -7593,6 +7746,20 @@ levn@^0.3.0, levn@~0.3.0:
     prelude-ls "~1.1.2"
     type-check "~0.3.2"
 
+liftoff@2.5.0:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec"
+  integrity sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=
+  dependencies:
+    extend "^3.0.0"
+    findup-sync "^2.0.0"
+    fined "^1.0.1"
+    flagged-respawn "^1.0.0"
+    is-plain-object "^2.0.4"
+    object.map "^1.0.0"
+    rechoir "^0.6.2"
+    resolve "^1.1.7"
+
 linkify-it@^2.0.0:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f"
@@ -7908,6 +8075,11 @@ lodash@4.17.5, lodash@^4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
   integrity sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==
 
+lodash@^4.17.0:
+  version "4.17.11"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
+  integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
+
 lodash@^4.17.10, lodash@^4.17.2, lodash@~4.17.10:
   version "4.17.10"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
@@ -8007,6 +8179,13 @@ make-dir@^1.0.0:
   dependencies:
     pify "^3.0.0"
 
+make-iterator@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
+  integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==
+  dependencies:
+    kind-of "^6.0.2"
+
 makeerror@1.0.x:
   version "1.0.11"
   resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
@@ -8014,7 +8193,7 @@ makeerror@1.0.x:
   dependencies:
     tmpl "1.0.x"
 
-map-cache@^0.2.2:
+map-cache@^0.2.0, map-cache@^0.2.2:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
   integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
@@ -8188,7 +8367,7 @@ micromatch@^2.1.5, micromatch@^2.3.11:
     parse-glob "^3.0.4"
     regex-cache "^0.4.2"
 
-micromatch@^3.1.4:
+micromatch@^3.0.4, micromatch@^3.1.4:
   version "3.1.10"
   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
   integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
@@ -8303,16 +8482,16 @@ minimist@1.1.x:
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
   integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=
 
+minimist@1.2.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+  integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
+
 minimist@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de"
   integrity sha1-md9lelJXTCHJBXSX33QnkLK0wN4=
 
-minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
-  integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
-
 minimist@~0.0.1:
   version "0.0.10"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
@@ -8460,12 +8639,7 @@ mute-stream@0.0.7, mute-stream@~0.0.4:
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
   integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
 
-nan@2.6.2:
-  version "2.6.2"
-  resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
-  integrity sha1-5P805slf37WuzAjeZZb0NgWn20U=
-
-nan@^2.10.0, nan@^2.9.2:
+nan@2.10.0, nan@^2.10.0, nan@^2.9.2:
   version "2.10.0"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
   integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==
@@ -8533,6 +8707,15 @@ nearley@^2.7.10:
     randexp "0.4.6"
     semver "^5.4.1"
 
+needle@^2.2.0:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e"
+  integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==
+  dependencies:
+    debug "^2.1.2"
+    iconv-lite "^0.4.4"
+    sax "^1.2.4"
+
 needle@^2.2.1:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d"
@@ -8667,20 +8850,21 @@ node-notifier@^5.2.1:
     shellwords "^0.1.1"
     which "^1.3.0"
 
-node-pre-gyp@0.6.36:
-  version "0.6.36"
-  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786"
-  integrity sha1-22BBEst04NR3VU6bUFsXq936t4Y=
+node-pre-gyp@0.9.1:
+  version "0.9.1"
+  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz#f11c07516dd92f87199dbc7e1838eab7cd56c9e0"
+  integrity sha1-8RwHUW3ZL4cZnbx+GDjqt81WyeA=
   dependencies:
+    detect-libc "^1.0.2"
     mkdirp "^0.5.1"
+    needle "^2.2.0"
     nopt "^4.0.1"
+    npm-packlist "^1.1.6"
     npmlog "^4.0.2"
     rc "^1.1.7"
-    request "^2.81.0"
     rimraf "^2.6.1"
     semver "^5.3.0"
-    tar "^2.2.1"
-    tar-pack "^3.4.0"
+    tar "^4"
 
 node-pre-gyp@^0.10.0:
   version "0.10.3"
@@ -8959,6 +9143,16 @@ object.assign@^4.0.4, object.assign@^4.1.0:
     has-symbols "^1.0.0"
     object-keys "^1.0.11"
 
+object.defaults@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf"
+  integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=
+  dependencies:
+    array-each "^1.0.1"
+    array-slice "^1.0.0"
+    for-own "^1.0.0"
+    isobject "^3.0.0"
+
 object.entries@^1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f"
@@ -8977,6 +9171,14 @@ object.getownpropertydescriptors@^2.0.3:
     define-properties "^1.1.2"
     es-abstract "^1.5.1"
 
+object.map@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37"
+  integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=
+  dependencies:
+    for-own "^1.0.0"
+    make-iterator "^1.0.0"
+
 object.omit@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
@@ -8985,7 +9187,7 @@ object.omit@^2.0.0:
     for-own "^0.1.4"
     is-extendable "^0.1.1"
 
-object.pick@^1.3.0:
+object.pick@^1.2.0, object.pick@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
   integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
@@ -9002,6 +9204,15 @@ object.values@^1.0.4:
     function-bind "^1.1.0"
     has "^1.0.1"
 
+objection@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/objection/-/objection-1.3.0.tgz#2b7e41d4b44a5c1abcb40e34e7ef6347e8bb683d"
+  integrity sha512-LhKd9N/tSNiFNKSozydrk7C8XmQbEbYNmnF1vC7ywgdWzMZfWhehILIE95mVpdo93f26jWDVaY6SHp/bjMvEng==
+  dependencies:
+    ajv "^6.1.1"
+    bluebird "^3.5.1"
+    lodash "^4.17.4"
+
 obuf@^1.0.0, obuf@^1.1.1:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
@@ -9260,6 +9471,15 @@ parse-entities@^1.1.0:
     is-decimal "^1.0.0"
     is-hexadecimal "^1.0.0"
 
+parse-filepath@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891"
+  integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=
+  dependencies:
+    is-absolute "^1.0.0"
+    map-cache "^0.2.0"
+    path-root "^0.1.1"
+
 parse-github-repo-url@^1.3.0:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50"
@@ -9417,6 +9637,18 @@ path-parse@^1.0.5:
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
   integrity sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=
 
+path-root-regex@^0.1.0:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d"
+  integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=
+
+path-root@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7"
+  integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=
+  dependencies:
+    path-root-regex "^0.1.0"
+
 path-to-regexp@0.1.7:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
@@ -9483,6 +9715,16 @@ pg-connection-string@0.1.3:
   resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7"
   integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=
 
+pg-connection-string@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.0.0.tgz#3eefe5997e06d94821e4d502e42b6a1c73f8df82"
+  integrity sha1-Pu/lmX4G2Ugh5NUC5CtqHHP434I=
+
+pg-ipc@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/pg-ipc/-/pg-ipc-1.0.4.tgz#e018f5aae417ded8a917878e33c1fe911bcce45f"
+  integrity sha1-4Bj1quQX3tipF4eOM8H+kRvM5F8=
+
 pg-pool@~2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.3.tgz#c022032c8949f312a4f91fb6409ce04076be3257"
@@ -10074,6 +10316,7 @@ promise@^7.1.1:
 prompt@^1.0.0, prompt@flatiron/prompt#1c95d1d8d333b5fbc13fa5f0619f3dcf0d514f87:
   version "1.0.0"
   resolved "https://codeload.github.com/flatiron/prompt/tar.gz/1c95d1d8d333b5fbc13fa5f0619f3dcf0d514f87"
+  integrity sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4=
   dependencies:
     colors "^1.1.2"
     read "1.0.x"
@@ -10330,72 +10573,36 @@ pubsweet-component-signup@^1.0.0:
     react-router "^4.2.0"
     redux "^3.7.2"
 
-pubsweet-server@2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/pubsweet-server/-/pubsweet-server-2.0.3.tgz#97d36cec0e2f4f0c2955fb0b0de73206ec05fe69"
-  integrity sha512-AEn4aSs4GHJciqsvTZkXKLh+NcgAJ34HDIPp1ODnZ9nubohSDH+ZM6XBIjiP77BaJtnnjPzs536v/b/zFy1rkw==
+pubsweet-server@10.0.1, pubsweet-server@^10.0.1:
+  version "10.0.1"
+  resolved "https://registry.yarnpkg.com/pubsweet-server/-/pubsweet-server-10.0.1.tgz#ac2ccc0ae1f42f2c97b044be3f90782b11b1d0fa"
+  integrity sha512-hUcOfVAV6rWeohgb93NO5sn414m03cOeKKUaOKxCXqn8CNgFmZQhmogLeEXH+MVbEXsnbpYnEuV0rcuwA0boNQ==
   dependencies:
-    "@pubsweet/logger" "^0.2.2"
-    apollo-server-express "^1.3.2"
-    apollo-upload-server "^4.0.2"
-    authsome "0.0.9"
-    bcrypt "^1.0.2"
-    bluebird "^3.5.1"
-    body-parser "^1.15.2"
-    colors "^1.1.2"
-    config "^1.26.2"
-    cookie-parser "^1.4.3"
-    dotenv "^4.0.0"
-    express "^4.16.1"
-    graphql "^0.12.3"
-    graphql-tools "^2.18.0"
-    helmet "^3.8.1"
-    http-status-codes "^1.0.6"
-    joi "^13.1.0"
-    jsonwebtoken "^7.1.7"
-    lodash "^4.0.0"
-    minimist "^1.2.0"
-    morgan "^1.8.2"
-    multer "^1.1.0"
-    passport "^0.3.2"
-    passport-anonymous "^1.0.1"
-    passport-http-bearer "^1.0.1"
-    passport-local "^1.0.0"
-    pg "^7.4.1"
-    promise-queue "^2.2.3"
-    prompt "^1.0.0"
-    pubsweet-sse "^0.1.4"
-    require-relative "^0.8.7"
-    uuid "^3.0.1"
-    winston "^2.2.0"
-
-pubsweet-server@^6.1.0:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/pubsweet-server/-/pubsweet-server-6.1.0.tgz#038b8fdb08717c1b701f175030546492f387303c"
-  integrity sha512-maPhfKtyEicoRhX9jCZkQgQ08S58P5BU1RpJ58gF+lmdswTyrCsRqbid22eVmJJHAiOW8XByDbV2ipw8PUbZ+w==
-  dependencies:
-    "@pubsweet/logger" "^0.2.2"
+    "@pubsweet/logger" "^0.2.7"
     apollo-server-express "^1.3.2"
     apollo-upload-server "^4.0.2"
     authsome "^0.1.0"
-    bcrypt "^1.0.2"
+    bcrypt "^2.0.1"
     bluebird "^3.5.1"
     body-parser "^1.15.2"
     colors "^1.1.2"
-    config "^1.26.2"
+    config "^2.0.1"
     cookie-parser "^1.4.3"
     dotenv "^4.0.0"
     express "^4.16.1"
-    graphql "^0.12.3"
-    graphql-tools "^2.18.0"
+    graphql "^14.0.2"
+    graphql-postgres-subscriptions "^1.0.4"
+    graphql-tools "^4.0.0"
     helmet "^3.8.1"
     http-status-codes "^1.0.6"
-    joi "^13.1.0"
+    joi "^13.6.0"
     jsonwebtoken "^7.1.7"
+    knex "^0.15.2"
     lodash "^4.0.0"
     minimist "^1.2.0"
     morgan "^1.8.2"
     multer "^1.1.0"
+    objection "^1.3.0"
     passport "^0.3.2"
     passport-anonymous "^1.0.1"
     passport-http-bearer "^1.0.1"
@@ -10403,28 +10610,23 @@ pubsweet-server@^6.1.0:
     pg "^7.4.1"
     promise-queue "^2.2.3"
     prompt "^1.0.0"
-    pubsweet-sse "^1.0.0"
-    require-relative "^0.8.7"
+    pubsweet-sse "^1.0.1"
+    subscriptions-transport-ws "^0.9.12"
     uuid "^3.0.1"
     winston "^2.2.0"
 
-pubsweet-sse@^0.1.4:
-  version "0.1.4"
-  resolved "https://registry.yarnpkg.com/pubsweet-sse/-/pubsweet-sse-0.1.4.tgz#1ff38a230143cbd487a8d44afb28a6c4746ee464"
-  integrity sha512-zQlcHSgVpKvsPSoNHgoh7+8DPIPQ6kqMRRhs3e8d/icHrJAhoz0aQdovB8VK5XZfjUkoHYidCjDT2LFueDvwVA==
-
-pubsweet-sse@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/pubsweet-sse/-/pubsweet-sse-1.0.0.tgz#dd36aa378a302b518d417b545b064da65aec876a"
-  integrity sha512-oxCfHoH68ym4k8WNxfGIkEh7OVGGSx14p1QVaYmVQJ4XpdWdY9J4vErG/RcbWTPpaAz2hZIUJb1AsCU7E70VKA==
+pubsweet-sse@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/pubsweet-sse/-/pubsweet-sse-1.0.1.tgz#675f699213a7c228a448e7c9f272a5a9e7585fcf"
+  integrity sha512-A5aDdSI38GmrfUhXc3bjXGExqUEzuzcWdm63Km7ww9KIMFQDnHl06ovap8OAP/+BmqxXvXooxHqqeQ/rhe0l7A==
 
-pubsweet@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/pubsweet/-/pubsweet-2.2.1.tgz#6191303105c8d531a16de7090b89aec8f451a454"
-  integrity sha512-7uCRpJFsBr3cxyb22ZrCpK8p4a9p+BKdR2Sg4se4U3Z+DKkEUtLZ5Nw6hm1od3bm2toihAEl91AILBQuIy8rjw==
+pubsweet@3.0.6:
+  version "3.0.6"
+  resolved "https://registry.yarnpkg.com/pubsweet/-/pubsweet-3.0.6.tgz#8f2543f8d101cea596be53edf3d559d6bd89a57f"
+  integrity sha512-eJIscLmMvLmZ5+DBsOh9fpMNmXDd1xYtwOHNYty8hMn5pP6+b93EOzXeI+ofoFzdCTVCeAIATWKMAJmzWutOnQ==
   dependencies:
-    "@pubsweet/db-manager" "^1.0.10"
-    "@pubsweet/logger" "^0.2.2"
+    "@pubsweet/db-manager" "^2.0.6"
+    "@pubsweet/logger" "^0.2.7"
     bluebird "^3.5.0"
     colors "^1.1.2"
     commander "^2.9.0"
@@ -10433,8 +10635,7 @@ pubsweet@^2.2.1:
     fs-extra "^4.0.2"
     inflection "^1.12.0"
     prompt flatiron/prompt#1c95d1d8d333b5fbc13fa5f0619f3dcf0d514f87
-    pubsweet-server "^6.1.0"
-    require-relative "^0.8.7"
+    pubsweet-server "^10.0.1"
     uuid "^3.0.1"
     webpack "^3.8.1"
     webpack-dev-middleware "^1.12.0"
@@ -11115,6 +11316,13 @@ recast@^0.13.0:
     private "~0.1.5"
     source-map "~0.6.1"
 
+rechoir@^0.6.2:
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
+  integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
+  dependencies:
+    resolve "^1.1.6"
+
 recompose@^0.26.0:
   version "0.26.0"
   resolved "https://registry.yarnpkg.com/recompose/-/recompose-0.26.0.tgz#9babff039cb72ba5bd17366d55d7232fbdfb2d30"
@@ -11543,7 +11751,7 @@ request@2.87.0, request@^2.87.0:
     tunnel-agent "^0.6.0"
     uuid "^3.1.0"
 
-request@^2.81.0, request@^2.83.0:
+request@^2.83.0:
   version "2.83.0"
   resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
   integrity sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==
@@ -11591,11 +11799,6 @@ require-main-filename@^1.0.1:
   resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
   integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
 
-require-relative@^0.8.7:
-  version "0.8.7"
-  resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de"
-  integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=
-
 require-uncached@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
@@ -11621,7 +11824,7 @@ resolve-cwd@^2.0.0:
   dependencies:
     resolve-from "^3.0.0"
 
-resolve-dir@^1.0.0:
+resolve-dir@^1.0.0, resolve-dir@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
   integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
@@ -11659,6 +11862,13 @@ resolve@1.1.7:
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
   integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
 
+resolve@^1.0.0, resolve@^1.1.6, resolve@^1.1.7:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
+  integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==
+  dependencies:
+    path-parse "^1.0.5"
+
 resolve@^1.3.3, resolve@^1.5.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
@@ -12732,6 +12942,17 @@ stylis@^3.5.0:
   resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.0.tgz#016fa239663d77f868fef5b67cf201c4b7c701e1"
   integrity sha512-pP7yXN6dwMzAR29Q0mBrabPCe0/mNO1MSr93bhay+hcZondvMMTpeGyd8nbhYJdyperNT2DRxONQuUGcJr5iPw==
 
+subscriptions-transport-ws@^0.9.12:
+  version "0.9.15"
+  resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.15.tgz#68a8b7ba0037d8c489fb2f5a102d1494db297d0d"
+  integrity sha512-f9eBfWdHsePQV67QIX+VRhf++dn1adyC/PZHP6XI5AfKnZ4n0FW+v5omxwdHVpd4xq2ZijaHEcmlQrhBY79ZWQ==
+  dependencies:
+    backo2 "^1.0.2"
+    eventemitter3 "^3.1.0"
+    iterall "^1.2.1"
+    symbol-observable "^1.0.4"
+    ws "^5.2.0"
+
 sugarss@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.1.tgz#be826d9003e0f247735f92365dc3fd7f1bae9e44"
@@ -12796,6 +13017,13 @@ supports-color@^5.2.0:
   dependencies:
     has-flag "^3.0.0"
 
+supports-color@^5.3.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+  integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+  dependencies:
+    has-flag "^3.0.0"
+
 svg-tags@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
@@ -12904,6 +13132,11 @@ tar@^4:
     safe-buffer "^5.1.2"
     yallist "^3.0.2"
 
+tarn@^1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/tarn/-/tarn-1.1.4.tgz#aeeb85964b1afa0bbf381359c1167df237c27b6a"
+  integrity sha512-j4samMCQCP5+6Il9/cxCqBd3x4vvlLeVdoyGex0KixPKl4F8LpNbDSC6NDhjianZgUngElRr9UI1ryZqJDhwGg==
+
 temp-dir@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d"
@@ -12973,6 +13206,13 @@ thunky@^1.0.2:
   resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.2.tgz#a862e018e3fb1ea2ec3fce5d55605cf57f247371"
   integrity sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=
 
+tildify@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a"
+  integrity sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=
+  dependencies:
+    os-homedir "^1.0.0"
+
 time-stamp@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357"
@@ -13282,6 +13522,21 @@ ultron@~1.1.0:
   resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
   integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==
 
+umzug@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/umzug/-/umzug-2.1.0.tgz#c49dd71c7c26d082a9c9d3592dc6dc92cf867761"
+  integrity sha512-BgT+ekpItEWaG+3JjLLj6yVTxw2wIH8Cr6JyKYIzukWAx9nzGhC6BGHb/IRMjpobMM1qtIrReATwLUjKpU2iOQ==
+  dependencies:
+    babel-runtime "^6.23.0"
+    bluebird "^3.4.1"
+    lodash "^4.17.0"
+    resolve "^1.0.0"
+
+unc-path-regex@^0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
+  integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo=
+
 uncontrollable@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-4.1.0.tgz#e0358291252e1865222d90939b19f2f49f81c1a9"
@@ -13456,6 +13711,13 @@ upper-case@^1.1.1:
   resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
   integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
 
+uri-js@^4.2.2:
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
+  integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
+  dependencies:
+    punycode "^2.1.0"
+
 urix@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
@@ -13571,6 +13833,18 @@ uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0:
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14"
   integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==
 
+uuid@^3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
+  integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
+
+v8flags@^3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.1.tgz#42259a1461c08397e37fe1d4f1cfb59cad85a053"
+  integrity sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==
+  dependencies:
+    homedir-polyfill "^1.0.1"
+
 validate-npm-package-license@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
@@ -14016,6 +14290,13 @@ ws@^4.0.0:
     safe-buffer "~5.1.0"
     ultron "~1.1.0"
 
+ws@^5.2.0:
+  version "5.2.2"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
+  integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
+  dependencies:
+    async-limiter "~1.0.0"
+
 x-is-function@^1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/x-is-function/-/x-is-function-1.0.4.tgz#5d294dc3d268cbdd062580e0c5df77a391d1fa1e"
@@ -14266,6 +14547,13 @@ yargs@~3.10.0:
     decamelize "^1.0.0"
     window-size "0.1.0"
 
+zen-observable-ts@^0.8.10:
+  version "0.8.10"
+  resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.10.tgz#18e2ce1c89fe026e9621fd83cc05168228fce829"
+  integrity sha512-5vqMtRggU/2GhePC9OU4sYEWOdvmayp2k3gjPf4F0mXwB3CSbbNznfDUvDJx9O2ZTa1EIXdJhPchQveFKwNXPQ==
+  dependencies:
+    zen-observable "^0.8.0"
+
 zen-observable-ts@^0.8.9:
   version "0.8.9"
   resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.9.tgz#d3c97af08c0afdca37ebcadf7cc3ee96bda9bab1"
@@ -14273,11 +14561,6 @@ zen-observable-ts@^0.8.9:
   dependencies:
     zen-observable "^0.8.0"
 
-zen-observable@^0.7.0:
-  version "0.7.1"
-  resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.7.1.tgz#f84075c0ee085594d3566e1d6454207f126411b3"
-  integrity sha512-OI6VMSe0yeqaouIXtedC+F55Sr6r9ppS7+wTbSexkYdHbdt4ctTuPNXP/rwm7GTVI63YBc+EBT0b0tl7YnJLRg==
-
 zen-observable@^0.8.0:
   version "0.8.8"
   resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.8.tgz#1ea93995bf098754a58215a1e0a7309e5749ec42"