docs: update README and architecture diagrams to reflect new ActivityPub features and user account management
Some checks failed
CI / Check / Test (push) Has been cancelled

This commit is contained in:
2026-06-30 02:31:40 +02:00
parent 5ae38c834a
commit 10c811d9a7
2 changed files with 14 additions and 9 deletions

View File

@@ -55,10 +55,10 @@ Open `http://localhost:3000`. The HTTP server and background worker start togeth
- People as first-class entities — browse by person via `GET /api/v1/people/{id}` and full credit history via `GET /api/v1/people/{id}/credits`; index populated automatically during TMDb enrichment
- RSS/Atom feed for public subscription (global and per-user)
- JWT authentication via cookie (HTML) or Bearer token (REST API)
- ActivityPub federation — follow/unfollow remote users, accept/reject/remove followers, federated reviews broadcast as `Note` objects with `#MoviesDiary` + `#MovieTitle` hashtags, paginated outbox, boost/Announce tracking, NodeInfo discovery endpoint, shared inbox delivery, actor profile sync (bio, avatar, discoverable)
- Federation moderation — instance-level domain blocking (admin-managed), per-user actor blocking with `Block` activity, delivery filter excludes blocked actors and blocked-domain inboxes
- ActivityPub federation — follow/unfollow remote users, accept/reject/remove followers, federated reviews broadcast as `Note` objects with movie poster image attachment, `#MoviesDiary` + `#MovieTitle` hashtags, paginated outbox (reviews, watchlist entries, goals), boost/Announce tracking, NodeInfo discovery endpoint, shared inbox delivery, actor profile sync (bio, avatar, discoverable); account migration via `Move` activity; account deletion broadcasts `Delete` actor to followers
- Federation moderation — instance-level domain blocking (admin-managed), per-user actor blocking with `Block` / `Undo Block` activities, delivery filter excludes blocked actors and blocked-domain inboxes
- Watchlist — add movies to watch later, per-user; federated watchlist entries visible for remote actors
- User profiles — display name, bio, avatar, banner, custom profile fields; editable via HTML settings page or REST API
- User profiles — display name, bio, avatar, banner, custom profile fields; editable via HTML settings page or REST API; account deletion broadcasts AP `Delete` actor activity; `alsoKnownAs` change triggers AP `Move` for account migration
- Jellyfin/Plex auto-import — media server sends a webhook on playback stop, movies land in a watch queue; review and confirm with a rating to create diary entries; per-user webhook tokens with SHA-256 auth; setup UI at `/settings/integrations`
- Annual Wrap-Up — Spotify Wrapped for movies: per-user and instance-wide year-in-review with stats (top directors, actors, genres, rating distribution, watch time, rewatches, budget analysis), shareable HTML page at `/wrapups/{user_id}/{year}`; admin-triggered or auto-generated in January
- Goals — set a "watch N movies in YEAR" target with a progress bar; progress computed from existing reviews (backwards compatible); per-user federation toggle in settings; displayed on profile (SPA: interactive with create/edit/delete, classic HTML: read-only glassmorphic card)
@@ -102,7 +102,7 @@ adapters/
image-storage — stores images (posters + user avatars) on local filesystem or S3-compatible storage
poster-sync — event handler: triggers poster fetch+store on MovieDiscovered
image-converter — optional background worker: converts stored images to AVIF or WebP; backfills existing images via a 24h periodic job
tmdb-enrichment — event handler: fetches full movie profile (cast, crew, genres, keywords, box office) from TMDb on MovieEnrichmentRequested; resolves IMDb IDs automatically
tmdb-enrichment — TMDb HTTP client implementing MovieEnrichmentClient and PersonEnrichmentClient; event handlers (MovieEnrichmentHandler, PersonEnrichmentHandler) live in the application layer
template-askama — Askama HTML rendering
rss — RSS/Atom feed generation
export — CSV and JSON diary serialization

View File

@@ -15,9 +15,9 @@ graph TB
subgraph UseCases["Use Cases"]
UC_AUTH["auth<br/>login, register"]
UC_DIARY["diary<br/>log_review, get_diary,<br/>get_activity_feed, export"]
UC_MOVIES["movies<br/>get_movies, get_movie_profile,<br/>enrich_movie, request_enrichment,<br/>sync_poster, reindex_search"]
UC_MOVIES["movies<br/>get_movies, get_movie_profile,<br/>enrich_movie, request_enrichment,<br/>sync_poster, reindex_search,<br/>merge_duplicates"]
UC_IMPORT["import<br/>create_session, apply_mapping,<br/>execute, profiles"]
UC_USERS["users<br/>get_users, get_profile,<br/>update_profile"]
UC_USERS["users<br/>get_users, get_profile,<br/>update_profile, delete_account"]
UC_WATCHLIST["watchlist<br/>add, remove, get"]
UC_WRAPUP["wrapup<br/>generate, compute,<br/>list, delete"]
UC_GOALS["goals<br/>create, update, delete,<br/>get, list"]
@@ -26,17 +26,22 @@ graph TB
UC_PERSON["person<br/>get, get_credits"]
end
subgraph EventHandlers["Event Handlers"]
EH_ENRICH["EnrichmentHandler"]
EH_MOVIE["MovieEnrichmentHandler<br/><i>on MovieEnrichmentRequested</i>"]
EH_PERSON["PersonEnrichmentHandler<br/><i>on PersonEnrichmentRequested</i>"]
EH_DISCOVER["MovieDiscoveryIndexer"]
EH_CLEANUP["SearchCleanupHandler"]
EH_REINDEX["SearchReindexHandler"]
EH_WRAPUP["WrapUpEventHandler"]
EH_AP["ActivityPubEventHandler<br/><i>reviews, watchlist, goals,<br/>UserDeleted, UserAccountMoved</i>"]
end
subgraph Jobs["Periodic Jobs"]
JOB_IMPORT["ImportSessionCleanup"]
JOB_WATCH["WatchEventCleanup"]
JOB_STALE["EnrichmentStaleness"]
JOB_WRAPGEN["WrapUpAutoGenerate"]
JOB_WRAPCLEAN["WrapUpCleanup"]
JOB_SESSION["RefreshSessionCleanup"]
JOB_DEDUP["MovieDeduplication<br/><i>merge duplicate movie<br/>records (daily)</i>"]
end
WORKER_SVC["WorkerService<br/><i>Semaphore(8), JoinSet,<br/>shutdown signal</i>"]
end
@@ -54,7 +59,7 @@ graph TB
M_SEARCH["SearchQuery,<br/>SearchResults"]
end
subgraph Ports["Port Traits (Interfaces)"]
P_REPOS["MovieRepository<br/>ReviewRepository<br/>DiaryRepository<br/>UserRepository<br/>WatchlistRepository<br/>WatchEventRepository<br/>WebhookTokenRepository<br/>ImportSessionRepository<br/>MovieProfileRepository<br/>WrapUpRepository<br/>GoalRepository<br/>UserSettingsRepository"]
P_REPOS["MovieRepository<br/>ReviewRepository<br/>DiaryRepository<br/>UserRepository<br/>WatchlistRepository<br/>WatchEventRepository<br/>WebhookTokenRepository<br/>ImportSessionRepository<br/>MovieProfileRepository<br/>WrapUpRepository<br/>GoalRepository<br/>UserSettingsRepository<br/>MovieDeduplicator"]
P_SERVICES["AuthService<br/>MetadataClient<br/>PosterFetcherClient<br/>ObjectStorage<br/>EventPublisher<br/>EventConsumer<br/>PasswordHasher<br/>DiaryExporter<br/>DocumentParser"]
P_SEARCH["SearchPort<br/>SearchCommand<br/>PersonQuery<br/>PersonCommand"]
P_FEDERATION["SocialQueryPort<br/>LocalApContentQuery<br/>RemoteWatchlistRepository<br/>RemoteGoalRepository"]
@@ -63,7 +68,7 @@ graph TB
DS_WRAPUP["WrapUpAnalyzer<br/><i>build_report, compute_*</i>"]
DS_REVIEW["ReviewHistoryAnalyzer<br/><i>rating_trend</i>"]
end
EVENTS["DomainEvent enum<br/><i>ReviewLogged, MovieDiscovered,<br/>GoalCreated, GoalUpdated,<br/>SearchReindexRequested, ...</i>"]
EVENTS["DomainEvent enum<br/><i>ReviewLogged, MovieDiscovered,<br/>GoalCreated, GoalUpdated,<br/>UserDeleted, UserAccountMoved,<br/>SearchReindexRequested, ...</i>"]
VO["Value Objects<br/><i>MovieId, UserId, Rating,<br/>Email, Username, Password, ...</i>"]
end