diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
index efb857a0f57699ae41d9bacd541656085fc80eb7..31273d00a0a76956b24dcda1e12e060bf11eebf8 100644
--- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java
@@ -19,7 +19,10 @@ import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.Client;
+import org.briarproject.bramble.api.sync.ClientVersioningManager;
+import org.briarproject.bramble.api.sync.ClientVersioningManager.ClientVersioningHook;
 import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.Group.Visibility;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.Message;
 import org.briarproject.bramble.api.sync.MessageId;
@@ -39,11 +42,13 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.logging.Logger;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+import static java.util.logging.Level.INFO;
 import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
 import static org.briarproject.briar.api.introduction.Role.INTRODUCEE;
 import static org.briarproject.briar.api.introduction.Role.INTRODUCER;
@@ -59,8 +64,13 @@ import static org.briarproject.briar.introduction.MessageType.REQUEST;
 @Immutable
 @NotNullByDefault
 class IntroductionManagerImpl extends ConversationClientImpl
-		implements IntroductionManager, Client, ContactHook {
+		implements IntroductionManager, Client, ContactHook,
+		ClientVersioningHook {
 
+	private static final Logger LOG =
+			Logger.getLogger(IntroductionManagerImpl.class.getName());
+
+	private final ClientVersioningManager clientVersioningManager;
 	private final ContactGroupFactory contactGroupFactory;
 	private final ContactManager contactManager;
 	private final MessageParser messageParser;
@@ -74,11 +84,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
 	private final Group localGroup;
 
 	@Inject
-	IntroductionManagerImpl(
-			DatabaseComponent db,
-			ClientHelper clientHelper,
-			MetadataParser metadataParser,
-			MessageTracker messageTracker,
+	IntroductionManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
+			ClientVersioningManager clientVersioningManager,MetadataParser metadataParser, MessageTracker messageTracker,
 			ContactGroupFactory contactGroupFactory,
 			ContactManager contactManager,
 			MessageParser messageParser,
@@ -89,6 +96,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
 			IntroductionCrypto crypto,
 			IdentityManager identityManager) {
 		super(db, clientHelper, metadataParser, messageTracker);
+		this.clientVersioningManager = clientVersioningManager;
 		this.contactGroupFactory = contactGroupFactory;
 		this.contactManager = contactManager;
 		this.messageParser = messageParser;
@@ -112,13 +120,17 @@ class IntroductionManagerImpl extends ConversationClientImpl
 	}
 
 	@Override
-	// TODO adapt to use upcoming ClientVersioning client
 	public void addingContact(Transaction txn, Contact c) throws DbException {
 		// Create a group to share with the contact
 		Group g = getContactGroup(c);
 		// Store the group and share it with the contact
 		db.addGroup(txn, g);
-		db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
+		// Apply the client's visibility to the contact group
+		Visibility client = clientVersioningManager.getClientVisibility(txn,
+				c.getId(), CLIENT_ID, CLIENT_VERSION);
+		if (LOG.isLoggable(INFO))
+			LOG.info("Applying visibility " + client + " to new contact group");db.setGroupVisibility(txn, c.getId(), g.getId(), client);
+		db.setGroupVisibility(txn, c.getId(), g.getId(), client);
 		// Attach the contact ID to the group
 		BdfDictionary meta = new BdfDictionary();
 		meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt());
@@ -135,9 +147,20 @@ class IntroductionManagerImpl extends ConversationClientImpl
 		abortOrRemoveSessionWithIntroducee(txn, c);
 
 		// Remove the contact group (all messages will be removed with it)
+
 		db.removeGroup(txn, getContactGroup(c));
 	}
 
+	@Override
+	public void onClientVisibilityChanging(Transaction txn, Contact c,
+			Visibility v) throws DbException {
+		// Apply the client's visibility to the contact group
+		Group g = getContactGroup(c);
+		if (LOG.isLoggable(INFO))
+			LOG.info("Applying visibility " + v + " to contact group");
+		db.setGroupVisibility(txn, c.getId(), g.getId(), v);
+	}
+
 	@Override
 	public Group getContactGroup(Contact c) {
 		return contactGroupFactory
@@ -147,10 +170,11 @@ class IntroductionManagerImpl extends ConversationClientImpl
 	@Override
 	protected boolean incomingMessage(Transaction txn, Message m, BdfList body,
 			BdfDictionary bdfMeta) throws DbException, FormatException {
-		// Parse the metadata
+// Parse the metadata
 		MessageMetadata meta = messageParser.parseMetadata(bdfMeta);
 		// Look up the session, if there is one
 		SessionId sessionId = meta.getSessionId();
+
 		IntroduceeSession newIntroduceeSession = null;
 		if (sessionId == null) {
 			if (meta.getMessageType() != REQUEST) throw new AssertionError();
@@ -161,7 +185,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
 		// Handle the message
 		Session session;
 		MessageId storageId;
-		if (ss == null) {
+		if (ss == null){
 			if (meta.getMessageType() != REQUEST) throw new FormatException();
 			if (newIntroduceeSession == null) throw new AssertionError();
 			storageId = createStorageId(txn);
@@ -172,12 +196,12 @@ class IntroductionManagerImpl extends ConversationClientImpl
 			Role role = sessionParser.getRole(ss.bdfSession);
 			if (role == INTRODUCER) {
 				session = handleMessage(txn, m, body, meta.getMessageType(),
-						sessionParser.parseIntroducerSession(ss.bdfSession),
-						introducerEngine);
+					sessionParser.parseIntroducerSession(ss.bdfSession),
+					introducerEngine);
 			} else if (role == INTRODUCEE) {
 				session = handleMessage(txn, m, body, meta.getMessageType(),
-						sessionParser.parseIntroduceeSession(m.getGroupId(),
-								ss.bdfSession), introduceeEngine);
+					sessionParser.parseIntroduceeSession(m.getGroupId(),
+						ss.bdfSession), introduceeEngine);
 			} else throw new AssertionError();
 		}
 		// Store the updated session
@@ -388,13 +412,14 @@ class IntroductionManagerImpl extends ConversationClientImpl
 		List<IntroductionMessage> messages;
 		Transaction txn = db.startTransaction(true);
 		try {
-			Contact contact = db.getContact(txn, c);
+			Contact contact =db.getContact(txn, c);
 			GroupId contactGroupId = getContactGroup(contact).getId();
 			BdfDictionary query = messageParser.getMessagesVisibleInUiQuery();
-			Map<MessageId, BdfDictionary> results = clientHelper
-					.getMessageMetadataAsDictionary(txn, contactGroupId, query);
-			messages = new ArrayList<>(results.size());
-			for (Entry<MessageId, BdfDictionary> e : results.entrySet()) {
+			Map<MessageId, BdfDictionary> results = clientHelper.getMessageMetadataAsDictionary(txn, contactGroupId, query);
+			 messages = new ArrayList<>(results.size());
+			for (Entry<
+				MessageId ,
+				BdfDictionary > e : results.entrySet()) {
 				MessageId m = e.getKey();
 				MessageMetadata meta =
 						messageParser.parseMetadata(e.getValue());
@@ -405,7 +430,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
 				if (type == REQUEST) {
 					messages.add(
 							parseInvitationRequest(txn, contactGroupId, m,
-									meta, status, ss.bdfSession));
+								meta, status, ss.bdfSession));
 				} else if (type == ACCEPT) {
 					messages.add(
 							parseInvitationResponse(contactGroupId, m, meta,
@@ -425,8 +450,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
 		return messages;
 	}
 
-	private IntroductionRequest parseInvitationRequest(Transaction txn,
-			GroupId contactGroupId, MessageId m, MessageMetadata meta,
+	private IntroductionRequest parseInvitationRequest(Transaction txn, GroupId contactGroupId, MessageId m, MessageMetadata meta,
 			MessageStatus status, BdfDictionary bdfSession)
 			throws DbException, FormatException {
 		Role role = sessionParser.getRole(bdfSession);
@@ -497,9 +521,9 @@ class IntroductionManagerImpl extends ConversationClientImpl
 		Map<MessageId, BdfDictionary> sessions;
 		try {
 			sessions = clientHelper
-					.getMessageMetadataAsDictionary(txn, localGroup.getId(),
+					.getMessageMetadataAsDictionary(txn,localGroup.getId(),
 							query);
-		} catch (FormatException e) {
+		} catch (FormatException e){
 			throw new DbException(e);
 		}
 		for (MessageId id : sessions.keySet()) {
@@ -510,20 +534,20 @@ class IntroductionManagerImpl extends ConversationClientImpl
 	private void abortOrRemoveSessionWithIntroducee(Transaction txn,
 			Contact c) throws DbException {
 		BdfDictionary query = sessionEncoder.getIntroducerSessionsQuery();
-		Map<MessageId, BdfDictionary> sessions;
+			Map<MessageId, BdfDictionary> sessions;
 		try {
 			sessions = clientHelper
-					.getMessageMetadataAsDictionary(txn, localGroup.getId(),
-							query);
+					.getMessageMetadataAsDictionary(txn,
+							localGroup.getId(),
+			query);
 		} catch (FormatException e) {
 			throw new DbException();
 		}
-		LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
-		for (Entry<MessageId, BdfDictionary> session : sessions.entrySet()) {
+		LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);for (Entry<MessageId, BdfDictionary> session : sessions.entrySet()) {
 			IntroducerSession s;
 			try {
 				s = sessionParser.parseIntroducerSession(session.getValue());
-			} catch (FormatException e) {
+			} catch (FormatException e){
 				throw new DbException();
 			}
 			if (s.getIntroduceeA().author.equals(c.getAuthor())) {
diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java
index a41215ae2fe40c192156c371603ee7a5eba6292c..f7e55c99ba77d787b6c0d745feb442070833bcc4 100644
--- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionModule.java
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.client.ClientHelper;
 import org.briarproject.bramble.api.contact.ContactManager;
 import org.briarproject.bramble.api.data.MetadataEncoder;
 import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.sync.ClientVersioningManager;
 import org.briarproject.bramble.api.sync.ValidationManager;
 import org.briarproject.bramble.api.system.Clock;
 import org.briarproject.briar.api.introduction.IntroductionManager;
@@ -47,12 +48,16 @@ public class IntroductionModule {
 			LifecycleManager lifecycleManager, ContactManager contactManager,
 			ValidationManager validationManager,
 			ConversationManager conversationManager,
+			ClientVersioningManager clientVersioningManager,
 			IntroductionManagerImpl introductionManager) {
 		lifecycleManager.registerClient(introductionManager);
 		contactManager.registerContactHook(introductionManager);
 		validationManager.registerIncomingMessageHook(CLIENT_ID,
 				CLIENT_VERSION, introductionManager);
 		conversationManager.registerConversationClient(introductionManager);
+		clientVersioningManager.registerClient(CLIENT_ID, CLIENT_VERSION);
+		clientVersioningManager.registerClientVersioningHook(CLIENT_ID,
+				CLIENT_VERSION, introductionManager);
 		return introductionManager;
 	}