v0.5.0 — codebase refinement, flexible API, architecture cleanup
All checks were successful
CI / fmt (push) Successful in 31s
CI / clippy (push) Successful in 4m0s
CI / test (push) Successful in 5m44s

Error handling:
  thiserror enum (NotFound/BadRequest/Unauthorized/Forbidden/Internal)
  eliminates 41 boilerplate .map_err() calls
  signature failures return 401, not 500

Named types:
  Keypair, LocalObject (with to/cc/bto/bcc addressing), Addressing

Readability:
  descriptive names everywhere, small functions, breathing room
  noisy comments removed, intent-explicit error handling (no let _ =)
  types.rs per module separating data from behavior

File organization:
  handlers/ module (actor, featured, followers, inbox, nodeinfo, outbox, webfinger)
  actors/ split (mod.rs + person.rs + types.rs)
  service/ split (builder, broadcast, collections, delivery, fetch, follow, lookup, types)
  tests next to modules

Repository traits:
  FollowRepository → 5 sub-traits (FollowerWriter/Reader, FollowingWriter/Reader, FollowMigration)
  ActorRepository → 3 sub-traits (KeypairRepository, RemoteActorCache, AnnounceRepository)
  BlocklistRepository → 2 sub-traits (DomainBlocklist, ActorBlocklist)
  supertraits with blanket impls — existing consumers unchanged
  FollowMigration has default no-op
  delete dead get_following_outbox_url

Testing:
  mock_repo! macro generates mock builders from compact specs
  MockFollowRepo, MockActorRepo, MockBlocklistRepo, MockActivityRepo,
  MockUserRepo, MockContentReader, MockObjectHandler, MockEventPublisher
  all hand-written test stubs replaced

Flexibility:
  UrlScheme trait — configurable URL patterns (DefaultUrlScheme = /users/{uuid})
  on_unknown_activity hook for custom AP extensions
  broadcast_raw_to_followers for arbitrary activity JSON
  broadcast_create/broadcast_update (renamed from Note-centric names)
  internal modules locked to pub(crate), clean public re-exports
  actor_handler, followers_handler, following_handler re-exported for custom routers

Security:
  SSRF: block IPv6-mapped private IPv4, TEST-NET, benchmarking, reserved ranges
  verify_attributed_to rejects missing/array attributedTo
  remove .expect() from outbox handler

Architecture:
  handlers/followers.rs delegates to serialize_ordered_collection (no more UrlScheme bypass)
  extract dispatch_sends, prepare_addressed_broadcast (eliminate duplication)
  DbActor::object_id(), RemoteActor::from/from_ap_person/placeholder
  send_activity unifies prepare+dispatch, deterministic_activity_id helper
  pass-through wrappers grouped in lookup.rs
This commit is contained in:
2026-07-25 17:01:44 +02:00
parent 17b57fb9b5
commit b569efe715
73 changed files with 3583 additions and 3160 deletions

View File

@@ -0,0 +1,36 @@
use anyhow::Result;
use async_trait::async_trait;
use super::types::FollowerStatus;
/// Write operations for follower relationships.
///
/// Used by:
/// - inbox handlers (Accept/Follow/Undo processing)
/// - `service/lookup.rs` (via `update_follower_status`, `remove_follower`)
#[async_trait]
pub trait FollowerWriter: Send + Sync {
async fn add_follower(
&self,
local_user_id: uuid::Uuid,
remote_actor_url: &str,
status: FollowerStatus,
follow_activity_id: &str,
) -> Result<()>;
async fn get_follower_follow_activity_id(
&self,
local_user_id: uuid::Uuid,
remote_actor_url: &str,
) -> Result<Option<String>>;
async fn remove_follower(
&self,
local_user_id: uuid::Uuid,
remote_actor_url: &str,
) -> Result<()>;
async fn update_follower_status(
&self,
local_user_id: uuid::Uuid,
remote_actor_url: &str,
status: FollowerStatus,
) -> Result<()>;
}