ActivityPub in OCaml using jsont/eio/requests
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update PLAN.md to reflect implementation progress

Mark completed phases: HTTP signatures, activity delivery, outbox
operations, follow protocol, NodeInfo, and most proto properties.
Note remaining work: location/preview fields, Question activity, and
CLI commands for post/follow/like/boost.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+67 -61
+67 -61
PLAN.md
··· 5 5 The `requests` library already provides RFC 9421 HTTP Message Signatures via `Requests.Signature`. 6 6 This simplifies Phase 1 significantly - we just need to integrate the existing signing. 7 7 8 - ## Phase 1: Integrate HTTP Signatures ✓ (requests library) 8 + ## Phase 1: Integrate HTTP Signatures ✓ 9 9 10 10 The requests library provides: 11 11 - `Signature.config` - signing configuration with key, keyid, components ··· 15 15 - `Signature.verify` - verify signatures 16 16 - `Signature.Content_digest` - body digest computation 17 17 18 - ### 1.1 Update Apubt.Signing 18 + ### 1.1 Update Apubt.Signing ✓ 19 19 - [x] Already has key_id and private_key fields 20 - - [ ] Add proper Key.t construction from PEM 21 - - [ ] Configure default signed components for ActivityPub 20 + - [x] Add proper Key.t construction from PEM 21 + - [x] Configure default signed components for ActivityPub 22 22 23 - ### 1.2 Integrate into Http.post 24 - - [ ] Create signature config from Apubt.Signing 25 - - [ ] Sign requests before sending 26 - - [ ] Add Content-Digest for POST bodies 23 + ### 1.2 Integrate into Http.post ✓ 24 + - [x] Create signature config from Apubt.Signing 25 + - [x] Sign requests before sending 26 + - [x] Add Content-Digest for POST bodies 27 27 28 - ## Phase 2: Activity Delivery 28 + ## Phase 2: Activity Delivery ✓ 29 29 30 - ### 2.1 Inbox Delivery 31 - - [ ] `Inbox.post` - POST signed activity to inbox URI 32 - - [ ] `Inbox.post_to_actor` - resolve inbox from actor, deliver 33 - - [ ] `Inbox.post_to_shared_inbox` - batch delivery to shared inbox 30 + ### 2.1 Inbox Delivery ✓ 31 + - [x] `Inbox.post` - POST signed activity to inbox URI 32 + - [x] `Inbox.post_to_actor` - resolve inbox from actor, deliver 33 + - [x] `Inbox.post_to_shared_inbox` - batch delivery to shared inbox 34 34 35 - ### 2.2 Recipient Resolution 36 - - [ ] Extract recipients from to/cc/bto/bcc fields 37 - - [ ] Dereference collection URIs to get actor list 38 - - [ ] Handle Public collection (use shared inbox) 39 - - [ ] De-duplicate recipients 35 + ### 2.2 Recipient Resolution ✓ 36 + - [x] Extract recipients from to/cc/bto/bcc fields 37 + - [x] Dereference collection URIs to get actor list 38 + - [x] Handle Public collection (use shared inbox) 39 + - [x] De-duplicate recipients 40 40 41 - ## Phase 3: Outbox Operations 41 + ## Phase 3: Outbox Operations ✓ 42 42 43 - ### 3.1 Note Creation 44 - - [ ] `Outbox.create_note` - construct Create(Note) activity 45 - - [ ] `Outbox.public_note` - to: Public, cc: followers 46 - - [ ] `Outbox.followers_only_note` - to: followers only 47 - - [ ] `Outbox.direct_note` - to: specific actors 48 - - [ ] Generate unique activity/object IDs 43 + ### 3.1 Note Creation ✓ 44 + - [x] `Outbox.create_note` - construct Create(Note) activity 45 + - [x] `Outbox.public_note` - to: Public, cc: followers 46 + - [x] `Outbox.followers_only_note` - to: followers only 47 + - [x] `Outbox.direct_note` - to: specific actors 48 + - [x] Generate unique activity/object IDs 49 49 50 - ### 3.2 Interactions 51 - - [ ] `Outbox.like` - Like activity 52 - - [ ] `Outbox.unlike` - Undo(Like) 53 - - [ ] `Outbox.announce` - boost/reblog 54 - - [ ] `Outbox.unannounce` - Undo(Announce) 50 + ### 3.2 Interactions ✓ 51 + - [x] `Outbox.like` - Like activity 52 + - [x] `Outbox.unlike` - Undo(Like) 53 + - [x] `Outbox.announce` - boost/reblog 54 + - [x] `Outbox.unannounce` - Undo(Announce) 55 55 56 - ### 3.3 Modifications 57 - - [ ] `Outbox.delete` - Delete with Tombstone 58 - - [ ] `Outbox.update_note` - Update activity 56 + ### 3.3 Modifications ✓ 57 + - [x] `Outbox.delete` - Delete with Tombstone 58 + - [x] `Outbox.update_note` - Update activity 59 59 60 - ## Phase 4: Follow Protocol 60 + ## Phase 4: Follow Protocol ✓ 61 61 62 - ### 4.1 Outgoing Follows 63 - - [ ] `Actor.follow` - send Follow to target inbox 64 - - [ ] `Actor.unfollow` - send Undo(Follow) 62 + ### 4.1 Outgoing Follows ✓ 63 + - [x] `Actor.follow` - send Follow to target inbox 64 + - [x] `Actor.unfollow` - send Undo(Follow) 65 65 66 - ### 4.2 Incoming Follows 67 - - [ ] `Actor.accept_follow` - send Accept(Follow) 68 - - [ ] `Actor.reject_follow` - send Reject(Follow) 66 + ### 4.2 Incoming Follows ✓ 67 + - [x] `Actor.accept_follow` - send Accept(Follow) 68 + - [x] `Actor.reject_follow` - send Reject(Follow) 69 69 70 - ## Phase 5: Missing Proto Properties 70 + ## Phase 5: Missing Proto Properties (Partial) 71 71 72 - ### 5.1 Actor Properties 73 - - [ ] `also_known_as: Uri.t list option` 74 - - [ ] `discoverable: bool option` 75 - - [ ] `suspended: bool option` 76 - - [ ] `moved_to: Uri.t option` 77 - - [ ] `featured: Uri.t option` 78 - - [ ] `featured_tags: Uri.t option` 72 + ### 5.1 Actor Properties ✓ 73 + - [x] `also_known_as: Uri.t list option` 74 + - [x] `discoverable: bool option` 75 + - [x] `suspended: bool option` 76 + - [x] `moved_to: Uri.t option` 77 + - [x] `featured: Uri.t option` 78 + - [x] `featured_tags: Uri.t option` 79 79 80 - ### 5.2 Object Properties 81 - - [ ] `context: Uri.t option` (conversation threading) 82 - - [ ] `audience: Recipient.t list option` 80 + ### 5.2 Object Properties (Partial) 81 + - [x] `conversation: Uri.t option` (conversation threading) 82 + - [x] `audience: Recipient.t list option` 83 83 - [ ] `location` support 84 84 - [ ] `preview: Link_or_uri.t option` 85 85 ··· 88 88 - [ ] `any_of: Object.t list option` 89 89 - [ ] `closed: Datetime.t option` 90 90 91 - ## Phase 6: NodeInfo 91 + ## Phase 6: NodeInfo ✓ 92 92 93 - - [ ] Fetch `/.well-known/nodeinfo` 94 - - [ ] Parse nodeinfo links for schema 2.0/2.1 95 - - [ ] Fetch and decode nodeinfo document 93 + - [x] Fetch `/.well-known/nodeinfo` 94 + - [x] Parse nodeinfo links for schema 2.0/2.1 95 + - [x] Fetch and decode nodeinfo document 96 96 97 97 ## Phase 7: CLI Enhancements 98 98 99 + Current commands: 100 + - [x] `apub webfinger` - look up account via Webfinger 101 + - [x] `apub actor` - fetch an ActivityPub actor 102 + - [x] `apub outbox` - fetch an actor's outbox 103 + 104 + Planned: 99 105 - [ ] `apub post` - create and post a note 100 106 - [ ] `apub follow` - follow an actor 101 107 - [ ] `apub like` - like a post ··· 104 110 ## Implementation Order 105 111 106 112 ``` 107 - Phase 1.1-1.2 (Signing integration) 113 + Phase 1.1-1.2 (Signing integration) ✓ 108 114 109 - Phase 2 (Delivery) ──→ Phase 4 (Follow) 115 + Phase 2 (Delivery) ✓ ──→ Phase 4 (Follow) ✓ 110 116 111 - Phase 3 (Outbox) 117 + Phase 3 (Outbox) ✓ 112 118 113 - Phase 7 (CLI) 119 + Phase 7 (CLI) - in progress 114 120 115 - Phase 5 (Properties) - parallel 116 - Phase 6 (NodeInfo) - parallel 121 + Phase 5 (Properties) ✓ (partial - missing location, preview, Question) 122 + Phase 6 (NodeInfo) ✓ 117 123 ```