Socialwg/ActivityPub wide review

From W3C Wiki

This is a collection of "wide review" feedback for ActivityPub. See also the transition request document.

How to provide feedback

Read the Working Draft, or even better, Editor's Draft, and do any of the following:

  • File issues on the issue tracker
  • Email Chris Webber personally (who will put your comments publicly on the social working group wiki, though you can be anonymous if you like): send to cwebber AT dustycloud DOT org, with "ActivityPub" somewhere in the subject.
  • Send to the public-socialweb-comments list
  • Edit this wiki, if you have permission! (If you don't, see "email Chris Webber" above)

Calls for review

Feedback

Github issues

7 issues remaining open which were questions resulting in imminent editorial updates.

146 issues have been opened, by or on behalf of 27 different people, 14 of whom are not in the WG.


mray on encryption

User mray would like to see encryption. Chris Webber replies, saying that encryption doesn't exist currently in the spec, but the spec leaves open the possibility for encryption in the future. mray replies, expressing preference for OMEMO, should encryption come in the future.

Jason Robinson and Michael Vogel on the desirability of signatures, and how Diaspora does it

Jason Robinson and Michael Vogel both have experience implementing federation in Diaspora. They weighed in on the mailing lists with some useful information / commentary:

  • Jason Robinson's initial email, in which he says he has two problems with the spec: there are no signatures, and that messages should not be trusted from anywhere except via the original server.
  • Michael Vogel follows up, explaining how Diaspora handles signatures for verification, even allowing forwarding.

Later, Jason Robinson asked on twitter:

is there more clarity these days how remote content is authorized in ActivityPub? Since signatures were out AFAICR.

Chris Webber replies:

It's not clarified clearly. I think the optimal direction is Linked Data Signatures, but that work won't be ready in time.

Jason responds:

that would be awesome. It would allow many use cases that Diaspora protocol for example can handle, ie non-direct message delivery AFAIK anyway. By non-direct, I mean that a third party relay passes the message to the target.

Notably, a forwarding mechanism is now described in the spec, as well as an authenticatoin mechanism using either Linked Data Signatures or (a little bit more ambiguously) OAuth + JSON Web Signatures. The group has decided that no authentication method will be agreed upon at this time, but these are explained as possible ways forward.

Jason later expressed further on Diaspora about the ActivityPub and signatures, and other things

Joey Hess on "what properties apply, anyway?"

Joey Hess (of git-annex and many other fine quality softwares) gave this feedback on IRC, with permission to repost on the Wiki:

<joeyh> oh hmm, I did read the spec with an eye to writing a hakell library    
        (then found a haskell library already for the older version) ..        
                                                                        [10:10]
<joeyh> my main problem was it seemed difficult to get a complete list of      
        required and optional attributes for each message. And pagination      
        seemed super-complex.                                           [10:11]
<joeyh> ^^ that's re activitystreams, not activitypub                   [10:16]
<joeyh> for example,                                                           
        https://www.w3.org/TR/activitystreams-vocabulary/#dfn-link lists some  
        properties. The included example uses other properties including       
        "type" and "@context" that are not on the list.                 [10:24]
<paroneayea> joeyh: it's worth noting that "type" and "@context" come from      
             JSON-LD                                                    [14:01]
<paroneayea> this is described in the activitystreams-core document (not the    
             vocabulary one)
<paroneayea> joeyh: nonetheless, mind if I include your feedback on the wiki?
<joeyh> sure, go ahead
<paroneayea> great, thanks joeyh :)
<joeyh> it would be very useful, as an implementor, to have a list of required  
        and optional properties, with it clearly indicated which is which       
                                                                        [14:02]
<paroneayea> joeyh: It's an interesting point... I think there really aren't    
             any "required" properties in ActivityStreams other than supplying  
             the type (well, it'll default to "cobject"), though of course in   
             a federated setting, not applying a type makes no sense            
                                                                        [14:09]
<paroneayea> and some other properties not being supplied can also seem         
             nonsensical
<paroneayea> joeyh: I'll try to think of what properties I basically mandate    
             for thhe different things.  I think it applies most especially to   
             the wrapping activities                                    [14:10]
<joeyh> yes, maybe the distinction should be between properties generally to    
        be included, and optional ones or something
<paroneayea> for example, a Create post coming across the network really ought  
             to have an object
<paroneayea> you can't just create "null" :)
<paroneayea> joeyh: recording that feedback, and I'll make an issue to look it  
             over for any of the objects we have where it seems required.       

And here's an issue filed based on this feedback.

Stephen Webber's review

Stephen's comments are quoted, Christopher Allan Webber's replies inline (we sat down and went over this in person.)

Stephen Webber writes:

> Here you go, enjoy!
>
>
> Spelling:
>
> "cannot share, reuse or derive form another"
>
> This should be
>
> "cannot share, reuse or derive from another"
>
>
> Conformance:
>
> The key words get repeated here with only slight variations in wording, for
> seemingly no reason.
>
>
> Ordered Collections:
>
> The followers collection MUST be either an OrderedCollection or a
> Collection.
>
> Preferably, I'd specify the order explictly. Reverse chronological is
> arbitrary. This would make the spec more flexible. No one wants a spec to
> go unused because it doesn't quite meet their needs.

Steve is concerned that as implementations grow, someone will want to
implement a collection that's ordered in some other way, and will either
abuse OrderedCollection or just not use the spec.

I pointed out you could do something like this to make your own extended
Collection with its own definition of what ordering means.

{"@context": ["http://w3c/activitypub/", "http://steve.example/collectables"],
 "type": ["Collection", "SteveCollection"]}

Steve seemed satisfied with this, and was interested to know this is a
feature of json-ld, which is a dependency anyway.

> Public Addressing:
>
> {
>   "@context": "https://www.w3.org/ns/activitypub",
>   "id": "https://www.w3.org/ns/activitypub/Public",
>   "type": "Collection"
> }
>
> Is the indicator that a resource is public really indicated by the URI
> itself? Splicing strings to extract information is rarely hygenic - It
> seems like it's inviting Bobby Table-esque naming conflicts
>

Steve is fine with it with understanding that Public this is effectively
a primitive, bound to this very specific URI.

> Ambiguity:
>
> Clients MAY address new Activities to the user's Followers Collection or
> the Public Collection by default.
>
> "Either or" OR "and or" ? Seems like "and or", in which case it's not a big
> deal.

Okay, clarified as and/or.

> Behavior of Like:
>
>   "to": ["https://rhiaro.co.uk/#amy",
>          "https://dustycloud.org/followers",
>          "https://rhiaro.co.uk/followers/"],
>
> Amy should decide whether the like is forwarded to followers. If Chris and
> Amy decide that they follow a shared handling of Like, then I would expect
> Chris MUST respect this agreement. Otherwise, responsibility is muddled.
> Amy could still decide the behavior of Like at runtime, and foward her
> behavior to Chris.
>

Steve wasn't aware that this part was talking about "Chris the client"
doing the Like as opposed to "Chris the server".  We should make this
more clear, as that might confuse others.

> Autowrapping:
>
> "which will be wrapped in a Create activity by the server"
>
> I have a mild adversion to optional behavior dependent on the validation of
> an object. It can be easy to get wrong or forget about a use case (for a
> contrived example, you may want to be able to nest Create messages, but
> this behavior prevents it). I would always wrap the object with a Create
> activity.

Steve feels that it's bad to be ambiguous about this behavior.

For example, (Chris trying to explain his point) how do you know if an
extended type is an activity or not?  You might accidentally wrap in
Create when you shouldn't.

Steve relates to SQL injection problems, when you have a special case
based on a special character, and you don't know contextually what case
you're in, and you do the wrong thing.

> Odd object model:
>
> "If an Activity is submitted with a value in the id property, servers MUST
> ignore this and generate a new id for the Activity"
>
> This weird behavior is because the id is inside the object. Just wrap the
> whole thing in an object field and slap a new id on. Why modify the
> original object?

What we mean is that the client *can't* provide an id here, in reality,
because it's not the one instantiating ids.

But, Steve says this was clear, just frustrating.

> Client to Server and Server to Server:
>
> There are really two different specs here. Client to Server is many to one
> with an implicit owner, and Server to Server is many to many with no owner.
> Even outside of section 7 and 8, they are special rules for both. Just a
> brain dump here.

Yes, that's true.

Explained to Steve the reasoning that we ended up with one document with
multiple sections.  He wwas happy to hear we thought about it.

> SHOULD and SHOULD NOT:
>
> Recommendations of SHOULD or SHOULD NOT seem superfluous to me. They can
> lead to confusion for implemention. I would use MAY and MAY NOT wherever
> SHOULD and SHOULD NOT are used. Some people may want to rely on SHOULD
> level recommendations, and introduce bugs. I realize this is subjective,
> and perhaps it's more successful in the open source community.
>
> You already know how to handle the difference between SHOULD/MAY and MUST:
>
> "All Objects in [ActivityStreams] should have unique global identifiers.
> ActivityPub extends this requirement; all objects distributed by the
> ActivityPub protocol MUST have unique global identifiers"
>
> Here you extend the ActivityStreams spec with the ActivityPub spec. If
> there is a SHOULD in your spec, it's probably because there is a use case
> that extends or implements ActivityStreams. Let's call this implicit and
> unnamed spec SocialPub. Change all the SHOULDs to MAY, and write a small
> extension spec "SocialPub" that specifies what MAYs are now MUSTs.

Yes those terms are confusing, and that's been discussed in the group...
but I feel like we're not going to solve it here.  Maybe we can improve
on it.

There's an issue to review all MUST / SHOULD / MAY etc, I'll keep that
in mind for this.

> Transactions:
>
> This is my biggest suggestion, and the least likely to gain traction.
>
> It is odd to me that "id" means something different for client to server
> than server to server. At the point of server to server the id tracks the
> object itself, but in client to server the id tracks the transaction. In
> several places in the spec, "id" is given special rules. It might benefit
> from consistent handling, as a transaction. I also wonder if there is a
> minor attack vector for spoofing, because no history is really being
> stored, and "id" is global.
>
> I think this model would be much simpler if it were based off a transaction
> log or blockchain, the same way that a filesystem or database maintains
> consistency. To get the number of likes, you count the number of likes on
> an item in the transaction log for instance, perhaps with caching for
> efficiency. Obviously a lot would be different, but this is how models like
> Datomic work. This would remove the side effects and some complexity.
> "Like" wouldn't have an inherent expected behavior in this model. Some
> clients might want to subscribe to "Like" transactions, while others won't
> care.

That's definitely a big overhaul. ;)

And I agree, I'm interested in this direction... and with the full ack
that it means cruft, I think that such a system can be built *on top* of
ActivityPub, even though it would mean possibly new
mostly-side-effect-free terms.

But I think that's a bigger research project than we have time for in
the group's charter.

Mats Sjöberg's feedback

Mats (also known as Sazius) is well known for his work on the Pump.io client Pumpa.

He gave extensive feedback, detailed below, with Christopher Allan Webber's responses inline:

<nowiki>
From: Christopher Allan Webber
To: Mats Sjöberg
Subject: Re: ActivityPub: comments on first third
Flags: seen
Date: Mon 31 Oct 2016 02:35:29 PM CDT
Maildir: /sent-to-misc

Mats Sjöberg writes:

> Hello,
>
> I started reading the ActivityPub spec from this URL
> https://w3c.github.io/activitypub/.  Unfortunately I only had time to
> read the first third today, but I thought I'd send you my notes so far
> (in case I don't get around to do more).  I'm not sure what types of
> things you want feedback on.  I review scientific papers constantly, so
> I'm used to reading things with a critical eye, also looking at the
> language and if things are expressed clearly.  In fact I don't have any
> critique of the actual spec so far :-)  And apologies for the blunt
> tone, it comes with "peer-review" :-)

Heya!  Thank you so much for doing it.  Sorry it took like... a month to
get all this feedback incorporated!  It turns out we got *way* more
feedback than I expected, which is I guess a good problem to have.

> Section 1.
>
> The word "activity" is used with many different meanings.  Activities
> are the things (data items) distributed by the ActivityPub implementing
> servers.  But also "are produced in response to a user performing an
> _activity_", and "causes the user's server to perform an _activity_ on
> behalf of the user".  Maybe it would be clearer to reserve the word
> "activity" for a single thing, i.e., what is distributed by ActivityPub
> servers, and then the server performs some "action" or some other synonym.

Thanks... I switched both cases of "performing an activity" to
"performing delivery of an activity", which I think is more consistent
with the rest of the document.

> Also activites are produced "in response to a user performing an
> activity", but are also "posted by a user to their outbox".  Sound like
> two different things to me.

Well, there are two things: the server generates the generation of the
ActivityStreams activity *object*, and then it delivers it.  Maybe it
could be better tuned, but i think this is not inconsistent with the
rest of the document.  It's probably helped by removing "performing
activity" at least... I hope :)

> Section 2.
>
> The same statement about "The key words ...  are to be interpreted as
> described in [RFC2119]." appears twice, and the "Conformance" title is
> repeated.

Fixed, thanks... this was a result of respec + putting in that text
manually.

> Section 2.1.
>
> "tying them into one social graph." => "tying them to the same social
> graph." ? Maybe there isn't One Social Graph, since the links can form
> several disjoint systems.

Good point; adjusted.

> Section 2.2.
>
> "A server handling an activity submitted by an authenticated actor to
> their outbox and handling _side_ client to server interaction effects
> appropriately." => an extraneous "side"?

Yeah, looks like I fixed this one already :)

> Section 3.
>
> "lays out" => a bit too casual?

Yeah good point; I removed "to get a sense of how this lays out"
entirely as it wasn't needed.

> 4.1
>
> The first mention of ActivityStreams is not linked to the spec, is that
> on purpose or a mistake?

Ok, I linked to it.

> What exactly is the proxyUrl for the actor?  I don't understand the
> description in the text. In pump.io today the proxyURL is a different
> URL for each object, and it is of course local to the server that the
> client is using.

Really?  Okay, in this design, an actor basically has a proxyURL for
their server, so it's like:

  https://dustycloud.org/api/proxyUrl

Then say I want to read https://sjoberg.fi/post/merry-xmas in my client,
but it's only readable for your collections of family and
friends... luckily in this scenario, I'm in your friends group!  :)

So, my client does a request like:

  https://dustycloud.org/api/proxyUrl?id=https%3A%2F%2Fsjoberg.fi%2Fpost%2Fmerry-xmas

... and it fetches that.  Since my client is authenticated, I retrieve
it.  It was admittedly underspecified; it didn't suggest using a form
property or etc.  I've updated it.

> (Oh, the source property is interesting, would definitely be useful for
> Pumpa! :-)

Good!  I thought so... it was part of the inspiration here. :)

> And feel free to publish this email publicly as you see fit.

Great!  I'll put it on the wiki after I get to your other emails :)

> Best regards,
> Mats

</nowiki>

<nowiki>
Mats Sjöberg writes:

> Hello again,
>
> Here is my next batch of ActivityPub notes.  Now I'm up to about 2/3 :-)
>
> Sorry for splitting them up, but I have about 1-1.5h of free time every
> evening, and wasn't sure how many evenings I could allocate to this.
>
> Posting to wiki is OK (as I said in the end of my previous email :-)
>
> Again, tone is blunt and peer-review-like :-)

Yay!

> ---
>
> Section 5.6.
>
> There's a "TODO" left there.  Should it still be there at this stage?

I think this was removed. :)

> Section 7.
>
> "Clients SHOULD check any objects attached to the Activity via the
> object, target, inReplyTo and/or tag fields, retrieve their actor or
> attributedTo properties, and MAY also retrieve their addressing
> properties, and add these to the to or cc fields of the new Activity
> being created."
>
> So "retrieve" here doesn't mean retrieve as in retrieving over the net
> with HTTP requests?  I'm just concerned that there is not a situation
> where the client has to do extra requests to get all the information
> needed, but that the server always includes the information needed
> inline.  I guess if you're reacting to an object in the client (i.e.
> creating an activity related to a visible object) it should already have
> everything in memory.
>
> Then I'm wondering why clients SHOULD check these objects, yet actually
> doing something with them is only a MAY. Or am I parsing the sentence
> wrong? If so, it should be written more clearly :-)

So yeah, the question of "should everything be embedded, or linked?"
ActivityPub doesn't require one way or the other... both are possible.

But, what I anticipate will happen in the "ecosystem" will be:
 - Servers will do "linking" to other objects by their id, and will
   likely transmit that from server <-> server.  This reduces cache
   invalidation problems of having to update old posts, and it is
   way less expensive to store than storing everything recursively.
   And, most importantly, unless an embedded post is of same-origin,
   sans signatures there's no way for a server to be sure that the
   embedded post is really what the original server claimed.  You have
   to go back and look it up.
 - However, for server->client it makes a lot of sense for the server to
   do all the work up front to embed things, since the client should
   trust their server in theory, and there's no reason to do multiple
   requests.

There's some risk here of not formalizing and requiring this, but I'm
hesitant to do that in this revision.  I feel like we need more
implementation experience before we put a requirement on it.  It's
possible that could end up being a mistake, but either direction could be.

> Otherwise I like that it's up to the client now, and the entire
> addressing is completely visible and transparent to the user.  Also
> objects have addressing, which solves a lot of problems seen in pump.io.

Great to hear!

> The activities in Example 7 and Example 8 are almost the same but have
> slightly different addressing ("https://rhiaro.co.uk/#amy" is missing in
> the latter).  More consistent to have the exact same activity?
>
;;

> Servers return HTTP 201 with the new URL in the Location header. Would
> it not also be good to get the newly created id?

Ooops, this meant the url of the id, not the "url" field.  I updated it
to just say "id".

> Section 7.1.
>
> "The Create activity is used to when" => extraneous "to"

Fixed!

> Section 7.5. and Section 7.6.
>
> What are Add and Remove exactly needed for?  Can Remove be used for
> unliking and unfollowing?

They're used from adding / removing from a collection... so I guess they
could be used for that.  Though I think Follow has some extra side
effects that may happen on the server, and Like doesn't even
*necessarily* have an associated collection...

> Section 7.8.
>
> Talks about users, but should it instead be actors?  Also the second
> occurrence of "user" now refers to the one doing the blocking?  Should
> be stated in a clearer way.

Good point, cleared it up!

> Section 7.9.
>
> I wonder if all activites have reasonable ways of being "undone"?  Could
> be tricky in some cases?  Would it not be safer to define explicit
> Unfollow and Unlike actions?

I agree that it's tricky.  I actually don't like "Undo", but I'm not a
spec editor on ActivityStreams.  My biggest complaint with AS2 is that
there was too much work to try to "pair down" AS2 as much as possible,
and I think that can have problems with overloading terms.  Oh well..

I pointed to the AS2 docs on inverse activities and undo though;
hopefully that'll help a bit.

Thank you!  Now to read/reply your third email...

</nowiki>

<nowiki>
Mats Sjöberg writes:

> Hello once more,
>
> My last comments after having read it through:
>
> ---
>
>
> Section 8.1.
>
> Is there a technical difference between to and cc targeting?  Or is it
> just semantic, as with email, i.e. for the human recipients to know the
> intention.

Semantic!

> So clients should/may (?) add actors for object, target, inReplyTo, or
> tag fields to to or cc (Section 7), but here it says that it is also the
> servers responsibility to notify them. ("Notification targeting: the
> actors for all objects in the object, target, inReplyTo or tag fields.")
> I suppose doing both is superfluous?

This was some cruft... the whole notification section has been dropped
and merged into the delivery section.  I think it's a lot clearer now.

> Is there some obvious reason why some activities are present in the
> client-to-server section, but not in the server-to-server section? Also
> the order could be the same in both?

Depends on what side effects are propagated in each section.  Any
activity can be propagated; its side effects are what need to be
defined.

Yeah, they ought to be the same order.  Fixed!

> The security stuff looks good, but I'm not an expert in that so I can't
> comment.  All in all, the spec looks good!  Thanks for all the work
> you've put into it!  I can't wait to see it adopted by pump.io and
> clients :-)

Good to hear.  Thanks for the kind words, and the really helpful review!

</nowiki>

Ben Sturmfels' feedback

Ben is a prominent contributor to MediaGoblin and an active participant on the Pump.io network.

Again, Chris Webber's replies are inline.

Ben Sturmfels writes:

> Hi Chris,
>
> Hopefully these comments aren't too late. I made it down to "8.2
> Delivery" this evening. Will continue tomorrow if that's still of any
> use.

Heya Ben!  Not too late, even if it looked that ways because *I* was so
late.  The spec got delayed a few times mainly because we did get so
much valuable feedback!

> Cheers,
> Ben
>
>
> 2.2 Candidate Recommendation Exit Criteria
> ------------------------------------------
> "derive form another qualifying implementation code" - should this
> be "derive from another qualifying implementation's code"?
>
> "side client to server interaction effects" - would "client to server
> interaction side effects" be more natural language here?

Fixed.

> 4 Actors
> --------
> Am I reading this right that users will log in as "example.org/alice/"
> rather than the more traditional "[email protected]"? It's a very minor
> thing, but there might need to be a workaround to allow the later
> format.

So yeah, the [email protected] uses webfinger.  ActivityPub took a
"follow your nose" approach which means that you go from link to link to
link to traverse the graph.  Webfinger uses /.well-known/ to look things
up, so at first glance it looks like there's no way for that to be
"follow your nose".  Luckily, there's a workaround!  There's a webfinger
URI scheme... so we can do webfingers as URIs after all.  We'll just
need to prefix them like "webfinger:[email protected]" or whatever it is
(I forget).  That's my understanding.

> 5.1 Followers Collection, 5.2 Following Collection
> --------------------------------------------------
> "Each actor MAY have a following collection" - does it matter that the
> ordering of "followers", "following" and SHOULD/MAY isn't consistent with 4.1 Actor
> Objects (SHOULD/SHOULD)?
>
> 5.3 Likes Collection
> --------------------
> "The following collection" should be "The likes collection".

Yeah, fixed!

> 6 Binary Data
> -------------
>
> "Upon successful submission a response containing the object with an ID
> is returned that can be posted to the users outbox." - this wording
> makes me confused about this is purely an upload and you must send out
> an activity as well to notify people, or whether the upload also
> notifies the "to" and "cc" recipients. If the notification is done
> automatically, then why would you also post to the user's outbox?

Heh, so I think the whole binary upload mechanism was confusing and I
long hated it.  I took the opportunity to give it an overhaul at last
minute into something more sane... it's now *one* post with a multipart
message, including the binary file for upload, as well as a shell
activitystreams object that the server finishes filling in.

So this whole bit changed very recently!  I did have a few people go
over it, so I think it'll be ok.  I never liked the old mechanism (which
was borrowed from an undocumented part of Pump.IO's api), and obviously
it's pretty important for our long term goals with MediaGoblin.

> Example 7
> ---------
>
> It looks as though the client gets to supply the "name" of "Like" activity.
> A receiving server would not be able to trust that this matches the
> expected patterns "[name] liked [object name]" - the client could put
> whatever they like here.

Yep, client can put whatever they like here.

It seems silly, right?  In my view the server will never make use of
this property because it should derive from its own knowledge of the
types.  The long story is: the "name" used to be two separate fields,
one for "user supplied name" and one for "a server's description of what
this activity is, in case you don't know this type and want a
fallback".  Those got merged together, and it's added confusion.
They'll be separated again soon, because this came up at the face to
face and nobody was happy.

So there's really no need for this name field, but I figured as long as
it's there it adds some clarity, but maybe it's just making it more
confusing.  I dunno, what do you think?  (This is non-normative, so it
doesn't need to be figured out in time for CR.)

> 8 Server to Server Interactions
> ------------------------------- 
>
> "unless it is intended to be transient" - I'm not clear on what a
> transient activity is.

I've added better descriptions about what transient means now... does
this make sense...?

    ActivityPub extends this requirement; all objects distributed by the
    ActivityPub protocol MUST have unique global identifiers, unless they
    are intentionally transient (short lived activities that are not
    intended to be able to be looked up, such as chat messages or game
    notifications).

Thanks for your review!  I'll also reply to your other emails.
Ben Sturmfels writes:

> Hi Chris,
>
> Sorry for the delay - continuing on...
>
> 8.2 Delivery
> ------------
> As discussed, maybe mention the full name "Linked Data Notifications"
> before the acronym.
>
> "property in the actor's profile" - perhaps say "recipient actor's
> profile" just to be clear.

This got refactored; hopefully it's clearer now.

> "In summary" - this section is helpful, but without going and reading
> the LDN spec, I'm not clear on why a POST would be sent "with
> authorization of the submitting user". I haven't got to the Auth section
> yet, so I'll assume the scenario is something to do with passing through
> some not-secret auth token, though don't know what purpose this would serve.

Yes... I think that the spec was previously "too tied" to LDN, in that a
person might feel that they don't really understand ActivityPub because
now they need to read another spec.  But I really like that there's
overlap.

So, I've revised it; I think it's clearer now, explaining the
relationship between this and LDN, but removing any requirement for
needing to read LDN to understand ActivityPub.

> 8.2.2 Inbox Delivery
> --------------------
> "The values of to, cc and/or bcc contain a Collection owned by the
> server" - should this be "an individual or Collection"?

No, it's a collection specifically... this is you about forwarding my
reply to say, your "followers" collection when I reply to your original
message..  This section needs an example, which I'll add, but since it's
non-normative it can wait till after CR.

> 8.6 Remove Activity
> -------------------
> "not allowed to be added" - should be "not allowed to be removed"

Oops, you're right!  Fixed it.

> 9.2 Linked Data Signatures and HTTP Signatures
> ----------------------------------------------
> "When Linked Data Signatures in combined" - should be "are combined".

Updated the grammar.

> Misc
> ----
> I wouldn't mind seeing an example of the message flow for the full
> federated process: client sends to home server, home server sends to
> destination server.

Yeah, I've opened an issue to add a nice example in the overview, maybe
with diagrams.  Again, something that can happen after CR.

> This is probably part of LDN, but do messages only ever take one server
> to server hop? It would me reading this to perhaps mention similarities
> and differences to how email works.

I'm not sure what you mean?  When messages are just delivered on-server
to the same server?  Or something about them being forwarded...?

Jan Kusanagi

Jan Kusanagi writes the Pump.IO client Dianara, and submitted this feedback over IRC (which was incorporated).

<jankusanagi_> ah paroneayea, I saw a couple of redundancies, like in one
               place which said something like "in the future, in case blah
               blah, in the future"                                     [16:58]
<jankusanagi_> are you interested in things like that too?              [16:59]
<paroneayea> jankusanagi_: yes!
<jankusanagi_> ok, will report those then =)
<jankusanagi_> but if memory serves, you can search for the string "in the
               future" to find that specific case :D                    [17:00]
<jankusanagi_> "handling verification become available in the future, servers
               are welcome to use those methods, in the future.)"       [17:02]
<jankusanagi_> section 3. Objects
<jankusanagi_> just before the example