docs: rewrite architecture diagram as mermaid
All checks were successful
lint / lint (push) Successful in 14m6s
test / unit (push) Successful in 15m45s

This commit is contained in:
2026-06-04 23:48:49 +02:00
parent 4d6df1ea60
commit 9aea5c1bd9

View File

@@ -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