Discussions API

(Please note this is still pending a review from myself, so best not to review anything too low-level)

This introduces discussions back-end functionality. Key areas of change:

1. A new generic `oae-messagebox` module which handles threaded messaging functionality, based on content comments. Content Comments now uses this API, as well as Discussions. This introduces changes to the comments model, including outstanding work to make the `created` attribute a timestamp and not a "threadKey", and makes it so that messages do not have top-level ids, they use a compound messagebox+timestamp key.

2. A new generic `oae-library` module, which handles indexing libraries. A "Library" is essentially a sorted list of resource ids in which a visibility mask is applied. You effectively get 3 different sub-lists: private, loggedin, public, and the authentication+tenant of the user accessing the library determines which version of the Library you get. This is a generalization based on Nico's content library work.
* Adds auto-repair when reading libraries to remove duplicates (duplicates which occur within the same page)

3. A Discussions module, which adds a new top-level discussion entity. Create, read, update discussions, listing discussion libraries, create / delete / list messages on discussions, etc... There is also some new patterns introduced, such as `DiscussionAPI.Authz.*` to hold discussion permissions and privacy logic.

4. A little bit of consolidation of privacy logic, by virtue of what DiscussionsAPI.Authz.* exposes. To my dismay, currently the ContentAPI will reference DiscussionsAPI.Authz logic directly to re-use some tricky privacy logic around library privacy, but I would prefer this kind of refactoring:

* Move `visibility` levels to Authz to be shared among all entities as Nico has mentioned
* Move the Library-related Authz methods that Content is mooching off of Discussions for into a `LibraryAPI.Authz.*` API that both Discussions and Content can use appropriately

I backed out of these changes just because of the other significant changes in the PR already, and potentially leaving an incomplete mess behind before my vacation.

5. Extracted a Locking API out of the Activity Cluster stuff. This was not necessary to this PR, but I did it in anticipation of introducing some locking mechanics to the library, and determined that it wasn't going to save us from much other than what simple auto-repair would. I decided not to revert those changes since its full functionality is tested by virtue of the activity cluster unit tests, and it is generic functionality that can be useful elsewhere.

Not in this PR:

* Some unit tests have TODO's. I plan on continuing those through-out this week, but they should not unveil significant changes to the core code
* Search and Activity is not done

About Search: When a new message is posted for a discussion, we cannot fetch all messages and re-index the text. Instead it would be best to try and use a parent-child relationship between Discussion->Message documents. This means that the search API needs to unlock the ability to plug it in for a consumer

About Activity: Should be pretty straight-forward. I believe it routes just like comments do with content. The "Recent Commenters" is now known as "Recent Contributors" and is handled automatically by the MessageBoxAPI, so it should just be a matter of doing the modelling required for the activity entities.