ActivityPub in OCaml using jsont/eio/requests
ActivityPub Implementation Plan#
Overview#
The requests library already provides RFC 9421 HTTP Message Signatures via Requests.Signature.
This simplifies Phase 1 significantly - we just need to integrate the existing signing.
Phase 1: Integrate HTTP Signatures ✓#
The requests library provides:
Signature.config- signing configuration with key, keyid, componentsSignature.Key- Ed25519, RSA, ECDSA P-256/P-384, HMAC keysSignature.sign- sign request headersSignature.sign_with_digest- sign with Content-Digest (RFC 9530)Signature.verify- verify signaturesSignature.Content_digest- body digest computation
1.1 Update Apubt.Signing ✓#
- Already has key_id and private_key fields
- Add proper Key.t construction from PEM
- Configure default signed components for ActivityPub
1.2 Integrate into Http.post ✓#
- Create signature config from Apubt.Signing
- Sign requests before sending
- Add Content-Digest for POST bodies
Phase 2: Activity Delivery ✓#
2.1 Inbox Delivery ✓#
-
Inbox.post- POST signed activity to inbox URI -
Inbox.post_to_actor- resolve inbox from actor, deliver -
Inbox.post_to_shared_inbox- batch delivery to shared inbox
2.2 Recipient Resolution ✓#
- Extract recipients from to/cc/bto/bcc fields
- Dereference collection URIs to get actor list
- Handle Public collection (use shared inbox)
- De-duplicate recipients
Phase 3: Outbox Operations ✓#
3.1 Note Creation ✓#
-
Outbox.create_note- construct Create(Note) activity -
Outbox.public_note- to: Public, cc: followers -
Outbox.followers_only_note- to: followers only -
Outbox.direct_note- to: specific actors - Generate unique activity/object IDs
3.2 Interactions ✓#
-
Outbox.like- Like activity -
Outbox.unlike- Undo(Like) -
Outbox.announce- boost/reblog -
Outbox.unannounce- Undo(Announce)
3.3 Modifications ✓#
-
Outbox.delete- Delete with Tombstone -
Outbox.update_note- Update activity
Phase 4: Follow Protocol ✓#
4.1 Outgoing Follows ✓#
-
Actor.follow- send Follow to target inbox -
Actor.unfollow- send Undo(Follow)
4.2 Incoming Follows ✓#
-
Actor.accept_follow- send Accept(Follow) -
Actor.reject_follow- send Reject(Follow)
Phase 5: Proto Properties ✓#
5.1 Actor Properties ✓#
-
also_known_as: Uri.t list option -
discoverable: bool option -
suspended: bool option -
moved_to: Uri.t option -
featured: Uri.t option -
featured_tags: Uri.t option
5.2 Object Properties ✓#
-
conversation: Uri.t option(conversation threading) -
audience: Recipient.t list option -
location: Link_or_uri.t option -
preview: Link_or_uri.t option
5.3 Question Activity ✓#
-
one_of: Object_ref.t list option -
any_of: Object_ref.t list option -
closed: Datetime.t option
Phase 6: NodeInfo ✓#
- Fetch
/.well-known/nodeinfo - Parse nodeinfo links for schema 2.0/2.1
- Fetch and decode nodeinfo document
Phase 7: CLI Enhancements ✓#
Current commands:
-
apub webfinger- look up account via Webfinger -
apub actor- fetch an ActivityPub actor -
apub outbox- fetch an actor's outbox -
apub post- create and post a note -
apub follow- follow an actor -
apub like- like a post -
apub boost- announce/reblog a post
Phase 8: WebFinger Integration ✓#
Integrated the webfinger library for RFC 7033/7565 compliant discovery:
- Use
Webfinger.query_acctfor proper acct URI handling - Support for percent-encoding in userparts
- Added
Webfinger.lookup_rawfor efficient direct JRD access - Added ActivityPub WebFinger spec to
spec/directory
Implementation Order#
Phase 1.1-1.2 (Signing integration) ✓
↓
Phase 2 (Delivery) ✓ ──→ Phase 4 (Follow) ✓
↓
Phase 3 (Outbox) ✓
↓
Phase 7 (CLI) ✓
↓
Phase 8 (WebFinger) ✓
Phase 5 (Properties) ✓
Phase 6 (NodeInfo) ✓
Completed#
All phases are now complete. The library provides:
- Full HTTP signature support (RFC 9421)
- Activity delivery to inboxes
- Outbox operations (create, like, boost, delete, update)
- Follow protocol (follow, unfollow, accept, reject)
- Question/poll activity support
- NodeInfo discovery
- Complete CLI with read and write operations
- RFC 7033/7565 compliant WebFinger via the
webfingerlibrary