diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index de8ba61..df263c2 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -2,110 +2,153 @@ Hexagonal (ports & adapters) architecture. Dependencies point inward — adapters implement domain ports, application orchestrates use cases, presentation handles HTTP. +## Crate dependency graph + +```mermaid +graph TD + subgraph Entry Points + bootstrap["bootstrap
HTTP server, DI wiring"] + worker["worker
background job consumer"] + end + + subgraph Interface Layer + presentation["presentation
axum handlers, extractors, AppState"] + api_types["api-types
DTOs, OpenAPI"] + end + + subgraph Application Layer + application["application
use cases, FederationEventService"] + end + + subgraph Domain Layer + domain["domain
models, value objects, events, port traits"] + end + + subgraph Adapters + postgres["postgres
UserRepo, ThoughtRepo, LikeRepo,
BoostRepo, FollowRepo, BlockRepo,
TagRepo, FeedRepo, FederationContentRepo, ...
"] + activitypub["activitypub
FederationActionPort,
FederationBroadcastPort,
FederationSchedulerPort
(wraps k-ap)
"] + postgres_fed["postgres-federation
k-ap DB traits"] + postgres_search["postgres-search
SearchPort"] + auth["auth
AuthService, ApiKeyService"] + nats["nats
EventPublisher, EventConsumer"] + storage["storage
MediaStore"] + event_transport["event-transport
event delivery"] + event_payload["event-payload
event serialization"] + end + + bootstrap --> presentation + bootstrap --> application + bootstrap --> postgres + bootstrap --> postgres_fed + bootstrap --> postgres_search + bootstrap --> activitypub + bootstrap --> auth + bootstrap --> nats + bootstrap --> storage + bootstrap --> event_transport + bootstrap --> event_payload + + worker --> application + worker --> activitypub + worker --> postgres + worker --> postgres_fed + worker --> nats + worker --> event_transport + worker --> event_payload + + presentation --> application + presentation --> api_types + presentation --> domain + + application --> domain + + postgres --> domain + activitypub --> domain + postgres_fed -.-> domain + postgres_search --> domain + postgres_search --> postgres + auth --> domain + nats --> domain + storage --> domain + event_transport --> domain + event_payload --> domain ``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ ENTRY POINTS │ -│ │ -│ ┌─────────────┐ ┌──────────┐ │ -│ │ bootstrap │ │ worker │ │ -│ │ (HTTP srv) │ │ (bg jobs) │ │ -│ └──────┬───────┘ └─────┬─────┘ │ -│ │ wires all deps │ consumes events │ -└─────────┼────────────────────────┼──────────────────────────────────────┘ - │ │ - ▼ ▼ -┌─────────────────────────────────────────────────────────────────────────┐ -│ INTERFACE LAYER │ -│ │ -│ ┌──────────────────┐ ┌────────────┐ │ -│ │ presentation │ │ api-types │ │ -│ │ (axum handlers, │◄───│ (DTOs, │ │ -│ │ extractors, │ │ OpenAPI) │ │ -│ │ AppState) │ └────────────┘ │ -│ └────────┬──────────┘ │ -│ │ calls use cases │ -└───────────┼─────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────────┐ -│ APPLICATION LAYER │ -│ │ -│ ┌─────────────────────────────────────────────┐ │ -│ │ application │ │ -│ │ │ │ -│ │ use_cases/ │ │ -│ │ thoughts, social, profile, │ │ -│ │ federation_management │ │ -│ │ │ │ -│ │ services/ │ │ -│ │ FederationEventService │ │ -│ │ (processes domain events → broadcasts) │ │ -│ └──────────────────┬──────────────────────────┘ │ -│ │ depends only on domain ports │ -└─────────────────────┼───────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────────┐ -│ DOMAIN LAYER (core) │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ domain │ │ -│ │ │ │ -│ │ models/ value_objects/ events/ errors/ │ │ -│ │ Thought UserId DomainEvent DomainErr │ │ -│ │ User ThoughtId EventEnvelope │ │ -│ │ RemoteActor Username │ │ -│ │ Follow,Like Content │ │ -│ │ Boost,Block Email │ │ -│ │ Notification PasswordHash │ │ -│ │ Tag,FeedEntry │ │ -│ │ │ │ -│ │ ports/ (trait interfaces) │ │ -│ │ UserRepository FederationContentRepository │ │ -│ │ ThoughtRepository FederationBroadcastPort │ │ -│ │ LikeRepository FederationLookupPort │ │ -│ │ BoostRepository FederationFollowPort │ │ -│ │ FollowRepository FederationFollowRequestPort │ │ -│ │ BlockRepository FederationFetchPort │ │ -│ │ TagRepository FederationBlockPort │ │ -│ │ NotificationRepository FederationSchedulerPort │ │ -│ │ FeedRepository FederationActionPort (supertrait) │ │ -│ │ SearchPort EventPublisher / EventConsumer │ │ -│ │ AuthService MediaStore / OutboxWriter │ │ -│ │ PasswordHasher RemoteActorConnectionRepository │ │ -│ │ ApiKeyRepository EngagementRepository │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────┘ - ▲ - │ implements ports - │ -┌─────────────────────────────────────────────────────────────────────────┐ -│ ADAPTER LAYER │ -│ │ -│ ┌──────────────────┐ ┌─────────────────────┐ ┌──────────────────┐ │ -│ │ postgres │ │ activitypub │ │ auth │ │ -│ │ │ │ │ │ │ │ -│ │ UserRepository │ │ FederationActionPort│ │ AuthService │ │ -│ │ ThoughtRepo │ │ FederationBroadcast │ │ ApiKeyService │ │ -│ │ LikeRepo │ │ FederationContent.. │ └──────────────────┘ │ -│ │ BoostRepo │ │ FederationScheduler │ │ -│ │ FollowRepo │ │ │ ┌──────────────────┐ │ -│ │ BlockRepo │ │ (wraps k-ap lib) │ │ storage │ │ -│ │ TagRepo │ └─────────────────────┘ │ MediaStore │ │ -│ │ NotificationRepo │ └──────────────────┘ │ -│ │ ApiKeyRepo │ ┌─────────────────────┐ │ -│ │ TopFriendRepo │ │ postgres-federation │ ┌──────────────────┐ │ -│ │ FeedRepo │ │ (k-ap DB traits) │ │ nats │ │ -│ │ EngagementRepo │ └─────────────────────┘ │ EventPublisher │ │ -│ │ FederationContent│ │ EventConsumer │ │ -│ │ OutboxWriter │ ┌─────────────────────┐ └──────────────────┘ │ -│ │ RemoteActorRepo │ │ postgres-search │ │ -│ │ RemoteActorConn │ │ SearchPort │ ┌──────────────────┐ │ -│ └──────────────────┘ └─────────────────────┘ │ event-transport │ │ -│ │ event-payload │ │ -│ │ (serialization) │ │ -│ └──────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────┘ + +## Domain ports + +```mermaid +classDiagram + class domain { + <> + } + + namespace Data Ports { + class UserRepository { + <> + find_by_id() + find_by_username() + save() + update_profile() + } + class ThoughtRepository { + <> + save() + find_by_id() + delete() + update_content() + } + class LikeRepository { <> } + class BoostRepository { <> } + class FollowRepository { <> } + class BlockRepository { <> } + class TagRepository { <> } + class FeedRepository { <> } + class NotificationRepository { <> } + class EngagementRepository { <> } + class SearchPort { <> } + } + + namespace Federation Ports { + class FederationContentRepository { + <> + outbox_entries_for_actor() + find_remote_actor_id() + intern_remote_actor() + accept_note() + retract_note() + } + class FederationBroadcastPort { + <> + broadcast_create() + broadcast_delete() + broadcast_update() + broadcast_announce() + broadcast_like() + } + class FederationActionPort { + <> + } + class FederationLookupPort { <> } + class FederationFollowPort { <> } + class FederationFollowRequestPort { <> } + class FederationFetchPort { <> } + class FederationBlockPort { <> } + class FederationSchedulerPort { <> } + } + + namespace Infra Ports { + class EventPublisher { <> } + class EventConsumer { <> } + class AuthService { <> } + class PasswordHasher { <> } + class MediaStore { <> } + } + + FederationActionPort --|> FederationLookupPort + FederationActionPort --|> FederationFollowPort + FederationActionPort --|> FederationFollowRequestPort + FederationActionPort --|> FederationFetchPort + FederationActionPort --|> FederationBlockPort ``` ## Dependency rule