diff --git a/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTest.java
index 7e180253d7459816c221dd4c2082811fad38628c..56502a64b0e64bced615b840e75a6e75f0f53fa2 100644
--- a/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTest.java
@@ -19,7 +19,7 @@ import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.identity.LocalAuthor;
 import org.briarproject.api.introduction.IntroductionManager;
 import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.lifecycle.LifecycleManager;
 import org.briarproject.api.properties.TransportProperties;
 import org.briarproject.api.properties.TransportPropertyManager;
diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index 4ffddcb7941655e914435692aac6c3b0867a5011..10b50aa4d7fb22e251f1d3a2b0ea5a02744518e1 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -141,11 +141,11 @@
 
 		<activity
 			android:name=".android.forum.ShareForumActivity"
-			android:label="@string/app_name"
-			android:parentActivityName=".android.NavDrawerActivity">
+			android:label="@string/forums_share_toolbar_header"
+			android:parentActivityName=".android.forum.ForumActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.NavDrawerActivity"
+				android:value=".android.forum.ForumActivity"
 				/>
 		</activity>
 
diff --git a/briar-android/res/menu/forum_share_actions.xml b/briar-android/res/menu/forum_share_actions.xml
index f128fd17c56f6991fda5bf0766cf9582aae25fc5..a3d6c154774c13dfe9d370c6eec048fc38dcb7b0 100644
--- a/briar-android/res/menu/forum_share_actions.xml
+++ b/briar-android/res/menu/forum_share_actions.xml
@@ -6,7 +6,7 @@
 	<item
 		android:id="@+id/action_share_forum"
 		android:icon="@drawable/ic_check_white"
-		android:title="@string/forum_share_with_some"
+		android:title="@string/forum_share_action"
 		app:showAsAction="always"/>
 
 </menu>
\ No newline at end of file
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 9934c12dc0be8d4636b0f6f14045d77e3895bc2f..4bbeca7689bdad9ebc71ac9792eb23b49b6f726e 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -85,8 +85,7 @@
 	<string name="choose_forum_name">Choose a name for your forum:</string>
 	<string name="create_forum_button">Create Forum</string>
 	<string name="forum_created_toast">Forum created</string>
-	<string name="forum_share_with_all">Share this forum with all contacts</string>
-	<string name="forum_share_with_some">Share this forum with chosen contacts</string>
+	<string name="forum_share_action">Share this forum with chosen contacts</string>
 	<string name="forum_share_button">Share Forum</string>
 	<string name="forum_compose_post">New Forum Post</string>
 	<string name="from">From:</string>
@@ -204,6 +203,7 @@
 	<string name="settings_toolbar_header">Settings</string>
 	<string name="contacts_toolbar_header">Contacts</string>
 	<string name="forums_toolbar_header">Forums</string>
+	<string name="forums_share_toolbar_header">Choose Contacts</string>
 	<!-- Progress titles -->
 	<string name="progress_title_logout">Signing out of Briar..</string>
 	<string name="progress_title_please_wait">Please wait..</string>
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
index c027bf4d639231216707bbd6905790b4da055d54..213e412b520aeea2edb35c6c4608bcd72d2ef148 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
@@ -51,7 +51,7 @@ import org.briarproject.api.introduction.IntroductionManager;
 import org.briarproject.api.introduction.IntroductionMessage;
 import org.briarproject.api.introduction.IntroductionRequest;
 import org.briarproject.api.introduction.IntroductionResponse;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.messaging.MessagingManager;
 import org.briarproject.api.messaging.PrivateMessage;
 import org.briarproject.api.messaging.PrivateMessageFactory;
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
index ea67900a411db5ff590b24fcaea2065becfdc6c8..91a006b9f53327f6534bfb30affd395f8599f4ef 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java
@@ -14,7 +14,7 @@ import android.widget.TextView;
 
 import org.briarproject.R;
 import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.messaging.PrivateMessageHeader;
 import org.briarproject.util.StringUtils;
 
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
index 6ce64a2a1bb1556450bf83ea2d55d37fe0a37e4d..67c6233b23bb5142856b18db2ced76af27295442 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
@@ -171,7 +171,7 @@ implements EventListener, OnItemClickListener {
 		runOnDbThread(new Runnable() {
 			public void run() {
 				try {
-					forumSharingManager.addForum(f);
+					forumManager.addForum(f);
 					forumSharingManager.setSharedWith(f.getId(), shared);
 				} catch (DbException e) {
 					if (LOG.isLoggable(WARNING))
diff --git a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java b/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
index 19a555c98eb21e2829b4e26ebd05a72a0f2da74c..a35834c93aead75bb04298bae7c94ac1efbfbaee 100644
--- a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
@@ -19,7 +19,7 @@ import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.forum.Forum;
-import org.briarproject.api.forum.ForumSharingManager;
+import org.briarproject.api.forum.ForumManager;
 import org.briarproject.util.StringUtils;
 
 import java.util.logging.Logger;
@@ -47,7 +47,7 @@ public class CreateForumActivity extends BriarActivity
 
 	// Fields that are accessed from background threads must be volatile
 	@Inject
-	protected volatile ForumSharingManager forumSharingManager;
+	protected volatile ForumManager forumManager;
 
 	@Override
 	public void onCreate(Bundle state) {
@@ -126,8 +126,8 @@ public class CreateForumActivity extends BriarActivity
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					Forum f = forumSharingManager.createForum(name);
-					forumSharingManager.addForum(f);
+					Forum f = forumManager.createForum(name);
+					forumManager.addForum(f);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Storing forum took " + duration + " ms");
diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
index cd44592df40e9cea57de3b5d6313fd7f1d449967..6dd00d231e76f8f23c4f845549b68f2c3feba0b1 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
@@ -68,7 +68,7 @@ public class ForumActivity extends BriarActivity implements EventListener,
 			Logger.getLogger(ForumActivity.class.getName());
 
 	@Inject protected AndroidNotificationManager notificationManager;
-	private Map<MessageId, byte[]> bodyCache = new HashMap<MessageId, byte[]>();
+	private Map<MessageId, byte[]> bodyCache = new HashMap<>();
 	private TextView empty = null;
 	private ForumAdapter adapter = null;
 	private ListView list = null;
@@ -158,7 +158,6 @@ public class ForumActivity extends BriarActivity implements EventListener,
 				Intent i2 = new Intent(this, ShareForumActivity.class);
 				i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
 				i2.putExtra(GROUP_ID, groupId.getBytes());
-				i2.putExtra(FORUM_NAME, forum.getName());
 				ActivityOptionsCompat options = ActivityOptionsCompat
 						.makeCustomAnimation(this, android.R.anim.slide_in_left,
 								android.R.anim.slide_out_right);
@@ -302,7 +301,7 @@ public class ForumActivity extends BriarActivity implements EventListener,
 	}
 
 	private void markPostsRead() {
-		List<MessageId> unread = new ArrayList<MessageId>();
+		List<MessageId> unread = new ArrayList<>();
 		int count = adapter.getCount();
 		for (int i = 0; i < count; i++) {
 			ForumPostHeader h = adapter.getItem(i).getHeader();
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
index c31fde43902b85b65b27c547f4f6203cff4fd9f3..dea9d1fe47d4243b318e035ad2c309c03aab0cd8 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
@@ -401,7 +401,7 @@ public class ForumListFragment extends BaseEventFragment implements
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					forumSharingManager.removeForum(f);
+					forumManager.removeForum(f);
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Removing forum took " + duration + " ms");
diff --git a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java b/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
index e2d4926b3b41c15816664fb9581fd810be386014..cccecbc7ae4c97a293edb50ab1d908f18870d8d8 100644
--- a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
@@ -33,7 +33,6 @@ import javax.inject.Inject;
 
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.forum.ForumActivity.FORUM_NAME;
 
 public class ShareForumActivity extends BriarActivity implements
 		BaseContactListAdapter.OnItemClickListener {
@@ -59,9 +58,6 @@ public class ShareForumActivity extends BriarActivity implements
 		byte[] b = i.getByteArrayExtra(GROUP_ID);
 		if (b == null) throw new IllegalStateException();
 		groupId = new GroupId(b);
-		String forumName = i.getStringExtra(FORUM_NAME);
-		if (forumName == null) throw new IllegalStateException();
-		setTitle(forumName);
 
 		adapter = new ContactSelectorAdapter(this, this);
 		BriarRecyclerView list =
@@ -112,11 +108,9 @@ public class ShareForumActivity extends BriarActivity implements
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					List<ContactListItem> contacts =
-							new ArrayList<ContactListItem>();
-					Collection<ContactId> selectedContacts =
-							new HashSet<ContactId>(
-									forumSharingManager.getSharedWith(groupId));
+					List<ContactListItem> contacts = new ArrayList<>();
+					Collection<ContactId> selectedContacts = new HashSet<>(
+							forumSharingManager.getSharedWith(groupId));
 
 					for (Contact c : contactManager.getActiveContacts()) {
 						LocalAuthor localAuthor = identityManager
diff --git a/briar-api/src/org/briarproject/api/ProtocolEngine.java b/briar-api/src/org/briarproject/api/clients/ProtocolEngine.java
similarity index 97%
rename from briar-api/src/org/briarproject/api/ProtocolEngine.java
rename to briar-api/src/org/briarproject/api/clients/ProtocolEngine.java
index 61833f6574ec628b33b9195adc4e17c49206840d..1958deaf0d6fcf02a1d29eef32afae69e037d3e3 100644
--- a/briar-api/src/org/briarproject/api/ProtocolEngine.java
+++ b/briar-api/src/org/briarproject/api/clients/ProtocolEngine.java
@@ -1,4 +1,4 @@
-package org.briarproject.api;
+package org.briarproject.api.clients;
 
 import org.briarproject.api.event.Event;
 
diff --git a/briar-api/src/org/briarproject/api/introduction/SessionId.java b/briar-api/src/org/briarproject/api/clients/SessionId.java
similarity index 65%
rename from briar-api/src/org/briarproject/api/introduction/SessionId.java
rename to briar-api/src/org/briarproject/api/clients/SessionId.java
index d68bf9e0301ecf48ca1e61ab58a2772a7458846a..c9730730bf52cfdc8be7a80f95daba27c1143584 100644
--- a/briar-api/src/org/briarproject/api/introduction/SessionId.java
+++ b/briar-api/src/org/briarproject/api/clients/SessionId.java
@@ -1,10 +1,10 @@
-package org.briarproject.api.introduction;
+package org.briarproject.api.clients;
 
 import org.briarproject.api.sync.MessageId;
 
 /**
- * Type-safe wrapper for a byte array that uniquely identifies an
- * introduction session.
+ * Type-safe wrapper for a byte array
+ * that uniquely identifies a protocol session.
  */
 public class SessionId extends MessageId {
 
diff --git a/briar-api/src/org/briarproject/api/event/IntroductionAbortedEvent.java b/briar-api/src/org/briarproject/api/event/IntroductionAbortedEvent.java
index 258d588e284a05c980aa7c193ff73f8993fe7305..b5d821655a4ec8c7103281ef360f3ad23dd72671 100644
--- a/briar-api/src/org/briarproject/api/event/IntroductionAbortedEvent.java
+++ b/briar-api/src/org/briarproject/api/event/IntroductionAbortedEvent.java
@@ -1,7 +1,7 @@
 package org.briarproject.api.event;
 
 import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 
 public class IntroductionAbortedEvent extends Event {
 
diff --git a/briar-api/src/org/briarproject/api/forum/ForumManager.java b/briar-api/src/org/briarproject/api/forum/ForumManager.java
index 1d32544654c799eed46be9320f34749665d1889c..bd5657b01bb8f6d262c036ffa676ce6f919c6f83 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumManager.java
+++ b/briar-api/src/org/briarproject/api/forum/ForumManager.java
@@ -1,6 +1,7 @@
 package org.briarproject.api.forum;
 
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.db.Transaction;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageId;
@@ -12,6 +13,18 @@ public interface ForumManager {
 	/** Returns the unique ID of the forum client. */
 	ClientId getClientId();
 
+	/** Creates a forum with the given name. */
+	Forum createForum(String name);
+
+	/** Creates a forum with the given name and salt. */
+	Forum createForum(String name, byte[] salt);
+
+	/** Subscribes to a forum. */
+	void addForum(Forum f) throws DbException;
+
+	/** Unsubscribes from a forum. */
+	void removeForum(Forum f) throws DbException;
+
 	/** Stores a local forum post. */
 	void addLocalPost(ForumPost p) throws DbException;
 
@@ -29,4 +42,11 @@ public interface ForumManager {
 
 	/** Marks a forum post as read or unread. */
 	void setReadFlag(MessageId m, boolean read) throws DbException;
+
+	/** Registers a hook to be called whenever a forum is removed. */
+	void registerRemoveForumHook(RemoveForumHook hook);
+
+	interface RemoveForumHook {
+		void removingForum(Transaction txn, Forum f) throws DbException;
+	}
 }
diff --git a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java b/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
index 91b806e0e828d4d228c17e348ce830c5260fbc78..e3e3b1191cca67bad368ab612018add384775ff5 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
+++ b/briar-api/src/org/briarproject/api/forum/ForumSharingManager.java
@@ -13,15 +13,6 @@ public interface ForumSharingManager {
 	/** Returns the unique ID of the forum sharing client. */
 	ClientId getClientId();
 
-	/** Creates a forum with the given name. */
-	Forum createForum(String name);
-
-	/** Subscribes to a forum. */
-	void addForum(Forum f) throws DbException;
-
-	/** Unsubscribes from a forum. */
-	void removeForum(Forum f) throws DbException;
-
 	/** Returns all forums to which the user could subscribe. */
 	Collection<Forum> getAvailableForums() throws DbException;
 
@@ -38,6 +29,4 @@ public interface ForumSharingManager {
 	void setSharedWith(GroupId g, Collection<ContactId> shared)
 			throws DbException;
 
-	/** Shares a forum with all current and future contacts. */
-	void setSharedWithAll(GroupId g) throws DbException;
 }
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java b/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java
index f02b9b635cc3a40cd655074f1e3c8e8ff1bdb447..9819c875801a56992725eff17a80bb1f3598b711 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java
+++ b/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java
@@ -1,15 +1,11 @@
 package org.briarproject.api.introduction;
 
 import org.briarproject.api.FormatException;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
-import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.db.DbException;
-import org.briarproject.api.db.Transaction;
 import org.briarproject.api.sync.ClientId;
-import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
 
 import java.util.Collection;
 
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionMessage.java b/briar-api/src/org/briarproject/api/introduction/IntroductionMessage.java
index 8582f36c6ddc0303fcd6e23b05205aae7f6b6518..8c9de76dfaf8eea628c8bd67946429acc1858918 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionMessage.java
+++ b/briar-api/src/org/briarproject/api/introduction/IntroductionMessage.java
@@ -1,5 +1,6 @@
 package org.briarproject.api.introduction;
 
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.sync.MessageId;
 
 import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java b/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java
index dc674f77b9f950bad7128ff1db95080cb53eb385..912f8a3fba8ff0507e9618a55fbfe64cc07ab519 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java
+++ b/briar-api/src/org/briarproject/api/introduction/IntroductionRequest.java
@@ -1,5 +1,6 @@
 package org.briarproject.api.introduction;
 
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.sync.MessageId;
 
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionResponse.java b/briar-api/src/org/briarproject/api/introduction/IntroductionResponse.java
index 956131ccb54a289841a33f2c488cad061c5fb965..be4cb57072cabc32dcb2cfb7037c3de164a57a7a 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionResponse.java
+++ b/briar-api/src/org/briarproject/api/introduction/IntroductionResponse.java
@@ -1,5 +1,6 @@
 package org.briarproject.api.introduction;
 
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.sync.MessageId;
 
diff --git a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
index 8d319ca4ad11a4ef6e66ebc431367829a4c3795d..63d4a2db832a983d99f774c43edf5127d161603c 100644
--- a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
+++ b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
@@ -17,10 +17,12 @@ import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.identity.LocalAuthor;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
+import org.briarproject.api.sync.GroupFactory;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.util.StringUtils;
 
+import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -29,9 +31,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.inject.Inject;
 
+import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
+import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
 import static org.briarproject.api.identity.Author.Status.ANONYMOUS;
 import static org.briarproject.api.identity.Author.Status.UNKNOWN;
 import static org.briarproject.api.identity.Author.Status.VERIFIED;
@@ -44,11 +49,19 @@ class ForumManagerImpl implements ForumManager {
 
 	private final DatabaseComponent db;
 	private final ClientHelper clientHelper;
+	private final GroupFactory groupFactory;
+	private final SecureRandom random;
+	private final List<RemoveForumHook> removeHooks;
 
 	@Inject
-	ForumManagerImpl(DatabaseComponent db, ClientHelper clientHelper) {
+	ForumManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
+			GroupFactory groupFactory, SecureRandom random) {
+
 		this.db = db;
 		this.clientHelper = clientHelper;
+		this.groupFactory = groupFactory;
+		this.random = random;
+		removeHooks = new CopyOnWriteArrayList<RemoveForumHook>();
 	}
 
 	@Override
@@ -56,6 +69,53 @@ class ForumManagerImpl implements ForumManager {
 		return CLIENT_ID;
 	}
 
+	@Override
+	public Forum createForum(String name) {
+		int length = StringUtils.toUtf8(name).length;
+		if (length == 0) throw new IllegalArgumentException();
+		if (length > MAX_FORUM_NAME_LENGTH)
+			throw new IllegalArgumentException();
+		byte[] salt = new byte[FORUM_SALT_LENGTH];
+		random.nextBytes(salt);
+		return createForum(name, salt);
+	}
+
+	@Override
+	public Forum createForum(String name, byte[] salt) {
+		try {
+			BdfList forum = BdfList.of(name, salt);
+			byte[] descriptor = clientHelper.toByteArray(forum);
+			Group g = groupFactory.createGroup(getClientId(), descriptor);
+			return new Forum(g, name, salt);
+		} catch (FormatException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	@Override
+	public void addForum(Forum f) throws DbException {
+		Transaction txn = db.startTransaction(false);
+		try {
+			db.addGroup(txn, f.getGroup());
+			txn.setComplete();
+		} finally {
+			db.endTransaction(txn);
+		}
+	}
+
+	@Override
+	public void removeForum(Forum f) throws DbException {
+		Transaction txn = db.startTransaction(false);
+		try {
+			for (RemoveForumHook hook : removeHooks)
+				hook.removingForum(txn, f);
+			db.removeGroup(txn, f.getGroup());
+			txn.setComplete();
+		} finally {
+			db.endTransaction(txn);
+		}
+	}
+
 	@Override
 	public void addLocalPost(ForumPost p) throws DbException {
 		try {
@@ -190,10 +250,16 @@ class ForumManagerImpl implements ForumManager {
 		}
 	}
 
+	@Override
+	public void registerRemoveForumHook(RemoveForumHook hook) {
+		removeHooks.add(hook);
+	}
+
 	private Forum parseForum(Group g) throws FormatException {
 		byte[] descriptor = g.getDescriptor();
 		// Name, salt
 		BdfList forum = clientHelper.toList(descriptor, 0, descriptor.length);
 		return new Forum(g, forum.getString(0), forum.getRaw(1));
 	}
+
 }
diff --git a/briar-core/src/org/briarproject/forum/ForumModule.java b/briar-core/src/org/briarproject/forum/ForumModule.java
index f801e2770cf200a7fb0f1997d4dea5470a2cdec0..ac0ff20616b31e0c7de10f3eb345fb7350e6046d 100644
--- a/briar-core/src/org/briarproject/forum/ForumModule.java
+++ b/briar-core/src/org/briarproject/forum/ForumModule.java
@@ -10,9 +10,12 @@ import org.briarproject.api.forum.ForumPostFactory;
 import org.briarproject.api.forum.ForumSharingManager;
 import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.sync.GroupFactory;
 import org.briarproject.api.sync.ValidationManager;
 import org.briarproject.api.system.Clock;
 
+import java.security.SecureRandom;
+
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
@@ -34,8 +37,9 @@ public class ForumModule {
 	@Provides
 	@Singleton
 	ForumManager provideForumManager(DatabaseComponent db,
-			ClientHelper clientHelper) {
-		return new ForumManagerImpl(db, clientHelper);
+			ClientHelper clientHelper,
+			GroupFactory groupFactory, SecureRandom random) {
+		return new ForumManagerImpl(db, clientHelper, groupFactory, random);
 	}
 
 	@Provides
@@ -75,12 +79,14 @@ public class ForumModule {
 			LifecycleManager lifecycleManager,
 			ContactManager contactManager,
 			ValidationManager validationManager,
+			ForumManager forumManager,
 			ForumSharingManagerImpl forumSharingManager) {
 		lifecycleManager.registerClient(forumSharingManager);
 		contactManager.registerAddContactHook(forumSharingManager);
 		contactManager.registerRemoveContactHook(forumSharingManager);
 		validationManager.registerIncomingMessageHook(
 				ForumSharingManagerImpl.CLIENT_ID, forumSharingManager);
+		forumManager.registerRemoveForumHook(forumSharingManager);
 		return forumSharingManager;
 	}
 }
diff --git a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
index b975a4537790396f2e5ad6a5dc5b3d074d9a5f97..62501e8e50ccd007c3d5bd9809fb28e882491999 100644
--- a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
@@ -19,7 +19,6 @@ import org.briarproject.api.forum.ForumManager;
 import org.briarproject.api.forum.ForumSharingManager;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
-import org.briarproject.api.sync.GroupFactory;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.MessageId;
@@ -28,7 +27,6 @@ import org.briarproject.api.system.Clock;
 import org.briarproject.util.StringUtils;
 
 import java.io.IOException;
-import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -40,12 +38,12 @@ import java.util.Set;
 
 import javax.inject.Inject;
 
-import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
-import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
 import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+import static org.briarproject.api.forum.ForumManager.RemoveForumHook;
 
 class ForumSharingManagerImpl implements ForumSharingManager, Client,
-		AddContactHook, RemoveContactHook, IncomingMessageHook {
+		AddContactHook, RemoveContactHook, IncomingMessageHook,
+		RemoveForumHook {
 
 	static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
 			"cd11a5d04dccd9e2931d6fc3df456313"
@@ -54,30 +52,23 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
 	private final DatabaseComponent db;
 	private final ForumManager forumManager;
 	private final ClientHelper clientHelper;
-	private final GroupFactory groupFactory;
 	private final PrivateGroupFactory privateGroupFactory;
-	private final SecureRandom random;
 	private final Clock clock;
-	private final Group localGroup;
 
 	@Inject
 	ForumSharingManagerImpl(DatabaseComponent db, ForumManager forumManager,
-			ClientHelper clientHelper, GroupFactory groupFactory,
-			PrivateGroupFactory privateGroupFactory, SecureRandom random,
+			ClientHelper clientHelper, PrivateGroupFactory privateGroupFactory,
 			Clock clock) {
+
 		this.db = db;
 		this.forumManager = forumManager;
 		this.clientHelper = clientHelper;
-		this.groupFactory = groupFactory;
 		this.privateGroupFactory = privateGroupFactory;
-		this.random = random;
 		this.clock = clock;
-		localGroup = privateGroupFactory.createLocalGroup(CLIENT_ID);
 	}
 
 	@Override
 	public void createLocalState(Transaction txn) throws DbException {
-		db.addGroup(txn, localGroup);
 		// Ensure we've set things up for any pre-existing contacts
 		for (Contact c : db.getContacts(txn)) addingContact(txn, c);
 	}
@@ -96,9 +87,6 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
 			BdfDictionary meta = new BdfDictionary();
 			meta.put("contactId", c.getId().getInt());
 			clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
-			// Share any forums that are shared with all contacts
-			List<Forum> shared = getForumsSharedWithAllContacts(txn);
-			storeMessage(txn, g.getId(), shared, 0);
 		} catch (FormatException e) {
 			throw new DbException(e);
 		}
@@ -126,40 +114,10 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
 	}
 
 	@Override
-	public Forum createForum(String name) {
-		int length = StringUtils.toUtf8(name).length;
-		if (length == 0) throw new IllegalArgumentException();
-		if (length > MAX_FORUM_NAME_LENGTH)
-			throw new IllegalArgumentException();
-		byte[] salt = new byte[FORUM_SALT_LENGTH];
-		random.nextBytes(salt);
-		return createForum(name, salt);
-	}
-
-	@Override
-	public void addForum(Forum f) throws DbException {
-		Transaction txn = db.startTransaction(false);
+	public void removingForum(Transaction txn, Forum f) throws DbException {
 		try {
-			db.addGroup(txn, f.getGroup());
-			txn.setComplete();
-		} finally {
-			db.endTransaction(txn);
-		}
-	}
-
-	@Override
-	public void removeForum(Forum f) throws DbException {
-		try {
-			// Update the list shared with each contact
-			Transaction txn = db.startTransaction(false);
-			try {
-				for (Contact c : db.getContacts(txn))
-					removeFromList(txn, getContactGroup(c).getId(), f);
-				db.removeGroup(txn, f.getGroup());
-				txn.setComplete();
-			} finally {
-				db.endTransaction(txn);
-			}
+			for (Contact c : db.getContacts(txn))
+				removeFromList(txn, getContactGroup(c).getId(), f);
 		} catch (IOException e) {
 			throw new DbException(e);
 		}
@@ -247,8 +205,6 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
 			try {
 				// Retrieve the forum
 				Forum f = parseForum(db.getGroup(txn, g));
-				// Remove the forum from the list shared with all contacts
-				removeFromList(txn, localGroup.getId(), f);
 				// Update the list shared with each contact
 				shared = new HashSet<ContactId>(shared);
 				for (Contact c : db.getContacts(txn)) {
@@ -272,46 +228,10 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
 		}
 	}
 
-	@Override
-	public void setSharedWithAll(GroupId g) throws DbException {
-		try {
-			Transaction txn = db.startTransaction(false);
-			try {
-				// Retrieve the forum
-				Forum f = parseForum(db.getGroup(txn, g));
-				// Add the forum to the list shared with all contacts
-				addToList(txn, localGroup.getId(), f);
-				// Add the forum to the list shared with each contact
-				for (Contact c : db.getContacts(txn)) {
-					Group cg = getContactGroup(c);
-					if (addToList(txn, cg.getId(), f)) {
-						if (listContains(txn, cg.getId(), g, false))
-							db.setVisibleToContact(txn, c.getId(), g, true);
-					}
-				}
-				txn.setComplete();
-			} finally {
-				db.endTransaction(txn);
-			}
-		} catch (FormatException e) {
-			throw new DbException(e);
-		}
-	}
-
 	private Group getContactGroup(Contact c) {
 		return privateGroupFactory.createPrivateGroup(CLIENT_ID, c);
 	}
 
-	private List<Forum> getForumsSharedWithAllContacts(Transaction txn)
-			throws DbException, FormatException {
-		// Find the latest update in the local group
-		LatestUpdate latest = findLatest(txn, localGroup.getId(), true);
-		if (latest == null) return Collections.emptyList();
-		// Retrieve and parse the latest update
-		BdfList message = clientHelper.getMessageAsList(txn, latest.messageId);
-		return parseForumList(message);
-	}
-
 	private LatestUpdate findLatest(Transaction txn, GroupId g, boolean local)
 			throws DbException, FormatException {
 		LatestUpdate latest = null;
@@ -334,7 +254,8 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
 		for (int i = 0; i < forumList.size(); i++) {
 			// Name, salt
 			BdfList forum = forumList.getList(i);
-			forums.add(createForum(forum.getString(0), forum.getRaw(1)));
+			forums.add(forumManager
+					.createForum(forum.getString(0), forum.getRaw(1)));
 		}
 		return forums;
 	}
@@ -400,18 +321,6 @@ class ForumSharingManagerImpl implements ForumSharingManager, Client,
 		}
 	}
 
-	private Forum createForum(String name, byte[] salt) {
-		try {
-			BdfList forum = BdfList.of(name, salt);
-			byte[] descriptor = clientHelper.toByteArray(forum);
-			Group g = groupFactory.createGroup(forumManager.getClientId(),
-					descriptor);
-			return new Forum(g, name, salt);
-		} catch (FormatException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
 	private Forum parseForum(Group g) throws FormatException {
 		byte[] descriptor = g.getDescriptor();
 		// Name, salt
diff --git a/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java b/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java
index 3f29b00b0019709302a514e494cec4391f9769fc..50af8e754ad010b7d69a9b577afeeeefc8518b56 100644
--- a/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java
+++ b/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java
@@ -1,7 +1,7 @@
 package org.briarproject.introduction;
 
 import org.briarproject.api.FormatException;
-import org.briarproject.api.ProtocolEngine;
+import org.briarproject.api.clients.ProtocolEngine;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.event.Event;
@@ -11,7 +11,7 @@ import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.introduction.IntroduceeAction;
 import org.briarproject.api.introduction.IntroduceeProtocolState;
 import org.briarproject.api.introduction.IntroductionRequest;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.sync.MessageId;
 
 import java.util.ArrayList;
diff --git a/briar-core/src/org/briarproject/introduction/IntroducerEngine.java b/briar-core/src/org/briarproject/introduction/IntroducerEngine.java
index e0e1449f653187c520d7e9b2b01c22c6a5031467..a431fd7e46d9040696c97abd99b815341d03ee98 100644
--- a/briar-core/src/org/briarproject/introduction/IntroducerEngine.java
+++ b/briar-core/src/org/briarproject/introduction/IntroducerEngine.java
@@ -1,7 +1,7 @@
 package org.briarproject.introduction;
 
 import org.briarproject.api.FormatException;
-import org.briarproject.api.ProtocolEngine;
+import org.briarproject.api.clients.ProtocolEngine;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.event.Event;
@@ -11,7 +11,7 @@ import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.introduction.IntroducerAction;
 import org.briarproject.api.introduction.IntroducerProtocolState;
 import org.briarproject.api.introduction.IntroductionResponse;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.sync.MessageId;
 
 import java.util.ArrayList;
diff --git a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java
index 0d0c3102bd609708baec13d068ff3324bd328023..97740b10acb6ab0c6b9705669c5215dd6cee4ed1 100644
--- a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java
+++ b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java
@@ -20,7 +20,7 @@ import org.briarproject.api.introduction.IntroductionManager;
 import org.briarproject.api.introduction.IntroductionMessage;
 import org.briarproject.api.introduction.IntroductionRequest;
 import org.briarproject.api.introduction.IntroductionResponse;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
diff --git a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java b/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
index 0307ccfd9f531c731405d1d5676e0851b645aea0..3babe437b4b23e70937b98169633852fd8fa90d2 100644
--- a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
+++ b/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
@@ -5,7 +5,7 @@ import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.system.Clock;
diff --git a/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java b/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java
index a4d986d2570d719e60ace1346d15c8068706edcb..c6a0afa45cff9fd1d12ab667010543649bba123d 100644
--- a/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java
+++ b/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java
@@ -19,7 +19,7 @@ import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.introduction.IntroduceeProtocolState;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.properties.TransportPropertyManager;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
diff --git a/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java b/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java
index f6b5e90e88d5f375bc7a325722873ef9abf2c1b9..fac0b0b32dbf483210e28468518613084069c53d 100644
--- a/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/introduction/IntroductionManagerImplTest.java
@@ -18,7 +18,7 @@ import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.Transaction;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.AuthorId;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
diff --git a/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java b/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java
index dbacbc8f740273e4f6bf1988406ab0cccf00eee2..d7d4112946dcce2965d76a7bcf29519630020e6e 100644
--- a/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java
+++ b/briar-tests/src/org/briarproject/introduction/IntroductionValidatorTest.java
@@ -9,7 +9,7 @@ import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfEntry;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
diff --git a/briar-tests/src/org/briarproject/introduction/MessageSenderTest.java b/briar-tests/src/org/briarproject/introduction/MessageSenderTest.java
index 1c9d3b82c72e5de6d9b3a84db37871be524f4e7e..8809fd0a1a5fdd6cbbcf95a9a84f2cbfbb83ca09 100644
--- a/briar-tests/src/org/briarproject/introduction/MessageSenderTest.java
+++ b/briar-tests/src/org/briarproject/introduction/MessageSenderTest.java
@@ -14,7 +14,7 @@ import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.Metadata;
 import org.briarproject.api.db.Transaction;
-import org.briarproject.api.introduction.SessionId;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;