diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java
index 2f4a21800d3e160ab3109968da555e788f43ab15..e2732145a8420d6b3265c2388d65fb256a8c1279 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.identity.Author;
 import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.lifecycle.LifecycleManager;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
@@ -113,6 +114,16 @@ public interface ContactManager {
 	boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
 			throws DbException;
 
+	/**
+	 * Returns the {@link AuthorInfo} for the given author.
+	 */
+	AuthorInfo getAuthorInfo(AuthorId a) throws DbException;
+
+	/**
+	 * Returns the {@link AuthorInfo} for the given author.
+	 */
+	AuthorInfo getAuthorInfo(Transaction txn, AuthorId a) throws DbException;
+
 	interface ContactHook {
 
 		void addingContact(Transaction txn, Contact c) throws DbException;
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java
index 0df402c280455267ea84e667da2ae51c28a8f13e..4d2d030e57fd037724b6c023808f6e457235bbbc 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/Author.java
@@ -16,10 +16,6 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
 @NotNullByDefault
 public class Author implements Nameable {
 
-	public enum Status {
-		NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
-	}
-
 	/**
 	 * The current version of the author structure.
 	 */
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorInfo.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c90d9aff05e6003c2a30b87d0a1bac37c6ab6f8
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/AuthorInfo.java
@@ -0,0 +1,52 @@
+package org.briarproject.bramble.api.identity;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class AuthorInfo {
+
+	public enum Status {
+		NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
+	}
+
+	private final Status status;
+	@Nullable
+	private final String alias;
+
+	public AuthorInfo(Status status, @Nullable String alias) {
+		this.status = status;
+		this.alias = alias;
+	}
+
+	public AuthorInfo(Status status) {
+		this(status, null);
+	}
+
+	public Status getStatus() {
+		return status;
+	}
+
+	@Nullable
+	public String getAlias() {
+		return alias;
+	}
+
+	@Override
+	public int hashCode() {
+		int hashCode = status.ordinal();
+		if (alias != null) hashCode += alias.hashCode();
+		return hashCode;
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (!(o instanceof AuthorInfo)) return false;
+		AuthorInfo info = (AuthorInfo) o;
+		return status == info.status &&
+				(alias == null ? info.alias == null : alias.equals(info.alias));
+	}
+}
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java
index 8160eb06d3bd5dc93ee8babad28436962a50b078..c3bd5fcf26697adfffb3f7e049ff2bc246cfc1f4 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/identity/IdentityManager.java
@@ -3,7 +3,6 @@ package org.briarproject.bramble.api.identity;
 import org.briarproject.bramble.api.crypto.CryptoExecutor;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
-import org.briarproject.bramble.api.identity.Author.Status;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 @NotNullByDefault
@@ -37,14 +36,4 @@ public interface IdentityManager {
 	 */
 	LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
 
-	/**
-	 * Returns the {@link Status} of the given author.
-	 */
-	Status getAuthorStatus(AuthorId a) throws DbException;
-
-	/**
-	 * Returns the {@link Status} of the given author.
-	 */
-	Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
-
 }
diff --git a/bramble-api/src/test/java/org/briarproject/bramble/api/identity/AuthorInfoTest.java b/bramble-api/src/test/java/org/briarproject/bramble/api/identity/AuthorInfoTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c059c84ec47ad08ffbc3c545488a92f7df1ee02
--- /dev/null
+++ b/bramble-api/src/test/java/org/briarproject/bramble/api/identity/AuthorInfoTest.java
@@ -0,0 +1,42 @@
+package org.briarproject.bramble.api.identity;
+
+import org.briarproject.bramble.test.BrambleTestCase;
+import org.junit.Test;
+
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+public class AuthorInfoTest extends BrambleTestCase {
+
+	@Test
+	public void testEquals() {
+		assertEquals(
+				new AuthorInfo(NONE),
+				new AuthorInfo(NONE, null)
+		);
+		assertEquals(
+				new AuthorInfo(NONE, "test"),
+				new AuthorInfo(NONE, "test")
+		);
+
+		assertNotEquals(
+				new AuthorInfo(NONE),
+				new AuthorInfo(VERIFIED)
+		);
+		assertNotEquals(
+				new AuthorInfo(NONE, "test"),
+				new AuthorInfo(NONE)
+		);
+		assertNotEquals(
+				new AuthorInfo(NONE),
+				new AuthorInfo(NONE, "test")
+		);
+		assertNotEquals(
+				new AuthorInfo(NONE, "a"),
+				new AuthorInfo(NONE, "b")
+		);
+	}
+
+}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java
index a6397f659924a1fdabfe4511808bb9163ae6ed10..71a63c9b57f32dc3ba47c6e90b8c3da8e1b62b03 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java
@@ -10,6 +10,9 @@ import org.briarproject.bramble.api.db.NoSuchContactException;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.identity.Author;
 import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.AuthorInfo;
+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.transport.KeyManager;
 
@@ -23,6 +26,10 @@ import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
 import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
 import static org.briarproject.bramble.util.StringUtils.toUtf8;
 
 @ThreadSafe
@@ -31,12 +38,15 @@ class ContactManagerImpl implements ContactManager {
 
 	private final DatabaseComponent db;
 	private final KeyManager keyManager;
+	private final IdentityManager identityManager;
 	private final List<ContactHook> hooks;
 
 	@Inject
-	ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
+	ContactManagerImpl(DatabaseComponent db, KeyManager keyManager,
+			IdentityManager identityManager) {
 		this.db = db;
 		this.keyManager = keyManager;
+		this.identityManager = identityManager;
 		hooks = new CopyOnWriteArrayList<>();
 	}
 
@@ -191,4 +201,23 @@ class ContactManagerImpl implements ContactManager {
 		db.removeContact(txn, c);
 	}
 
+	@Override
+	public AuthorInfo getAuthorInfo(AuthorId a) throws DbException {
+		return db.transactionWithResult(true, txn -> getAuthorInfo(txn, a));
+	}
+
+	@Override
+	public AuthorInfo getAuthorInfo(Transaction txn, AuthorId authorId)
+			throws DbException {
+		LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
+		if (localAuthor.getId().equals(authorId))
+			return new AuthorInfo(OURSELVES);
+		Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
+		if (contacts.isEmpty()) return new AuthorInfo(UNKNOWN);
+		if (contacts.size() > 1) throw new AssertionError();
+		Contact c = contacts.iterator().next();
+		if (c.isVerified()) return new AuthorInfo(VERIFIED, c.getAlias());
+		else return new AuthorInfo(UNVERIFIED, c.getAlias());
+	}
+
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java
index 44bf94550620c9bfcf3ce9a2772d4e511c4d6857..783ed336a42d083c5fb48c5efe5a8083c097f53f 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/identity/IdentityManagerImpl.java
@@ -1,29 +1,21 @@
 package org.briarproject.bramble.identity;
 
-import org.briarproject.bramble.api.contact.Contact;
 import org.briarproject.bramble.api.crypto.CryptoComponent;
 import org.briarproject.bramble.api.crypto.KeyPair;
 import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
-import org.briarproject.bramble.api.identity.Author.Status;
 import org.briarproject.bramble.api.identity.AuthorFactory;
-import org.briarproject.bramble.api.identity.AuthorId;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
-import java.util.Collection;
 import java.util.logging.Logger;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
-import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
-import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
-import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
 import static org.briarproject.bramble.util.LogUtils.logDuration;
 import static org.briarproject.bramble.util.LogUtils.now;
 
@@ -118,26 +110,4 @@ class IdentityManagerImpl implements IdentityManager {
 		return db.getLocalAuthors(txn).iterator().next();
 	}
 
-	@Override
-	public Status getAuthorStatus(AuthorId authorId) throws DbException {
-		Transaction txn = db.startTransaction(true);
-		try {
-			return getAuthorStatus(txn, authorId);
-		} finally {
-			db.endTransaction(txn);
-		}
-	}
-
-	@Override
-	public Status getAuthorStatus(Transaction txn, AuthorId authorId)
-			throws DbException {
-		if (getLocalAuthor(txn).getId().equals(authorId)) return OURSELVES;
-		Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
-		if (contacts.isEmpty()) return UNKNOWN;
-		for (Contact c : contacts) {
-			if (c.isVerified()) return VERIFIED;
-		}
-		return UNVERIFIED;
-	}
-
 }
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java
index e2a997f426dd4574fd4620a2cf5ed2c3aafce20a..1dea4f9df9850cf0b34faed098dfd2cab908abaa 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java
@@ -5,10 +5,14 @@ import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.contact.ContactManager;
 import org.briarproject.bramble.api.crypto.SecretKey;
 import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.NoSuchContactException;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.identity.Author;
 import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.AuthorInfo;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.transport.KeyManager;
 import org.briarproject.bramble.test.BrambleMockTestCase;
 import org.briarproject.bramble.test.DbExpectations;
@@ -21,12 +25,20 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Random;
 
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
 import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
 import static org.briarproject.bramble.test.TestUtils.getAuthor;
+import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
 import static org.briarproject.bramble.test.TestUtils.getRandomId;
 import static org.briarproject.bramble.test.TestUtils.getSecretKey;
 import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 public class ContactManagerImplTest extends BrambleMockTestCase {
@@ -34,17 +46,20 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
 	private final Mockery context = new Mockery();
 	private final DatabaseComponent db = context.mock(DatabaseComponent.class);
 	private final KeyManager keyManager = context.mock(KeyManager.class);
+	private final IdentityManager identityManager =
+			context.mock(IdentityManager.class);
 	private final ContactManager contactManager;
 	private final ContactId contactId = new ContactId(42);
 	private final Author remote = getAuthor();
 	private final AuthorId local = new AuthorId(getRandomId());
+	private final LocalAuthor localAuthor = getLocalAuthor();
 	private final String alias = getRandomString(MAX_AUTHOR_NAME_LENGTH);
 	private final boolean verified = false, active = true;
 	private final Contact contact =
 			new Contact(contactId, remote, local, alias, verified, active);
 
 	public ContactManagerImplTest() {
-		contactManager = new ContactManagerImpl(db, keyManager);
+		contactManager = new ContactManagerImpl(db, keyManager, identityManager);
 	}
 
 	@Test
@@ -109,7 +124,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
 			oneOf(db).startTransaction(true);
 			will(returnValue(txn));
 			oneOf(db).getContactsByAuthorId(txn, remote.getId());
-			will(returnValue(Collections.emptyList()));
+			will(returnValue(emptyList()));
 			oneOf(db).endTransaction(txn);
 		}});
 
@@ -208,4 +223,79 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
 		assertTrue(contactManager.contactExists(remote.getId(), local));
 	}
 
+	@Test
+	public void testGetAuthorStatus() throws Exception {
+		Transaction txn = new Transaction(null, true);
+		Collection<Contact> contacts = singletonList(
+				new Contact(new ContactId(1), remote, localAuthor.getId(),
+						alias, false, true));
+
+		context.checking(new DbExpectations() {{
+			oneOf(db).transactionWithResult(with(equal(true)),
+					withDbCallable(txn));
+			oneOf(identityManager).getLocalAuthor(txn);
+			will(returnValue(localAuthor));
+			oneOf(db).getContactsByAuthorId(txn, remote.getId());
+			will(returnValue(contacts));
+		}});
+		AuthorInfo authorInfo =
+				contactManager.getAuthorInfo(txn, remote.getId());
+		assertEquals(UNVERIFIED, authorInfo.getStatus());
+		assertEquals(alias, contact.getAlias());
+	}
+
+	@Test
+	public void testGetAuthorStatusTransaction() throws DbException {
+		Transaction txn = new Transaction(null, true);
+
+		// check unknown author
+		context.checking(new Expectations() {{
+			oneOf(identityManager).getLocalAuthor(txn);
+			will(returnValue(localAuthor));
+			oneOf(db).getContactsByAuthorId(txn, remote.getId());
+			will(returnValue(emptyList()));
+		}});
+		AuthorInfo authorInfo =
+				contactManager.getAuthorInfo(txn, remote.getId());
+		assertEquals(UNKNOWN, authorInfo.getStatus());
+		assertNull(authorInfo.getAlias());
+
+		// check unverified contact
+		Collection<Contact> contacts = singletonList(
+				new Contact(new ContactId(1), remote, localAuthor.getId(),
+						alias, false, true));
+		checkAuthorStatusContext(txn, remote.getId(), contacts);
+		authorInfo = contactManager.getAuthorInfo(txn, remote.getId());
+		assertEquals(UNVERIFIED, authorInfo.getStatus());
+		assertEquals(alias, contact.getAlias());
+
+		// check verified contact
+		contacts = singletonList(new Contact(new ContactId(1), remote,
+				localAuthor.getId(), alias, true, true));
+		checkAuthorStatusContext(txn, remote.getId(), contacts);
+		authorInfo = contactManager.getAuthorInfo(txn, remote.getId());
+		assertEquals(VERIFIED, authorInfo.getStatus());
+		assertEquals(alias, contact.getAlias());
+
+		// check ourselves
+		context.checking(new Expectations() {{
+			oneOf(identityManager).getLocalAuthor(txn);
+			will(returnValue(localAuthor));
+			never(db).getContactsByAuthorId(txn, remote.getId());
+		}});
+		authorInfo = contactManager.getAuthorInfo(txn, localAuthor.getId());
+		assertEquals(OURSELVES, authorInfo.getStatus());
+		assertNull(authorInfo.getAlias());
+	}
+
+	private void checkAuthorStatusContext(Transaction txn, AuthorId authorId,
+			Collection<Contact> contacts) throws DbException {
+		context.checking(new Expectations() {{
+			oneOf(identityManager).getLocalAuthor(txn);
+			will(returnValue(localAuthor));
+			oneOf(db).getContactsByAuthorId(txn, authorId);
+			will(returnValue(contacts));
+		}});
+	}
+
 }
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java
index 2d228cbdb99d6eee5211ef0bb460bec74787799c..622a04e81baa99d876bab9e019fc17ec6b1e37cf 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java
@@ -1,7 +1,5 @@
 package org.briarproject.bramble.identity;
 
-import org.briarproject.bramble.api.contact.Contact;
-import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.crypto.CryptoComponent;
 import org.briarproject.bramble.api.crypto.KeyPair;
 import org.briarproject.bramble.api.crypto.PrivateKey;
@@ -9,9 +7,7 @@ import org.briarproject.bramble.api.crypto.PublicKey;
 import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
-import org.briarproject.bramble.api.identity.Author;
 import org.briarproject.bramble.api.identity.AuthorFactory;
-import org.briarproject.bramble.api.identity.AuthorId;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.test.BrambleMockTestCase;
@@ -19,17 +15,10 @@ import org.jmock.Expectations;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 
-import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
-import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
-import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
-import static org.briarproject.bramble.test.TestUtils.getAuthor;
 import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
-import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.junit.Assert.assertEquals;
 
 public class IdentityManagerImplTest extends BrambleMockTestCase {
@@ -108,60 +97,4 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
 		assertEquals(localAuthor, identityManager.getLocalAuthor());
 	}
 
-	@Test
-	public void testGetAuthorStatus() throws DbException {
-		Author author = getAuthor();
-		AuthorId authorId = author.getId();
-		Collection<Contact> contacts = new ArrayList<>();
-
-		context.checking(new Expectations() {{
-			oneOf(db).startTransaction(true);
-			will(returnValue(txn));
-			oneOf(db).getLocalAuthors(txn);
-			will(returnValue(localAuthors));
-			oneOf(db).getContactsByAuthorId(txn, authorId);
-			will(returnValue(contacts));
-			oneOf(db).endTransaction(txn);
-		}});
-		assertEquals(UNKNOWN, identityManager.getAuthorStatus(authorId));
-
-		// add one unverified contact
-		Contact contact = new Contact(new ContactId(1), author,
-				localAuthor.getId(), getRandomString(5), false, true);
-		contacts.add(contact);
-
-		checkAuthorStatusContext(authorId, contacts);
-		assertEquals(UNVERIFIED, identityManager.getAuthorStatus(authorId));
-
-		// add one verified contact
-		Contact contact2 = new Contact(new ContactId(1), author,
-				localAuthor.getId(), getRandomString(5), true, true);
-		contacts.add(contact2);
-
-		checkAuthorStatusContext(authorId, contacts);
-		assertEquals(VERIFIED, identityManager.getAuthorStatus(authorId));
-
-		context.checking(new Expectations() {{
-			oneOf(db).startTransaction(true);
-			will(returnValue(txn));
-			never(db).getLocalAuthors(txn);
-			never(db).getContactsByAuthorId(txn, authorId);
-			oneOf(db).endTransaction(txn);
-		}});
-		assertEquals(OURSELVES,
-				identityManager.getAuthorStatus(localAuthor.getId()));
-	}
-
-	private void checkAuthorStatusContext(AuthorId authorId,
-			Collection<Contact> contacts) throws DbException {
-		context.checking(new Expectations() {{
-			oneOf(db).startTransaction(true);
-			will(returnValue(txn));
-			never(db).getLocalAuthors(txn);
-			oneOf(db).getContactsByAuthorId(txn, authorId);
-			will(returnValue(contacts));
-			oneOf(db).endTransaction(txn);
-		}});
-	}
-
 }
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/DbExpectations.java b/bramble-core/src/test/java/org/briarproject/bramble/test/DbExpectations.java
index 4493552d3a0f4d8842f42394a1c976bb32540f7c..8c5fa8f281e2e308acb97a39a3ccebdac26aa55a 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/test/DbExpectations.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/test/DbExpectations.java
@@ -1,5 +1,6 @@
 package org.briarproject.bramble.test;
 
+import org.briarproject.bramble.api.db.DbCallable;
 import org.briarproject.bramble.api.db.DbRunnable;
 import org.briarproject.bramble.api.db.Transaction;
 import org.jmock.Expectations;
@@ -13,4 +14,11 @@ public class DbExpectations extends Expectations {
 		return null;
 	}
 
+	protected <R, E extends Exception> DbCallable<R, E> withDbCallable(
+			Transaction txn) {
+		addParameterMatcher(any(DbCallable.class));
+		currentBuilder().setAction(new RunTransactionWithResultAction(txn));
+		return null;
+	}
+
 }
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/RunTransactionWithResultAction.java b/bramble-core/src/test/java/org/briarproject/bramble/test/RunTransactionWithResultAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..cbd22b1260fc2d020b789c622db4c1ebfb3fa79e
--- /dev/null
+++ b/bramble-core/src/test/java/org/briarproject/bramble/test/RunTransactionWithResultAction.java
@@ -0,0 +1,27 @@
+package org.briarproject.bramble.test;
+
+import org.briarproject.bramble.api.db.DbCallable;
+import org.briarproject.bramble.api.db.Transaction;
+import org.hamcrest.Description;
+import org.jmock.api.Action;
+import org.jmock.api.Invocation;
+
+public class RunTransactionWithResultAction implements Action {
+
+	private final Transaction txn;
+
+	public RunTransactionWithResultAction(Transaction txn) {
+		this.txn = txn;
+	}
+
+	@Override
+	public Object invoke(Invocation invocation) throws Throwable {
+		DbCallable task = (DbCallable) invocation.getParameter(1);
+		return task.call(txn);
+	}
+
+	@Override
+	public void describeTo(Description description) {
+		description.appendText("runs a task inside a database transaction");
+	}
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostItem.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostItem.java
index f350fc3f0938ff9f6b2ce893dac936c841a154e6..d64303c07bd2476037cc1c0f5e950a38b713e329 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostItem.java
@@ -3,7 +3,7 @@ package org.briarproject.briar.android.blog;
 import android.support.annotation.NonNull;
 
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.briar.api.blog.BlogPostHeader;
@@ -15,6 +15,7 @@ import javax.annotation.concurrent.NotThreadSafe;
 public class BlogPostItem implements Comparable<BlogPostItem> {
 
 	private final BlogPostHeader header;
+	@Nullable
 	protected String text;
 	private boolean read;
 
@@ -40,10 +41,11 @@ public class BlogPostItem implements Comparable<BlogPostItem> {
 		return header.getAuthor();
 	}
 
-	Status getAuthorStatus() {
-		return header.getAuthorStatus();
+	AuthorInfo getAuthorInfo() {
+		return header.getAuthorInfo();
 	}
 
+	@Nullable
 	public String getText() {
 		return text;
 	}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostViewHolder.java
index ec42e8ef4c20d7107dd62a7b4fefe8e4614877c8..92c75f187314745c2c798583a6da9cd9e9d8e4e8 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/BlogPostViewHolder.java
@@ -100,7 +100,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
 		BlogPostHeader post = item.getPostHeader();
 		Author a = post.getAuthor();
 		author.setAuthor(a);
-		author.setAuthorStatus(post.getAuthorStatus());
+		author.setAuthorInfo(post.getAuthorInfo());
 		author.setDate(post.getTimestamp());
 		author.setPersona(
 				item.isRssFeed() ? AuthorView.RSS_FEED : AuthorView.NORMAL);
@@ -144,7 +144,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
 	private void onBindComment(BlogCommentItem item) {
 		// reblogger
 		reblogger.setAuthor(item.getAuthor());
-		reblogger.setAuthorStatus(item.getAuthorStatus());
+		reblogger.setAuthorInfo(item.getAuthorInfo());
 		reblogger.setDate(item.getTimestamp());
 		if (!fullText) {
 			reblogger.setAuthorClickable(v -> listener.onAuthorClick(item));
@@ -166,7 +166,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
 			TextView text = v.findViewById(R.id.textView);
 
 			author.setAuthor(c.getAuthor());
-			author.setAuthorStatus(c.getAuthorStatus());
+			author.setAuthorInfo(c.getAuthorInfo());
 			author.setDate(c.getTimestamp());
 			// TODO make author clickable #624
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumItem.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumItem.java
index e963aed49a64e11a8165a3df074e394250a204a5..4dae7e7c107edf2346649eb600e610e7ad8a493d 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumItem.java
@@ -1,7 +1,7 @@
 package org.briarproject.briar.android.forum;
 
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.briar.android.threaded.ThreadItem;
 import org.briarproject.briar.api.forum.ForumPostHeader;
@@ -14,12 +14,12 @@ class ForumItem extends ThreadItem {
 
 	ForumItem(ForumPostHeader h, String text) {
 		super(h.getId(), h.getParentId(), text, h.getTimestamp(), h.getAuthor(),
-				h.getAuthorStatus(), h.isRead());
+				h.getAuthorInfo(), h.isRead());
 	}
 
 	ForumItem(MessageId messageId, @Nullable MessageId parentId, String text,
-			long timestamp, Author author, Status status) {
-		super(messageId, parentId, text, timestamp, author, status, true);
+			long timestamp, Author author, AuthorInfo authorInfo) {
+		super(messageId, parentId, text, timestamp, author, authorInfo, true);
 	}
 
 }
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageItem.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageItem.java
index 408fd29ba83429e35cf584f9e1df209a2f388398..27ce086e945a78353b19f1f03f4fdf8ab8c1e2d7 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupMessageItem.java
@@ -4,7 +4,7 @@ import android.support.annotation.LayoutRes;
 import android.support.annotation.UiThread;
 
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.briar.R;
@@ -22,14 +22,14 @@ class GroupMessageItem extends ThreadItem {
 
 	private GroupMessageItem(MessageId messageId, GroupId groupId,
 			@Nullable MessageId parentId, String text, long timestamp,
-			Author author, Status status, boolean isRead) {
-		super(messageId, parentId, text, timestamp, author, status, isRead);
+			Author author, AuthorInfo authorInfo, boolean isRead) {
+		super(messageId, parentId, text, timestamp, author, authorInfo, isRead);
 		this.groupId = groupId;
 	}
 
 	GroupMessageItem(GroupMessageHeader h, String text) {
 		this(h.getId(), h.getGroupId(), h.getParentId(), text, h.getTimestamp(),
-				h.getAuthor(), h.getAuthorStatus(), h.isRead());
+				h.getAuthor(), h.getAuthorInfo(), h.isRead());
 	}
 
 	public GroupId getGroupId() {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItemViewHolder.java
index c14d46ed27d4535389cafdc8215c6c8f5903a6df..09f50711e0ba16b757f5cbcaf142089c4f6d1244 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItemViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/JoinMessageItemViewHolder.java
@@ -9,7 +9,7 @@ import org.briarproject.briar.R;
 import org.briarproject.briar.android.threaded.BaseThreadItemViewHolder;
 import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener;
 
-import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
 
 @UiThread
 @NotNullByDefault
@@ -49,7 +49,7 @@ class JoinMessageItemViewHolder
 			textView.setText(ctx.getString(R.string.groups_member_created,
 					item.getAuthor().getName()));
 		} else {
-			if (item.getStatus() == OURSELVES) {
+			if (item.getAuthorInfo().getStatus() == OURSELVES) {
 				textView.setText(R.string.groups_member_joined_you);
 			} else {
 				textView.setText(ctx.getString(R.string.groups_member_joined,
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java
index bdef6a5886d9f4fcc0c5b80f7863e910defc5125..a83c2c9a35bb684eee13b6a83a8593b5a59c03df 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItem.java
@@ -2,7 +2,8 @@ package org.briarproject.briar.android.privategroup.memberlist;
 
 import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
+import org.briarproject.bramble.api.identity.AuthorInfo.Status;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.briar.api.privategroup.GroupMember;
 
@@ -25,8 +26,12 @@ class MemberListItem {
 		return groupMember.getAuthor();
 	}
 
+	AuthorInfo getAuthorInfo() {
+		return groupMember.getAuthorInfo();
+	}
+
 	Status getStatus() {
-		return groupMember.getStatus();
+		return groupMember.getAuthorInfo().getStatus();
 	}
 
 	boolean isCreator() {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java
index 002f80db2e6f2a3a58605d4594904f4629a4be00..accaced350ef942df4167b48ecb8106518d33df3 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/memberlist/MemberListItemHolder.java
@@ -10,7 +10,9 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.briar.R;
 import org.briarproject.briar.android.view.AuthorView;
 
-import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
 
 @UiThread
 @NotNullByDefault
@@ -28,25 +30,25 @@ class MemberListItemHolder extends RecyclerView.ViewHolder {
 	}
 
 	protected void bind(MemberListItem item) {
-		// member name, avatar and status
+		// member name, avatar and author info
 		author.setAuthor(item.getMember());
-		author.setAuthorStatus(item.getStatus());
+		author.setAuthorInfo(item.getAuthorInfo());
 
 		// online status of visible contacts
 		if (item.getContactId() != null) {
-			bulb.setVisibility(View.VISIBLE);
+			bulb.setVisibility(VISIBLE);
 			if (item.isOnline()) {
 				bulb.setImageResource(R.drawable.contact_connected);
 			} else {
 				bulb.setImageResource(R.drawable.contact_disconnected);
 			}
 		} else {
-			bulb.setVisibility(View.GONE);
+			bulb.setVisibility(GONE);
 		}
 
 		// text shown for creator
 		if (item.isCreator()) {
-			creator.setVisibility(View.VISIBLE);
+			creator.setVisibility(VISIBLE);
 			if (item.getStatus() == OURSELVES) {
 				creator.setText(R.string.groups_member_created_you);
 			} else {
@@ -55,7 +57,7 @@ class MemberListItemHolder extends RecyclerView.ViewHolder {
 								item.getMember().getName()));
 			}
 		} else {
-			creator.setVisibility(View.GONE);
+			creator.setVisibility(GONE);
 		}
 	}
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java
index 45f66b83b3dec6546c206553906cabe83db04791..a88f709ed1572f5e3e9eecc7fc43a5384ebc1fb9 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/BaseThreadItemViewHolder.java
@@ -45,7 +45,7 @@ public abstract class BaseThreadItemViewHolder<I extends ThreadItem>
 
 		author.setAuthor(item.getAuthor());
 		author.setDate(item.getTimestamp());
-		author.setAuthorStatus(item.getStatus());
+		author.setAuthorInfo(item.getAuthorInfo());
 
 		if (item.isHighlighted()) {
 			layout.setActivated(true);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItem.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItem.java
index 62431da9a16c56870ca2c1634429ffd423a42148..79cc0ab186a57e210c76993c6a99c685be2cc918 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItem.java
@@ -1,7 +1,7 @@
 package org.briarproject.briar.android.threaded;
 
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.briar.api.client.MessageTree.MessageNode;
@@ -21,19 +21,19 @@ public abstract class ThreadItem implements MessageNode {
 	private final String text;
 	private final long timestamp;
 	private final Author author;
-	private final Status status;
+	private final AuthorInfo authorInfo;
 	private int level = UNDEFINED;
 	private boolean isRead, highlighted;
 
 	public ThreadItem(MessageId messageId, @Nullable MessageId parentId,
-			String text, long timestamp, Author author, Status status,
+			String text, long timestamp, Author author, AuthorInfo authorInfo,
 			boolean isRead) {
 		this.messageId = messageId;
 		this.parentId = parentId;
 		this.text = text;
 		this.timestamp = timestamp;
 		this.author = author;
-		this.status = status;
+		this.authorInfo = authorInfo;
 		this.isRead = isRead;
 		this.highlighted = false;
 	}
@@ -66,8 +66,8 @@ public abstract class ThreadItem implements MessageNode {
 		return author;
 	}
 
-	public Status getStatus() {
-		return status;
+	public AuthorInfo getAuthorInfo() {
+		return authorInfo;
 	}
 
 	@Override
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/AuthorView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/AuthorView.java
index fa766baa481805467653d95599d37a093188ef59..783c3dcd09cca33dfc1bcce7c5d3cfc9d5bbdcca 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/view/AuthorView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/AuthorView.java
@@ -12,7 +12,7 @@ import android.widget.ImageView;
 import android.widget.TextView;
 
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.briar.R;
 import org.briarproject.briar.android.util.UiUtils;
 
@@ -24,8 +24,8 @@ import im.delight.android.identicons.IdenticonDrawable;
 import static android.content.Context.LAYOUT_INFLATER_SERVICE;
 import static android.graphics.Typeface.BOLD;
 import static android.util.TypedValue.COMPLEX_UNIT_PX;
-import static org.briarproject.bramble.api.identity.Author.Status.NONE;
-import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
 import static org.briarproject.briar.android.util.UiUtils.resolveAttribute;
 
 @UiThread
@@ -79,15 +79,15 @@ public class AuthorView extends ConstraintLayout {
 		requestLayout();
 	}
 
-	public void setAuthorStatus(Status status) {
-		if (status != NONE) {
-			trustIndicator.setTrustLevel(status);
+	public void setAuthorInfo(AuthorInfo authorInfo) {
+		if (authorInfo.getStatus() != NONE) {
+			trustIndicator.setTrustLevel(authorInfo.getStatus());
 			trustIndicator.setVisibility(VISIBLE);
 		} else {
 			trustIndicator.setVisibility(GONE);
 		}
 
-		if (status == OURSELVES) {
+		if (authorInfo.getStatus() == OURSELVES) {
 			authorName.setTypeface(authorNameTypeface, BOLD);
 		} else {
 			authorName.setTypeface(authorNameTypeface, NORMAL);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/TrustIndicatorView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TrustIndicatorView.java
index 3aac50e9b56e5b35704e3620584305967d79bf76..aa3c78c508e421af51a358e876de59606ce44cf9 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/view/TrustIndicatorView.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TrustIndicatorView.java
@@ -3,14 +3,14 @@ package org.briarproject.briar.android.view;
 import android.content.Context;
 import android.support.annotation.UiThread;
 import android.support.v4.content.ContextCompat;
+import android.support.v7.widget.AppCompatImageView;
 import android.util.AttributeSet;
-import android.widget.ImageView;
 
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo.Status;
 import org.briarproject.briar.R;
 
 @UiThread
-public class TrustIndicatorView extends ImageView {
+public class TrustIndicatorView extends AppCompatImageView {
 
 	public TrustIndicatorView(Context context) {
 		super(context);
diff --git a/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java b/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java
index d940e5b8ab6dc5b60a44b3162a74f25a7f3420d8..0f3f94733a19d52868a8111c5b9793ec2bbbc190 100644
--- a/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/forum/ForumActivityTest.java
@@ -6,6 +6,7 @@ import junit.framework.Assert;
 
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.briar.android.TestBriarApplication;
 import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
@@ -26,7 +27,7 @@ import java.util.Arrays;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
-import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN;
 import static org.briarproject.bramble.test.TestUtils.getAuthor;
 import static org.briarproject.bramble.test.TestUtils.getRandomId;
 import static org.briarproject.bramble.util.StringUtils.getRandomString;
@@ -87,7 +88,8 @@ public class ForumActivityTest {
 			Author author = getAuthor();
 			String text = getRandomString(MAX_FORUM_POST_TEXT_LENGTH);
 			forumItems[i] = new ForumItem(MESSAGE_IDS[i], PARENT_IDS[i],
-					text, System.currentTimeMillis(), author, UNKNOWN);
+					text, System.currentTimeMillis(), author,
+					new AuthorInfo(UNKNOWN));
 			forumItems[i].setLevel(LEVELS[i]);
 		}
 		ThreadItemList<ForumItem> list = new ThreadItemListImpl<>();
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogCommentHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogCommentHeader.java
index f7914c9d55a2c45329522ea1795010c64887b5a3..16bf16ab8d8a87212a40849612670ae38f4e770b 100644
--- a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogCommentHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogCommentHeader.java
@@ -1,7 +1,7 @@
 package org.briarproject.briar.api.blog;
 
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.MessageId;
@@ -23,10 +23,10 @@ public class BlogCommentHeader extends BlogPostHeader {
 	public BlogCommentHeader(MessageType type, GroupId groupId,
 			@Nullable String comment, BlogPostHeader parent, MessageId id,
 			long timestamp, long timeReceived, Author author,
-			Status authorStatus, boolean read) {
+			AuthorInfo authorInfo, boolean read) {
 
 		super(type, groupId, id, parent.getId(), timestamp,
-				timeReceived, author, authorStatus, false, read);
+				timeReceived, author, authorInfo, false, read);
 
 		if (type != COMMENT && type != WRAPPED_COMMENT)
 			throw new IllegalArgumentException("Incompatible Message Type");
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostHeader.java
index 57a0ef58a93968c690335bb53736f76678eb2518..ba6ad20a39bf4a1c392b09f3f0fffc8f895680cb 100644
--- a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogPostHeader.java
@@ -1,7 +1,7 @@
 package org.briarproject.briar.api.blog;
 
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.MessageId;
@@ -21,8 +21,8 @@ public class BlogPostHeader extends PostHeader {
 
 	public BlogPostHeader(MessageType type, GroupId groupId, MessageId id,
 			@Nullable MessageId parentId, long timestamp, long timeReceived,
-			Author author, Status authorStatus, boolean rssFeed, boolean read) {
-		super(id, parentId, timestamp, author, authorStatus, read);
+			Author author, AuthorInfo authorInfo, boolean rssFeed, boolean read) {
+		super(id, parentId, timestamp, author, authorInfo, read);
 		this.type = type;
 		this.groupId = groupId;
 		this.timeReceived = timeReceived;
@@ -31,9 +31,9 @@ public class BlogPostHeader extends PostHeader {
 
 	public BlogPostHeader(MessageType type, GroupId groupId, MessageId id,
 			long timestamp, long timeReceived, Author author,
-			Status authorStatus, boolean rssFeed, boolean read) {
+			AuthorInfo authorInfo, boolean rssFeed, boolean read) {
 		this(type, groupId, id, null, timestamp, timeReceived, author,
-				authorStatus, rssFeed, read);
+				authorInfo, rssFeed, read);
 	}
 
 	public MessageType getType() {
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/client/PostHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/client/PostHeader.java
index 1935e27f6471fd8f0651bd4e1acfb0646f62840e..3a975f5c2608a7228902ff395ed13d5677264af9 100644
--- a/briar-api/src/main/java/org/briarproject/briar/api/client/PostHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/client/PostHeader.java
@@ -1,7 +1,8 @@
 package org.briarproject.briar.api.client;
 
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
+import org.briarproject.bramble.api.identity.AuthorInfo.Status;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.MessageId;
 
@@ -17,16 +18,16 @@ public abstract class PostHeader {
 	private final MessageId parentId;
 	private final long timestamp;
 	private final Author author;
-	private final Status authorStatus;
+	private final AuthorInfo authorInfo;
 	private final boolean read;
 
 	public PostHeader(MessageId id, @Nullable MessageId parentId,
-			long timestamp, Author author, Status authorStatus, boolean read) {
+			long timestamp, Author author, AuthorInfo authorInfo, boolean read) {
 		this.id = id;
 		this.parentId = parentId;
 		this.timestamp = timestamp;
 		this.author = author;
-		this.authorStatus = authorStatus;
+		this.authorInfo = authorInfo;
 		this.read = read;
 	}
 
@@ -39,7 +40,11 @@ public abstract class PostHeader {
 	}
 
 	public Status getAuthorStatus() {
-		return authorStatus;
+		return authorInfo.getStatus();
+	}
+
+	public AuthorInfo getAuthorInfo() {
+		return authorInfo;
 	}
 
 	public long getTimestamp() {
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostHeader.java
index 01c76a5e7735f1c7d3663ac58d656b5f27e96ae7..ae8304d4a1c9b325cabf8230f4a61e3372199bc3 100644
--- a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumPostHeader.java
@@ -1,6 +1,7 @@
 package org.briarproject.briar.api.forum;
 
 import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.briar.api.client.PostHeader;
@@ -13,9 +14,9 @@ import javax.annotation.concurrent.Immutable;
 public class ForumPostHeader extends PostHeader {
 
 	public ForumPostHeader(MessageId id, @Nullable MessageId parentId,
-			long timestamp, Author author, Author.Status authorStatus,
+			long timestamp, Author author, AuthorInfo authorInfo,
 			boolean read) {
-		super(id, parentId, timestamp, author, authorStatus, read);
+		super(id, parentId, timestamp, author, authorInfo, read);
 	}
 
 }
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java
index b83c1e7b4faac529e88bcce6291eb305ad993729..6080b6a9e712645679c2dcad995ef087800e1f25 100644
--- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMember.java
@@ -2,7 +2,7 @@ package org.briarproject.briar.api.privategroup;
 
 import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import javax.annotation.Nullable;
@@ -13,16 +13,16 @@ import javax.annotation.concurrent.Immutable;
 public class GroupMember {
 
 	private final Author author;
-	private final Status status;
+	private final AuthorInfo authorInfo;
 	private final boolean isCreator;
 	@Nullable
 	private final ContactId contactId;
 	private final Visibility visibility;
 
-	public GroupMember(Author author, Status status, boolean isCreator,
+	public GroupMember(Author author, AuthorInfo authorInfo, boolean isCreator,
 			@Nullable ContactId contactId, Visibility visibility) {
 		this.author = author;
-		this.status = status;
+		this.authorInfo = authorInfo;
 		this.isCreator = isCreator;
 		this.contactId = contactId;
 		this.visibility = visibility;
@@ -32,8 +32,8 @@ public class GroupMember {
 		return author;
 	}
 
-	public Status getStatus() {
-		return status;
+	public AuthorInfo getAuthorInfo() {
+		return authorInfo;
 	}
 
 	public boolean isCreator() {
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageHeader.java
index f75183010f68b26e34d24a7297976b85941485cd..7174114c575c29366217c210dcb3f119f35d4aa0 100644
--- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/GroupMessageHeader.java
@@ -1,7 +1,7 @@
 package org.briarproject.briar.api.privategroup;
 
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.MessageId;
@@ -18,8 +18,8 @@ public class GroupMessageHeader extends PostHeader {
 
 	public GroupMessageHeader(GroupId groupId, MessageId id,
 			@Nullable MessageId parentId, long timestamp,
-			Author author, Status authorStatus, boolean read) {
-		super(id, parentId, timestamp, author, authorStatus, read);
+			Author author, AuthorInfo authorInfo, boolean read) {
+		super(id, parentId, timestamp, author, authorInfo, read);
 		this.groupId = groupId;
 	}
 
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/JoinMessageHeader.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/JoinMessageHeader.java
index 74619a80c14690c580d9f00261aca7a406681d24..dfcfeff5d8476da2ce2da1433c3bc29ea2286dfa 100644
--- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/JoinMessageHeader.java
+++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/JoinMessageHeader.java
@@ -14,7 +14,7 @@ public class JoinMessageHeader extends GroupMessageHeader {
 	public JoinMessageHeader(GroupMessageHeader h, Visibility visibility,
 			boolean isInitial) {
 		super(h.getGroupId(), h.getId(), h.getParentId(), h.getTimestamp(),
-				h.getAuthor(), h.getAuthorStatus(), h.isRead());
+				h.getAuthor(), h.getAuthorInfo(), h.isRead());
 		this.visibility = visibility;
 		this.isInitial = isInitial;
 	}
diff --git a/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
index 18c97f3ad8177c1ac1d8b3ba2a236445c8c51567..7c4bde47745ffd81b2488981077e58c139d7a305 100644
--- a/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/blog/BlogManagerImpl.java
@@ -3,6 +3,7 @@ package org.briarproject.briar.blog;
 import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.ClientHelper;
 import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactManager;
 import org.briarproject.bramble.api.contact.ContactManager.ContactHook;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.data.BdfEntry;
@@ -12,8 +13,8 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
 import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -49,6 +50,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
 import javax.annotation.Nullable;
 import javax.inject.Inject;
 
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
 import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
 import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT;
 import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID;
@@ -68,17 +70,19 @@ import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
 class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 		ContactHook, Client {
 
+	private final ContactManager contactManager;
 	private final IdentityManager identityManager;
 	private final BlogFactory blogFactory;
 	private final BlogPostFactory blogPostFactory;
 	private final List<RemoveBlogHook> removeHooks;
 
 	@Inject
-	BlogManagerImpl(DatabaseComponent db, IdentityManager identityManager,
-			ClientHelper clientHelper, MetadataParser metadataParser,
-			BlogFactory blogFactory, BlogPostFactory blogPostFactory) {
+	BlogManagerImpl(DatabaseComponent db, ContactManager contactManager,
+			IdentityManager identityManager, ClientHelper clientHelper,
+			MetadataParser metadataParser, BlogFactory blogFactory,
+			BlogPostFactory blogPostFactory) {
 		super(db, clientHelper, metadataParser);
-
+		this.contactManager = contactManager;
 		this.identityManager = identityManager;
 		this.blogFactory = blogFactory;
 		this.blogPostFactory = blogPostFactory;
@@ -501,25 +505,24 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 					new HashMap<>(metadata1.size() + metadata2.size());
 			metadata.putAll(metadata1);
 			metadata.putAll(metadata2);
-			// get all authors we need to get the status for
+			// get all authors we need to get the information for
 			Set<AuthorId> authors = new HashSet<>();
 			for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
 				BdfList authorList = entry.getValue().getList(KEY_AUTHOR);
 				Author a = clientHelper.parseAndValidateAuthor(authorList);
 				authors.add(a.getId());
 			}
-			// get statuses for all authors
-			Map<AuthorId, Status> authorStatuses = new HashMap<>();
+			// get information for all authors
+			Map<AuthorId, AuthorInfo> authorInfos = new HashMap<>();
 			for (AuthorId authorId : authors) {
-				authorStatuses.put(authorId,
-						identityManager.getAuthorStatus(txn, authorId));
+				authorInfos.put(authorId,
+						contactManager.getAuthorInfo(txn, authorId));
 			}
 			// get post headers
 			for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
 				BdfDictionary meta = entry.getValue();
-				BlogPostHeader h =
-						getPostHeaderFromMetadata(txn, g, entry.getKey(), meta,
-								authorStatuses);
+				BlogPostHeader h = getPostHeaderFromMetadata(txn, g,
+						entry.getKey(), meta, authorInfos);
 				headers.add(h);
 			}
 			db.commitTransaction(txn);
@@ -563,7 +566,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 
 	private BlogPostHeader getPostHeaderFromMetadata(Transaction txn,
 			GroupId groupId, MessageId id, BdfDictionary meta,
-			Map<AuthorId, Status> authorStatuses)
+			Map<AuthorId, AuthorInfo> authorInfos)
 			throws DbException, FormatException {
 
 		MessageType type = getMessageType(meta);
@@ -574,13 +577,13 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 		BdfList authorList = meta.getList(KEY_AUTHOR);
 		Author author = clientHelper.parseAndValidateAuthor(authorList);
 		boolean isFeedPost = meta.getBoolean(KEY_RSS_FEED, false);
-		Status authorStatus;
+		AuthorInfo authorInfo;
 		if (isFeedPost) {
-			authorStatus = Status.NONE;
-		} else if (authorStatuses.containsKey(author.getId())) {
-			authorStatus = authorStatuses.get(author.getId());
+			authorInfo = new AuthorInfo(NONE);
+		} else if (authorInfos.containsKey(author.getId())) {
+			authorInfo = authorInfos.get(author.getId());
 		} else {
-			authorStatus = identityManager.getAuthorStatus(txn, author.getId());
+			authorInfo = contactManager.getAuthorInfo(txn, author.getId());
 		}
 
 		boolean read = meta.getBoolean(KEY_READ, false);
@@ -591,10 +594,10 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
 			BlogPostHeader parent =
 					getPostHeaderFromMetadata(txn, groupId, parentId);
 			return new BlogCommentHeader(type, groupId, comment, parent, id,
-					timestamp, timeReceived, author, authorStatus, read);
+					timestamp, timeReceived, author, authorInfo, read);
 		} else {
 			return new BlogPostHeader(type, groupId, id, timestamp,
-					timeReceived, author, authorStatus, isFeedPost, read);
+					timeReceived, author, authorInfo, isFeedPost, read);
 		}
 	}
 
diff --git a/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java
index d1b3bb9750e333394e372c6b50b7b675722a0909..493778470fe762d0f3c9f7d26eef4ba5dc8b4fd7 100644
--- a/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java
@@ -2,6 +2,7 @@ package org.briarproject.briar.forum;
 
 import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.ContactManager;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.data.BdfList;
 import org.briarproject.bramble.api.data.MetadataParser;
@@ -9,9 +10,8 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
 import org.briarproject.bramble.api.identity.AuthorId;
-import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.Group;
@@ -45,7 +45,7 @@ import javax.annotation.Nullable;
 import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
-import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
 import static org.briarproject.briar.api.forum.ForumConstants.KEY_AUTHOR;
 import static org.briarproject.briar.api.forum.ForumConstants.KEY_LOCAL;
 import static org.briarproject.briar.api.forum.ForumConstants.KEY_PARENT;
@@ -56,19 +56,19 @@ import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ
 @NotNullByDefault
 class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 
-	private final IdentityManager identityManager;
+	private final ContactManager contactManager;
 	private final ForumFactory forumFactory;
 	private final ForumPostFactory forumPostFactory;
 	private final MessageTracker messageTracker;
 	private final List<RemoveForumHook> removeHooks;
 
 	@Inject
-	ForumManagerImpl(DatabaseComponent db, IdentityManager identityManager,
+	ForumManagerImpl(DatabaseComponent db, ContactManager contactManager,
 			ClientHelper clientHelper, MetadataParser metadataParser,
 			ForumFactory forumFactory, ForumPostFactory forumPostFactory,
 			MessageTracker messageTracker) {
 		super(db, clientHelper, metadataParser);
-		this.identityManager = identityManager;
+		this.contactManager = contactManager;
 		this.forumFactory = forumFactory;
 		this.forumPostFactory = forumPostFactory;
 		this.messageTracker = messageTracker;
@@ -142,8 +142,9 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 				throw new AssertionError(e);
 			}
 		});
+		AuthorInfo authorInfo = new AuthorInfo(OURSELVES);
 		return new ForumPostHeader(p.getMessage().getId(), p.getParent(),
-				p.getMessage().getTimestamp(), p.getAuthor(), OURSELVES, true);
+				p.getMessage().getTimestamp(), p.getAuthor(), authorInfo, true);
 	}
 
 	@Override
@@ -196,7 +197,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 				Collection<ForumPostHeader> headers = new ArrayList<>();
 				Map<MessageId, BdfDictionary> metadata =
 						clientHelper.getMessageMetadataAsDictionary(txn, g);
-				// get all authors we need to get the status for
+				// get all authors we need to get the info for
 				Set<AuthorId> authors = new HashSet<>();
 				for (Entry<MessageId, BdfDictionary> entry :
 						metadata.entrySet()) {
@@ -204,17 +205,17 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 					Author a = clientHelper.parseAndValidateAuthor(authorList);
 					authors.add(a.getId());
 				}
-				// get statuses for all authors
-				Map<AuthorId, Status> statuses = new HashMap<>();
+				// get information for all authors
+				Map<AuthorId, AuthorInfo> authorInfos = new HashMap<>();
 				for (AuthorId id : authors) {
-					statuses.put(id, identityManager.getAuthorStatus(txn, id));
+					authorInfos.put(id, contactManager.getAuthorInfo(txn, id));
 				}
 				// Parse the metadata
 				for (Entry<MessageId, BdfDictionary> entry :
 						metadata.entrySet()) {
 					BdfDictionary meta = entry.getValue();
 					headers.add(getForumPostHeader(txn, entry.getKey(), meta,
-							statuses));
+							authorInfos));
 				}
 				return headers;
 			});
@@ -252,7 +253,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 	}
 
 	private ForumPostHeader getForumPostHeader(Transaction txn, MessageId id,
-			BdfDictionary meta, Map<AuthorId, Status> statuses)
+			BdfDictionary meta, Map<AuthorId, AuthorInfo> authorInfos)
 			throws DbException, FormatException {
 
 		long timestamp = meta.getLong(KEY_TIMESTAMP);
@@ -261,12 +262,12 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
 			parentId = new MessageId(meta.getRaw(KEY_PARENT));
 		BdfList authorList = meta.getList(KEY_AUTHOR);
 		Author author = clientHelper.parseAndValidateAuthor(authorList);
-		Status status = statuses.get(author.getId());
-		if (status == null)
-			status = identityManager.getAuthorStatus(txn, author.getId());
+		AuthorInfo authorInfo = authorInfos.get(author.getId());
+		if (authorInfo == null)
+			authorInfo = contactManager.getAuthorInfo(txn, author.getId());
 		boolean read = meta.getBoolean(MSG_KEY_READ);
 
-		return new ForumPostHeader(id, parentId, timestamp, author, status,
+		return new ForumPostHeader(id, parentId, timestamp, author, authorInfo,
 				read);
 	}
 
diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java
index 64dbe834bc7be36bbfe63a4027daa1338a699b2d..10614efd676bb85ce36f6ccfb56b78c0540a0c9e 100644
--- a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java
+++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java
@@ -13,8 +13,9 @@ import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.event.Event;
 import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.identity.Author.Status;
 import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.identity.AuthorInfo;
+import org.briarproject.bramble.api.identity.AuthorInfo.Status;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -53,9 +54,9 @@ import java.util.concurrent.CopyOnWriteArrayList;
 import javax.annotation.concurrent.ThreadSafe;
 import javax.inject.Inject;
 
-import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
-import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
 import static org.briarproject.briar.api.privategroup.MessageType.JOIN;
 import static org.briarproject.briar.api.privategroup.MessageType.POST;
 import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
@@ -231,9 +232,10 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
 		} finally {
 			db.endTransaction(txn);
 		}
+		AuthorInfo authorInfo = new AuthorInfo(OURSELVES);
 		return new GroupMessageHeader(m.getMessage().getGroupId(),
 				m.getMessage().getId(), m.getParent(),
-				m.getMessage().getTimestamp(), m.getMember(), OURSELVES, true);
+				m.getMessage().getTimestamp(), m.getMember(), authorInfo, true);
 	}
 
 	private void addMessageMetadata(BdfDictionary meta, GroupMessage m) {
@@ -321,15 +323,15 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
 		try {
 			Map<MessageId, BdfDictionary> metadata =
 					clientHelper.getMessageMetadataAsDictionary(txn, g);
-			// get all authors we need to get the status for
+			// get all authors we need to get the information for
 			Set<AuthorId> authors = new HashSet<>();
 			for (BdfDictionary meta : metadata.values()) {
 				authors.add(getAuthor(meta).getId());
 			}
-			// get statuses for all authors
-			Map<AuthorId, Status> statuses = new HashMap<>();
+			// get information for all authors
+			Map<AuthorId, AuthorInfo> authorInfos = new HashMap<>();
 			for (AuthorId id : authors) {
-				statuses.put(id, identityManager.getAuthorStatus(txn, id));
+				authorInfos.put(id, contactManager.getAuthorInfo(txn, id));
 			}
 			// get current visibilities for join messages
 			Map<Author, Visibility> visibilities = getMembers(txn, g);
@@ -340,10 +342,10 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
 					Author member = getAuthor(meta);
 					Visibility v = visibilities.get(member);
 					headers.add(getJoinMessageHeader(txn, g, entry.getKey(),
-							meta, statuses, v));
+							meta, authorInfos, v));
 				} else {
 					headers.add(getGroupMessageHeader(txn, g, entry.getKey(),
-							meta, statuses));
+							meta, authorInfos));
 				}
 			}
 			db.commitTransaction(txn);
@@ -356,7 +358,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
 	}
 
 	private GroupMessageHeader getGroupMessageHeader(Transaction txn, GroupId g,
-			MessageId id, BdfDictionary meta, Map<AuthorId, Status> statuses)
+			MessageId id, BdfDictionary meta,
+			Map<AuthorId, AuthorInfo> authorInfos)
 			throws DbException, FormatException {
 
 		MessageId parentId = null;
@@ -366,24 +369,25 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
 		long timestamp = meta.getLong(KEY_TIMESTAMP);
 
 		Author member = getAuthor(meta);
-		Status status;
-		if (statuses.containsKey(member.getId())) {
-			status = statuses.get(member.getId());
+		AuthorInfo authorInfo;
+		if (authorInfos.containsKey(member.getId())) {
+			authorInfo = authorInfos.get(member.getId());
 		} else {
-			status = identityManager.getAuthorStatus(txn, member.getId());
+			authorInfo = contactManager.getAuthorInfo(txn, member.getId());
 		}
 		boolean read = meta.getBoolean(KEY_READ);
 
 		return new GroupMessageHeader(g, id, parentId, timestamp, member,
-				status, read);
+				authorInfo, read);
 	}
 
 	private JoinMessageHeader getJoinMessageHeader(Transaction txn, GroupId g,
-			MessageId id, BdfDictionary meta, Map<AuthorId, Status> statuses,
-			Visibility v) throws DbException, FormatException {
+			MessageId id, BdfDictionary meta,
+			Map<AuthorId, AuthorInfo> authorInfos, Visibility v)
+			throws DbException, FormatException {
 
 		GroupMessageHeader header =
-				getGroupMessageHeader(txn, g, id, meta, statuses);
+				getGroupMessageHeader(txn, g, id, meta, authorInfos);
 		boolean creator = meta.getBoolean(KEY_INITIAL_JOIN_MSG);
 		return new JoinMessageHeader(header, v, creator);
 	}
@@ -398,7 +402,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
 			PrivateGroup privateGroup = getPrivateGroup(txn, g);
 			for (Entry<Author, Visibility> m : authors.entrySet()) {
 				Author a = m.getKey();
-				Status status = identityManager.getAuthorStatus(txn, a.getId());
+				AuthorInfo authorInfo = contactManager.getAuthorInfo(txn, a.getId());
+				Status status = authorInfo.getStatus();
 				Visibility v = m.getValue();
 				ContactId c = null;
 				if (v != INVISIBLE &&
@@ -407,7 +412,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
 							.getId();
 				}
 				boolean isCreator = privateGroup.getCreator().equals(a);
-				members.add(new GroupMember(a, status, isCreator, c, v));
+				members.add(new GroupMember(a, authorInfo, isCreator, c, v));
 			}
 			db.commitTransaction(txn);
 			return members;
diff --git a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
index 0f1f94e5bd9bdf811a809a0737156d5d08e70dfc..df573bf1b6feb186b325302443e43ccc9d5e20d6 100644
--- a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.ClientHelper;
 import org.briarproject.bramble.api.contact.Contact;
 import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.data.BdfEntry;
 import org.briarproject.bramble.api.data.BdfList;
@@ -12,6 +13,7 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.db.Transaction;
 import org.briarproject.bramble.api.identity.Author;
+import org.briarproject.bramble.api.identity.AuthorInfo;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.sync.Group;
@@ -29,9 +31,9 @@ import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
 
-import static org.briarproject.bramble.api.identity.Author.Status.NONE;
-import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
-import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
 import static org.briarproject.bramble.test.TestUtils.getGroup;
 import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
 import static org.briarproject.bramble.test.TestUtils.getMessage;
@@ -64,6 +66,8 @@ public class BlogManagerImplTest extends BriarTestCase {
 	private final Mockery context = new Mockery();
 	private final BlogManagerImpl blogManager;
 	private final DatabaseComponent db = context.mock(DatabaseComponent.class);
+	private final ContactManager contactManager =
+			context.mock(ContactManager.class);
 	private final IdentityManager identityManager =
 			context.mock(IdentityManager.class);
 	private final ClientHelper clientHelper = context.mock(ClientHelper.class);
@@ -72,6 +76,8 @@ public class BlogManagerImplTest extends BriarTestCase {
 			context.mock(BlogPostFactory.class);
 
 	private final LocalAuthor localAuthor1, localAuthor2, rssLocalAuthor;
+	private final AuthorInfo ourselvesInfo = new AuthorInfo(OURSELVES);
+	private final AuthorInfo verifiedInfo = new AuthorInfo(VERIFIED);
 	private final BdfList authorList1, authorList2, rssAuthorList;
 	private final Blog blog1, blog2, rssBlog;
 	private final Message message, rssMessage;
@@ -81,7 +87,7 @@ public class BlogManagerImplTest extends BriarTestCase {
 
 	public BlogManagerImplTest() {
 		MetadataParser metadataParser = context.mock(MetadataParser.class);
-		blogManager = new BlogManagerImpl(db, identityManager, clientHelper,
+		blogManager = new BlogManagerImpl(db, contactManager, identityManager, clientHelper,
 				metadataParser, blogFactory, blogPostFactory);
 
 		localAuthor1 = getLocalAuthor();
@@ -175,8 +181,8 @@ public class BlogManagerImplTest extends BriarTestCase {
 		context.checking(new Expectations() {{
 			oneOf(clientHelper).parseAndValidateAuthor(authorList1);
 			will(returnValue(localAuthor1));
-			oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
-			will(returnValue(VERIFIED));
+			oneOf(contactManager).getAuthorInfo(txn, localAuthor1.getId());
+			will(returnValue(verifiedInfo));
 		}});
 
 		blogManager.incomingMessage(txn, message, body, meta);
@@ -281,8 +287,8 @@ public class BlogManagerImplTest extends BriarTestCase {
 			oneOf(clientHelper).addLocalMessage(txn, message, meta, true);
 			oneOf(clientHelper).parseAndValidateAuthor(authorList1);
 			will(returnValue(localAuthor1));
-			oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
-			will(returnValue(OURSELVES));
+			oneOf(contactManager).getAuthorInfo(txn, localAuthor1.getId());
+			will(returnValue(ourselvesInfo));
 			oneOf(db).commitTransaction(txn);
 			oneOf(db).endTransaction(txn);
 		}});
@@ -396,21 +402,21 @@ public class BlogManagerImplTest extends BriarTestCase {
 			// Create the headers for the comment and its parent
 			oneOf(clientHelper).parseAndValidateAuthor(authorList1);
 			will(returnValue(localAuthor1));
-			oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
-			will(returnValue(OURSELVES));
+			oneOf(contactManager).getAuthorInfo(txn, localAuthor1.getId());
+			will(returnValue(ourselvesInfo));
 			oneOf(clientHelper).getMessageMetadataAsDictionary(txn, messageId);
 			will(returnValue(postMeta));
 			oneOf(clientHelper).parseAndValidateAuthor(authorList1);
 			will(returnValue(localAuthor1));
-			oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
-			will(returnValue(OURSELVES));
+			oneOf(contactManager).getAuthorInfo(txn, localAuthor1.getId());
+			will(returnValue(ourselvesInfo));
 			oneOf(db).commitTransaction(txn);
 			oneOf(db).endTransaction(txn);
 		}});
 
 		BlogPostHeader postHeader = new BlogPostHeader(POST, blog1.getId(),
 				messageId, null, timestamp, timeReceived, localAuthor1,
-				OURSELVES, false, true);
+				ourselvesInfo, false, true);
 		blogManager.addLocalComment(localAuthor1, blog1.getId(), comment,
 				postHeader);
 		context.assertIsSatisfied();
@@ -504,22 +510,22 @@ public class BlogManagerImplTest extends BriarTestCase {
 			// Create the headers for the comment and the wrapped post
 			oneOf(clientHelper).parseAndValidateAuthor(authorList2);
 			will(returnValue(localAuthor2));
-			oneOf(identityManager).getAuthorStatus(txn, localAuthor2.getId());
-			will(returnValue(OURSELVES));
+			oneOf(contactManager).getAuthorInfo(txn, localAuthor2.getId());
+			will(returnValue(ourselvesInfo));
 			oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
 					wrappedPostId);
 			will(returnValue(wrappedPostMeta));
 			oneOf(clientHelper).parseAndValidateAuthor(authorList1);
 			will(returnValue(localAuthor1));
-			oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
-			will(returnValue(VERIFIED));
+			oneOf(contactManager).getAuthorInfo(txn, localAuthor1.getId());
+			will(returnValue(verifiedInfo));
 			oneOf(db).commitTransaction(txn);
 			oneOf(db).endTransaction(txn);
 		}});
 
 		BlogPostHeader originalPostHeader = new BlogPostHeader(POST,
 				blog1.getId(), messageId, null, timestamp, timeReceived,
-				localAuthor1, VERIFIED, false, true);
+				localAuthor1, verifiedInfo, false, true);
 		blogManager.addLocalComment(localAuthor2, blog2.getId(), comment,
 				originalPostHeader);
 		context.assertIsSatisfied();
@@ -613,8 +619,8 @@ public class BlogManagerImplTest extends BriarTestCase {
 			// Create the headers for the comment and the wrapped post
 			oneOf(clientHelper).parseAndValidateAuthor(authorList1);
 			will(returnValue(localAuthor1));
-			oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
-			will(returnValue(OURSELVES));
+			oneOf(contactManager).getAuthorInfo(txn, localAuthor1.getId());
+			will(returnValue(ourselvesInfo));
 			oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
 					wrappedPostId);
 			will(returnValue(wrappedPostMeta));
@@ -626,7 +632,7 @@ public class BlogManagerImplTest extends BriarTestCase {
 
 		BlogPostHeader originalPostHeader = new BlogPostHeader(POST,
 				rssBlog.getId(), rssMessageId, null, timestamp, timeReceived,
-				rssLocalAuthor, NONE, true, true);
+				rssLocalAuthor, new AuthorInfo(NONE), true, true);
 		blogManager.addLocalComment(localAuthor1, blog1.getId(), comment,
 				originalPostHeader);
 		context.assertIsSatisfied();
@@ -752,15 +758,15 @@ public class BlogManagerImplTest extends BriarTestCase {
 			// the rewrapped post
 			oneOf(clientHelper).parseAndValidateAuthor(authorList2);
 			will(returnValue(localAuthor2));
-			oneOf(identityManager).getAuthorStatus(txn, localAuthor2.getId());
-			will(returnValue(OURSELVES));
+			oneOf(contactManager).getAuthorInfo(txn, localAuthor2.getId());
+			will(returnValue(ourselvesInfo));
 			oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
 					wrappedCommentId);
 			will(returnValue(wrappedCommentMeta));
 			oneOf(clientHelper).parseAndValidateAuthor(authorList1);
 			will(returnValue(localAuthor1));
-			oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
-			will(returnValue(VERIFIED));
+			oneOf(contactManager).getAuthorInfo(txn, localAuthor1.getId());
+			will(returnValue(verifiedInfo));
 			oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
 					rewrappedPostId);
 			will(returnValue(rewrappedPostMeta));
@@ -772,10 +778,10 @@ public class BlogManagerImplTest extends BriarTestCase {
 
 		BlogPostHeader wrappedPostHeader = new BlogPostHeader(WRAPPED_POST,
 				blog1.getId(), wrappedPostId, null, timestamp, timeReceived,
-				rssLocalAuthor, NONE, true, true);
+				rssLocalAuthor, new AuthorInfo(NONE), true, true);
 		BlogCommentHeader originalCommentHeader = new BlogCommentHeader(COMMENT,
 				blog1.getId(), comment, wrappedPostHeader, originalCommentId,
-				timestamp, timeReceived, localAuthor1, VERIFIED, true);
+				timestamp, timeReceived, localAuthor1, verifiedInfo, true);
 
 		blogManager.addLocalComment(localAuthor2, blog2.getId(), localComment,
 				originalCommentHeader);
diff --git a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java
index ffa6ed73413bf86dea27f705a3ce31cd0c73510f..7e6638a5ab51068c7fe0f79ae95019f77014522b 100644
--- a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java
@@ -1,6 +1,5 @@
 package org.briarproject.briar.blog;
 
-import org.briarproject.bramble.api.identity.Author;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.test.TestDatabaseModule;
@@ -23,6 +22,7 @@ import java.util.Iterator;
 import static junit.framework.Assert.assertNotNull;
 import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
 import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
 import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.briarproject.briar.api.blog.MessageType.COMMENT;
@@ -424,7 +424,7 @@ public class BlogManagerIntegrationTest
 		assertEquals(1, headers.size());
 		BlogPostHeader header = headers.iterator().next();
 		assertEquals(POST, header.getType());
-		assertEquals(Author.Status.NONE, header.getAuthorStatus());
+		assertEquals(NONE, header.getAuthorStatus());
 		assertTrue(header.isRssFeed());
 	}
 
diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupIntegrationTest.java
index c42fe911f667698ada9253de252b9576ebd41291..61c2fcdd9ef807d519a416e9f4d8952d2c1e8f93 100644
--- a/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupIntegrationTest.java
@@ -24,7 +24,7 @@ import java.util.Collection;
 
 import javax.annotation.Nullable;
 
-import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
 import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
 import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_CONTACT;
 import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_US;
@@ -92,7 +92,8 @@ public class PrivateGroupIntegrationTest
 		Collection<GroupMember> members = groupManager0.getMembers(groupId0);
 		assertEquals(1, members.size());
 		assertEquals(author0, members.iterator().next().getAuthor());
-		assertEquals(OURSELVES, members.iterator().next().getStatus());
+		assertEquals(OURSELVES,
+				members.iterator().next().getAuthorInfo().getStatus());
 
 		sync0To1(1, true);
 		groupInvitationManager1
@@ -107,7 +108,7 @@ public class PrivateGroupIntegrationTest
 		members = groupManager0.getMembers(groupId0);
 		assertEquals(2, members.size());
 		for (GroupMember m : members) {
-			if (m.getStatus() == OURSELVES) {
+			if (m.getAuthorInfo().getStatus() == OURSELVES) {
 				assertEquals(author0.getId(), m.getAuthor().getId());
 			} else {
 				assertEquals(author1.getId(), m.getAuthor().getId());
@@ -117,7 +118,7 @@ public class PrivateGroupIntegrationTest
 		members = groupManager1.getMembers(groupId0);
 		assertEquals(2, members.size());
 		for (GroupMember m : members) {
-			if (m.getStatus() == OURSELVES) {
+			if (m.getAuthorInfo().getStatus() == OURSELVES) {
 				assertEquals(author1.getId(), m.getAuthor().getId());
 			} else {
 				assertEquals(author0.getId(), m.getAuthor().getId());
diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupManagerIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupManagerIntegrationTest.java
index 4c4172741bea3adc3c0024171ca182312494d34e..a6daa7488d7abba943f134a5f2adfb9635778292 100644
--- a/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupManagerIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/PrivateGroupManagerIntegrationTest.java
@@ -20,7 +20,7 @@ import org.junit.Test;
 
 import java.util.Collection;
 
-import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
+import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
 import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
 import static org.briarproject.bramble.test.TestUtils.getRandomId;
diff --git a/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.kt b/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.kt
index 2b3b4bc5bd4b9f2b950ea303b8ae9b05a85596b3..3b6617582849e3402615b89c469eaec502b15182 100644
--- a/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.kt
+++ b/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.kt
@@ -1,6 +1,7 @@
 package org.briarproject.bramble.identity
 
 import org.briarproject.bramble.api.identity.Author
+import org.briarproject.bramble.api.identity.AuthorInfo
 import org.briarproject.briar.headless.json.JsonDict
 
 fun Author.output() = JsonDict(
@@ -10,4 +11,4 @@ fun Author.output() = JsonDict(
     "publicKey" to publicKey
 )
 
-fun Author.Status.output() = name.toLowerCase()
+fun AuthorInfo.Status.output() = name.toLowerCase()
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.kt
index 0a8b2ccc737f78d2d537407014bfbd8afdba0a79..af9ea2ab40e1e3abda4ddfe46cb860a6bc7eb1b8 100644
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.kt
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.kt
@@ -8,7 +8,7 @@ import org.briarproject.briar.headless.json.JsonDict
 internal fun BlogPostHeader.output(text: String) = JsonDict(
         "text" to text,
         "author" to author.output(),
-        "authorStatus" to authorStatus.output(),
+        "authorStatus" to authorInfo.status.output(),
         "type" to type.output(),
         "id" to id.bytes,
         "parentId" to parentId?.bytes,
diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt
index db4774d272d47759aa35eb10c90af910b27d8653..a33e796a59dbe406c408bf759a00e5fb9761ccc9 100644
--- a/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt
+++ b/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt
@@ -6,7 +6,8 @@ import io.mockk.Runs
 import io.mockk.every
 import io.mockk.just
 import io.mockk.mockk
-import org.briarproject.bramble.api.identity.Author.Status.OURSELVES
+import org.briarproject.bramble.api.identity.AuthorInfo
+import org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES
 import org.briarproject.bramble.api.sync.MessageId
 import org.briarproject.bramble.identity.output
 import org.briarproject.bramble.util.StringUtils.getRandomString
@@ -30,8 +31,16 @@ internal class BlogControllerTest : ControllerTest() {
     private val rssFeed = false
     private val read = true
     private val header = BlogPostHeader(
-        POST, group.id, message.id, parentId, message.timestamp, timestamp, author, OURSELVES,
-        rssFeed, read
+        POST,
+        group.id,
+        message.id,
+        parentId,
+        message.timestamp,
+        timestamp,
+        author,
+        AuthorInfo(OURSELVES),
+        rssFeed,
+        read
     )
 
     @Test