In addition to the conversations here, @devnull and I have been working on NodeBB <> Discourse integration via chat, and I’m going to describe some of the issues we addressed there. These are not necessarily contentious issues from a normative perspective, but since we faced them as new implementers, other new implementors in this space may also face them, so it’s worth recording them here.
Implicit Creates
Essentially this is where a Note (or Article) is sent to your inbox without an associated CRUD Activity. This can happen in a few forms:
Note. Attributed to an Actor.
Announce > Note. Announce Actor may be different from attributed to Actor.
In both cases, the Create activity is implicit. The “explicit” version of both would be:
Create > Note. Create Actor should be the same as the attributed to Actor.
Announce > Create > Note. Announce Actor may be different from the Create and attributed to Actor.
I’m not sure it’s correct to call Announce Create Note as more “explicit” than Announce Note. Semantically they mean slightly different things. This is one of the quirks of 1b12 using Announce to wrap activities instead of objects, or instead of relying on inbox forwarding (which, to be fair, inbox forwarding doesn’t play well with HTTP signatures unless you have a way to replay an entire HTTP POST call).
Announce means you are drawing attention to something
Announce’s side effect is to add the current activity to the object.shares collection
Announce Note is the “typical” way of using the Announce activity. It is semantically equivalent to a reshare, retweet, repost, boost, etc. Browsing the shares collection shows you all the Announce activities where Announce.object is the current object.
Announcing activities is the 1b12 way of using the Announce activity. It is semantically equivalent to letting someone know that some activity took place. In this case, the expectation is that you unwrap the Announce.object and process it as an activity. This means you have to normalize the “bare” object from the “typical” case into an activity, and then process the side effects. So a non-activity would be assumed to be Created, I guess.
I think I understand what you mean. Let’s play this out with an example.
You receive a Create with Note A. Both have the same Actor, Actor A.
Subsequently you receive an Announce of Note A from Actor B.
Since you have already created Note A, the subsequent Announce is not an implicit Create, but simply an Announce (or boost / share) by Actor B. So in other words, the “implicit create” scenario is just a subset of the scenarios that Announce > Note may contain.
Yeah, I am using “explicit” in a looser way perhaps, insofar as within that scenario where Announce > Note is also creating the Note, Announce > Create > Note is more explicit than just Announce > Note. But I take your point.
Yeah, that example would be correct. The core of the issue is that you don’t necessarily have a complete view of the world and its history of actions/activities. So if you see an object that wasn’t created… yes it was, you just didn’t see the Create. It isn’t limited to Announce, either. You may receive a Like of an object that you never received a Create for. Or an Add. Or so on.
Is it possible that you are mixing C2S and S2S here? Submitting a Note without an activity is only specified for the C2S outbox (AP 6.2.1) rather than for an S2S federated inbox.
The use of “create” is not clear to me here. Neither the S2S Create(Note) nor Announce(Note) activities instruct the receiver to create a Note. They are notifications, not commands. Sure, a typical implementation will locally cache the remote content for performance reasons, but that’s an implementation detail. An implementation could also dereference the object URI for either activity on-demand.
The way ActivitPub uses the Activity Streams 2.0 activities in C2S and S2S can be confusing, in my opinion. There’s little difference between an S2S Create(Note) and an Announce(Note). They both are notifications to draw attention to the activity’s object. One would expect Create(Note) to only be attributed to the Note author (although that’s not explicitly required), but the Announce(Note) could be associated with any actor (including the author). It seems to me that an Announce(Note) where the activity actor is the Note’s attributedTo actor is effectively the same as a Create(Note).
@stevebate Yup, I don’t disagree with anything you’re saying.
To be clear, the focus here is one of practical implementation. I’m not attempting to give a description of the normative state of the standard. This is more a reflection of the kind of things you’re thinking about when implementing the standard.
In other words, yes, normatively speaking a Create is a notification of sorts, not a command. Nevertheless, what you do with a Create activity as an implementor, is typically, to, well, create something. I’m not trying to describe a normative concept of “implicit creates”, rather I’m trying to think through the typical cases in which you might infer a Create activity.
But thanks for the corrective / clarification, it’s useful
Got it. Yeah, I think all S2S inbox activities imply an object was created at some point in the past (other than Create, which is an explicit notification). IIUC, that’s what @trwnh was saying too.
Some activities refer to objects that will (typically) never have an associated Create activity, like Follow(Person), where you wouldn’t expect to see a Create(Person).