1
ActivityPub Primer
Gabriel Kaszewski edited this page 2026-05-29 02:07:40 +00:00

ActivityPub Primer

ActivityPub is a W3C standard protocol for federated social networking. Servers that implement it can exchange data with each other — a user on one instance can follow, like, or reply to content from a different instance, without either platform needing to know anything specific about the other.

This page covers only what you need to understand before working with k-ap. See the spec links at the bottom for depth.


Actors

An actor is anything that can perform actions in the federation — a user account, a bot, a relay, a service. Every actor has a stable URL that serves as its permanent ID.

When another server fetches that URL with the right Accept: application/activity+json header, it receives an actor JSON document:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1"
  ],
  "type": "Person",
  "id": "https://example.com/users/alice",
  "name": "Alice",
  "preferredUsername": "alice",
  "inbox": "https://example.com/users/alice/inbox",
  "outbox": "https://example.com/users/alice/outbox",
  "followers": "https://example.com/users/alice/followers",
  "following": "https://example.com/users/alice/following",
  "publicKey": { "..." }
}

Actor types include Person, Service, Application, Organization, and Group. k-ap supports all five — set via ApUser::actor_type.


Inboxes and Outboxes

Every actor has an inbox and an outbox:

  • Inbox — where other servers POST activities to deliver them to this actor
  • Outbox — a paginated collection of activities this actor has performed (readable by anyone)

When Alice on alpha.social posts a note, alpha.social wraps it in a Create activity and POSTs it to the inboxes of Alice's followers on other servers. Those servers then call their local handlers to process the delivery.

k-ap registers the inbox routes and handles the full receive → verify → dispatch cycle. You supply the handler callbacks via ApObjectHandler.


The Follow Model

Federation between two users on different servers works through explicit follows:

  1. Bob (beta.social) sends a Follow activity to Alice's inbox
  2. Alice's server responds with Accept (Bob is now a follower) or Reject
  3. Future activities Alice publishes are delivered to Bob's inbox

k-ap handles Follow, Accept, and Reject activities automatically. You implement FollowRepository to persist the follower graph.


Activities vs Objects

ActivityPub separates activities (things that happen) from objects (the content):

  • A Note is an object — a piece of content
  • A Create wrapping a Note is an activity — "this actor created this note"
  • A Like pointing at a Note is another activity — "this actor liked this note"
  • A Delete pointing at a Note's URL is another activity — "this actor deleted this note"

k-ap handles the activity layer. What goes inside Create, Update, etc. — your content types — is up to you. k-ap passes them through to your ApObjectHandler callbacks as raw serde_json::Value.


HTTP Signatures

Federation requires that servers prove the identity of the actor sending a request. This is done with HTTP Signatures: a cryptographic signature over request headers and body, verified by the receiving server against the sender's public key (fetched from the actor document).

k-ap handles HTTP signature creation for all outbound requests and verification for all inbound inbox deliveries. You generate RSA keypairs at user creation time and store them — k-ap fetches them via ActorRepository.


WebFinger

WebFinger is a discovery protocol that resolves a handle like @alice@example.com into an actor URL. A client sends a request to:

https://example.com/.well-known/webfinger?resource=acct:alice@example.com

and receives a JSON Resource Descriptor with the actor URL. k-ap registers the WebFinger route and serves the JRD automatically.