Done when
- The dropdown query returns readable rows: kind, actor's username, post title (empty for follows), time.
- "Mark all as read" drops the bell count to zero and the dropdown to empty.
- Every bad insert in step 6 is rejected by the database.
- You can defend each decision in your design to someone who would have done it differently.
When this works, you've done the whole loop on your own: model a feature, constrain it, write to it, read from it, and make it fast. That loop is most of practical SQL.