feat: per-entity federation privacy toggles for reviews and watchlist #7

Closed
opened 2026-06-10 09:47:46 +00:00 by GKaszewski · 1 comment
Owner

Background

UserSettings already has a federate_goals: bool toggle that gates whether goal events are published to the fediverse. However, ReviewLogged, WatchlistEntryAdded, and WatchlistEntryRemoved are federated unconditionally — there is no way for a user to keep their reviews or watchlist private.

Proposed changes

Add two new settings flags:

  • federate_reviews: bool — controls whether ReviewLogged and ReviewUpdated events are federated
  • federate_watchlist: bool — controls whether WatchlistEntryAdded and WatchlistEntryRemoved events are federated

Domain

crates/domain/src/models/user_settings.rs:

  • Add federate_reviews: bool and federate_watchlist: bool fields
  • Default both to true (preserves current behaviour for existing users)
  • Add getters and setters following the existing federate_goals pattern

crates/domain/src/ports.rs (UserSettingsRepository):

  • Add get_user_federate_reviews(&UserId) -> Result<bool, DomainError>
  • Add get_user_federate_watchlist(&UserId) -> Result<bool, DomainError>

Storage

New migration for both sqlite and postgres adapters:

ALTER TABLE user_settings ADD COLUMN federate_reviews BOOLEAN NOT NULL DEFAULT TRUE;
ALTER TABLE user_settings ADD COLUMN federate_watchlist BOOLEAN NOT NULL DEFAULT TRUE;

Federation event handler

crates/adapters/activitypub/src/event_handler.rs:

  • Gate ReviewLogged / ReviewUpdated on get_user_federate_reviews()
  • Gate WatchlistEntryAdded / WatchlistEntryRemoved on get_user_federate_watchlist()

Settings API + UI

  • Expose both flags in the settings GET/PUT endpoint
  • Add toggles to the settings page (HTML) and SPA settings view

Default values

Both default to true so existing users continue to federate reviews and watchlist entries without any action required. Users who want privacy opt out explicitly.

Affected files

  • crates/domain/src/models/user_settings.rs
  • crates/domain/src/ports.rs
  • crates/adapters/sqlite/src/user_settings.rs
  • crates/adapters/postgres/src/ (user_settings)
  • crates/adapters/sqlite/migrations/ (new migration)
  • crates/adapters/postgres/migrations/ (new migration)
  • crates/adapters/activitypub/src/event_handler.rs
  • crates/application/src/users/update_settings.rs
  • crates/presentation/src/handlers/ (settings endpoint)
  • crates/api-types/ (settings DTO)
## Background `UserSettings` already has a `federate_goals: bool` toggle that gates whether goal events are published to the fediverse. However, `ReviewLogged`, `WatchlistEntryAdded`, and `WatchlistEntryRemoved` are federated unconditionally — there is no way for a user to keep their reviews or watchlist private. ## Proposed changes Add two new settings flags: - `federate_reviews: bool` — controls whether `ReviewLogged` and `ReviewUpdated` events are federated - `federate_watchlist: bool` — controls whether `WatchlistEntryAdded` and `WatchlistEntryRemoved` events are federated ### Domain `crates/domain/src/models/user_settings.rs`: - Add `federate_reviews: bool` and `federate_watchlist: bool` fields - Default both to `true` (preserves current behaviour for existing users) - Add getters and setters following the existing `federate_goals` pattern `crates/domain/src/ports.rs` (`UserSettingsRepository`): - Add `get_user_federate_reviews(&UserId) -> Result<bool, DomainError>` - Add `get_user_federate_watchlist(&UserId) -> Result<bool, DomainError>` ### Storage New migration for both sqlite and postgres adapters: ```sql ALTER TABLE user_settings ADD COLUMN federate_reviews BOOLEAN NOT NULL DEFAULT TRUE; ALTER TABLE user_settings ADD COLUMN federate_watchlist BOOLEAN NOT NULL DEFAULT TRUE; ``` ### Federation event handler `crates/adapters/activitypub/src/event_handler.rs`: - Gate `ReviewLogged` / `ReviewUpdated` on `get_user_federate_reviews()` - Gate `WatchlistEntryAdded` / `WatchlistEntryRemoved` on `get_user_federate_watchlist()` ### Settings API + UI - Expose both flags in the settings GET/PUT endpoint - Add toggles to the settings page (HTML) and SPA settings view ## Default values Both default to `true` so existing users continue to federate reviews and watchlist entries without any action required. Users who want privacy opt out explicitly. ## Affected files - `crates/domain/src/models/user_settings.rs` - `crates/domain/src/ports.rs` - `crates/adapters/sqlite/src/user_settings.rs` - `crates/adapters/postgres/src/` (user_settings) - `crates/adapters/sqlite/migrations/` (new migration) - `crates/adapters/postgres/migrations/` (new migration) - `crates/adapters/activitypub/src/event_handler.rs` - `crates/application/src/users/update_settings.rs` - `crates/presentation/src/handlers/` (settings endpoint) - `crates/api-types/` (settings DTO)
Author
Owner

Performance note: the current pattern uses per-flag DB methods (get_user_federate_goals, etc.) — each is a separate query. With three flags, the event handler could issue up to 3 DB round-trips per federated event. Consider loading the full UserSettings once per event dispatch and reading all flags from the struct in memory instead.

**Performance note**: the current pattern uses per-flag DB methods (`get_user_federate_goals`, etc.) — each is a separate query. With three flags, the event handler could issue up to 3 DB round-trips per federated event. Consider loading the full `UserSettings` once per event dispatch and reading all flags from the struct in memory instead.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GKaszewski/movies-diary#7