
La Ruche
Academic team project · In active development
What it was
La Ruche is a discussion forum reserved for the students of a Montréal cégep. Discussions live in groups: subject groups for coursework, created by the administration, and interest groups proposed by students, which stay pending until an administrator approves them. Members post, comment and report content, and each group has its own moderators and its own ban list.
Two teams of four are building it: a FastAPI REST API whose openapi.yml file is the contract every response is tested against, and a Kotlin Android client in MVP. A web app and an admin app are planned against the same API. The Android app still runs on simulated data; connecting it to the API is the next step.
What I owned
On the API, the users collection end to end (create, read, filter, update, delete), the end-to-end tests for groups and posts, the helper that checks each response against the OpenAPI contract, and the Docker and CI setup. I also wrote the sprint 3 refactoring plan. On the Android app, the post, new-post, profile and joined-groups screens, with their presenters tested against fake views.
The hard part
The hard part has been visibility. The same post can be shown, hidden or a 404 depending on who asks: a pending or refused group is visible only to its creator and administrators, a deleted group only to administrators, a deleted post only to its author, the group's moderators and administrators. Each rule has to hold on every route that can reach the content, nested ones included, and most of my API fixes were a route that let one slip, such as a post in a deleted group still being served.
Sign-up had a race of its own. FastAPI runs synchronous routes on a thread pool, so two simultaneous registrations could both pass the uniqueness check on a username or email. The check and the write now happen under one lock, with the slow password hashing done before taking it.
What I would do differently
That lock only protects one process holding its data in memory. With MariaDB in sprint 3, uniqueness belongs in a UNIQUE constraint, not in application code. The visibility rules are also restated route by route instead of living in one function, which is why the fixes came one route at a time.

