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
Some checks failed
CI / Check / Test (push) Has been cancelled
This commit is contained in:
@@ -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
|
- 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)
|
- RSS/Atom feed for public subscription (global and per-user)
|
||||||
- JWT authentication via cookie (HTML) or Bearer token (REST API)
|
- 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)
|
- 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` activity, delivery filter excludes blocked actors and blocked-domain inboxes
|
- 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
|
- 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`
|
- 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
|
- 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)
|
- 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
|
image-storage — stores images (posters + user avatars) on local filesystem or S3-compatible storage
|
||||||
poster-sync — event handler: triggers poster fetch+store on MovieDiscovered
|
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
|
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
|
template-askama — Askama HTML rendering
|
||||||
rss — RSS/Atom feed generation
|
rss — RSS/Atom feed generation
|
||||||
export — CSV and JSON diary serialization
|
export — CSV and JSON diary serialization
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ graph TB
|
|||||||
subgraph UseCases["Use Cases"]
|
subgraph UseCases["Use Cases"]
|
||||||
UC_AUTH["auth<br/>login, register"]
|
UC_AUTH["auth<br/>login, register"]
|
||||||
UC_DIARY["diary<br/>log_review, get_diary,<br/>get_activity_feed, export"]
|
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_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_WATCHLIST["watchlist<br/>add, remove, get"]
|
||||||
UC_WRAPUP["wrapup<br/>generate, compute,<br/>list, delete"]
|
UC_WRAPUP["wrapup<br/>generate, compute,<br/>list, delete"]
|
||||||
UC_GOALS["goals<br/>create, update, delete,<br/>get, list"]
|
UC_GOALS["goals<br/>create, update, delete,<br/>get, list"]
|
||||||
@@ -26,17 +26,22 @@ graph TB
|
|||||||
UC_PERSON["person<br/>get, get_credits"]
|
UC_PERSON["person<br/>get, get_credits"]
|
||||||
end
|
end
|
||||||
subgraph EventHandlers["Event Handlers"]
|
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_DISCOVER["MovieDiscoveryIndexer"]
|
||||||
EH_CLEANUP["SearchCleanupHandler"]
|
EH_CLEANUP["SearchCleanupHandler"]
|
||||||
EH_REINDEX["SearchReindexHandler"]
|
EH_REINDEX["SearchReindexHandler"]
|
||||||
EH_WRAPUP["WrapUpEventHandler"]
|
EH_WRAPUP["WrapUpEventHandler"]
|
||||||
|
EH_AP["ActivityPubEventHandler<br/><i>reviews, watchlist, goals,<br/>UserDeleted, UserAccountMoved</i>"]
|
||||||
end
|
end
|
||||||
subgraph Jobs["Periodic Jobs"]
|
subgraph Jobs["Periodic Jobs"]
|
||||||
JOB_IMPORT["ImportSessionCleanup"]
|
JOB_IMPORT["ImportSessionCleanup"]
|
||||||
JOB_WATCH["WatchEventCleanup"]
|
JOB_WATCH["WatchEventCleanup"]
|
||||||
JOB_STALE["EnrichmentStaleness"]
|
JOB_STALE["EnrichmentStaleness"]
|
||||||
JOB_WRAPGEN["WrapUpAutoGenerate"]
|
JOB_WRAPGEN["WrapUpAutoGenerate"]
|
||||||
|
JOB_WRAPCLEAN["WrapUpCleanup"]
|
||||||
|
JOB_SESSION["RefreshSessionCleanup"]
|
||||||
|
JOB_DEDUP["MovieDeduplication<br/><i>merge duplicate movie<br/>records (daily)</i>"]
|
||||||
end
|
end
|
||||||
WORKER_SVC["WorkerService<br/><i>Semaphore(8), JoinSet,<br/>shutdown signal</i>"]
|
WORKER_SVC["WorkerService<br/><i>Semaphore(8), JoinSet,<br/>shutdown signal</i>"]
|
||||||
end
|
end
|
||||||
@@ -54,7 +59,7 @@ graph TB
|
|||||||
M_SEARCH["SearchQuery,<br/>SearchResults"]
|
M_SEARCH["SearchQuery,<br/>SearchResults"]
|
||||||
end
|
end
|
||||||
subgraph Ports["Port Traits (Interfaces)"]
|
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_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_SEARCH["SearchPort<br/>SearchCommand<br/>PersonQuery<br/>PersonCommand"]
|
||||||
P_FEDERATION["SocialQueryPort<br/>LocalApContentQuery<br/>RemoteWatchlistRepository<br/>RemoteGoalRepository"]
|
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_WRAPUP["WrapUpAnalyzer<br/><i>build_report, compute_*</i>"]
|
||||||
DS_REVIEW["ReviewHistoryAnalyzer<br/><i>rating_trend</i>"]
|
DS_REVIEW["ReviewHistoryAnalyzer<br/><i>rating_trend</i>"]
|
||||||
end
|
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>"]
|
VO["Value Objects<br/><i>MovieId, UserId, Rating,<br/>Email, Username, Password, ...</i>"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user