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