Re: API thoughts

Sorry, this is going to be long.

On Wed, Jan 28, 2015 at 6:07 PM, Sandro Hawke <sandro@w3.org> wrote:
[snip]
>
> I agree this model is quite accurate, and elegant.   My only concern is that
> it may be still be too complicated for end-users.  I don't really think most
> folks will understand the idea of "Persona", and if they misunderstand it
> even a little, they could easily have some nasty surprises.   I don't think
> I've seen it in a mass-market UI.
>
[snip]

Indeed. So working down from where we started, we seem to be in
agreement that while the Identity concept exists, it's too high level.
The Persona concept is where we want to focus, only let's call it
"Account" instead. And instead of talking about an Identity with
multiple Persona's, we're talking about "Linked Accounts". This
accurately reflects what I see in implementations so as far as that is
concerned, we're good so far.

So bringing it back to the Social API... given an Account identifier,
the API needs to be able to tell us what it knows about the Account.
This can include: (a) the Account Profile, (b) the Social Artifacts
owned by the Account, and (c) Linked Accounts.

[snip]
>
> The full model is:
>
> Agent: an abstract concept - I just prefer this term, but I think it's
> similar to James' Identity - for organisations, groups, bots, etc as well as
> people; specifically some entity with agency that can be tracked to the
> 'real world'.
> Persona: also an abstract concept - some version or subset of an Agent (not
> a subclass).
>

Fortunately we already have a term for this in Activity Streams 2.0:
The Actor. The Actor can be a person, it can also be an application,
or a device, or a process, or a group, etc. These are the things that
Do Stuff within the context of our Social API. When we talk about
"@type": "Person" in an Activity stream, we're effectively talking
about a Person as represented by an Account.

I think we are fairly well in agreement on this even if we differ on
relatively minor details such as what exact we want to call these
objects. Let's use the Activity Streams 2.0 terminology for now.

So I have an Actor. The Actor is the thing that does stuff. The Actor
can also own stuff. The stuff that Actor owns we'll call "Social
Artifacts". What are the Social Artifacts we care about and what are
the things we can do with them?

The vocabulary here
(http://jasnell.github.io/w3c-socialwg-activitystreams/activitystreams2-vocabulary.html)
already defines a broad range of Social Artifacts that we can see
implemented in a wide range of existing, real world social platform
implementations. The vocabulary also describes Collections of social
artifacts (things like Album, Folder, etc). These Collections are
themselves types of Social Artifacts. So rather than talking about
specific kinds of Artifacts (because there are so many), let's talk in
more general terms.

What do our Actor's need to be able to do with their Artifacts. Well,
let's start with the basics: they need to be able to Create them,
Update them, Delete them. They need to be able to organize them into
Collections. This ought to be straightforward enough.

Let's assume we have an account identifier. I know it makes some
people's skin crawl, but let's assume the account identifier is
something that looks like an email address: acct:jasnell@us.ibm.com. I
want to find out everything I can find out about this identifier.
Let's call this, Step 1:

Step 1: For the sake of the discussion, Step 1 will use WebFinger. I'd
send a GET request to
http://us.ibm.com/.well-known/webfinger?resource=acct:jasnell@us.ibm.com
and would get back a JSON document with links to other resources
associated with the account identifier. Those other resources might
represent my Profile, or Collections of Social Artifacts to which the
account identifier is associated.

One I have this listing of other things associated with this account
identifier, I need to pick one that I'm interested in. Let's assume
that what I want is profile information that describes the identified
account. I would look for the profile resource, follow my nose to find
a URL, then I'd move on to Step 2:

Step 2: Send a GET request to the profile URL and retrieve a profile document.

I've achieved my goal. I have the profile. All that was required from
a "Social API" point of view is two HTTP GET requests, one using
conventions defined by the WebFinger spec, and the other using nothing
more than a simple HTTP GET.

Let's do something else now, following Step 1, suppose that I am the
owner of the identified account and what I want to do is make it so
that an application on my phone can automatically start backing up
photos into a Collection of my choosing. I would need to look at the
results of the WebFinger request to see if I can find something that
looks like a Collection to which I could upload photos. How exactly do
I identify such a thing? Let's say by some bit of magic I find a
Collection to upload to, I pass the URL for that Collection on to my
application. When it starts to upload photos, it essentially starts
sending HTTP POST requests to the server, working through the list of
photos to send. Here, again, we have a simple WebFinger request
followed by one or more fairly simple HTTP POST requests.

Later on I want to view that album so I can show off all the pictures
to my friends. That's just a GET request. It can return an Activity
Streams 2.0 collection or an HTML page. Easy.

Let's say I want to delete a photo. I send a DELETE request to the
photo URL. Done. Ditto on updating the photo.

What should be obvious at this point is that these are all problems
we've dealt with and have solutions for. There's not a lot we need to
define. We ought to just pick one of the existing solutions that are
already available (pick one: Atompub, OpenSocial API, Linked Data
Platform, etc) The critical aspect is not really HOW we perform these
operations but how we discover WHERE to perform them. So that initial
Step 1 is very important. Is WebFinger the thing we want to use there?
I'm not convinced it is although some may argue that it's fine.

So that covers artifact CRUD. Let's talk about Artifact Actions... or
the things we can DO with an Artifact separately from just managing
their lifecycle. The Activity Streams vocabulary already includes a
broad range of Actions (or what we call Activities). Let's pick a few:
Like, Share, and Save.

For any given Social Artifact (regardless of what kind of artifact it
is) I need to be able to ask and have answered: What can I do with
this thing? And once I know what I can do with it, *how* do I go about
doing that thing. That's where things like Action Handlers come into
play (http://jasnell.github.io/w3c-socialwg-activitystreams/activitystreams2-actions.html).
The Action Handlers vocabulary allows us to explicitly say, "With this
Note object, you can Like it, Share it, or Save it, and here's how you
do each"... For instance:

{
  "@type": "Note",
  "content": "This is a note",
  "action": [
    {
      "@type": "Like",
      "using": {
        "@type": "EmbeddedView",
        "mediaType": "text/html",
        "content": "<div class='like-button'>...</div>"
      }
  ]
}

We can represent a similar structure in HTML using
Microdata/RDFa/Microformats. The point is not the specific format used
but the fact that the Actions... the list of things we can DO with the
object... travel along with the object itself. Not only that, there's
a description of HOW we do those things included as well. Once again,
as with the CRUD examples above, we can follow our nose and get to the
right place. We can define the "how" part in generic terms and allow
implementations to fill in the details. For instance, "implement this
action using an HTTP Request with the following parameters", or
"implement this action by displaying this snippet of HTML" or
"implement this action by showing this html page in a new browser
view". The point is, there's very little API specification that needs
to be done here... implementations just follow their nose once they
know where to begin.

The TL/DR version is this:

1. The Social API needs an initial Discovery step that takes, as
input, the identifier for some kind of thing, whether it's an Actor or
an Artifact and outputs some listing of information answering the
question "What is this and what can we do with it?"

2. The Social API needs a mechanism that allows an Actor to create,
update and organize Social Artifacts.

3. The Social API needs a mechanism for attaching potential actions to
an artifact.

For #1, we can start with WebFinger but I'd rather see if we can do
better for that initial step.
For #2, let's identify some combination of HTTP GET, PUT, POST, DELETE
and PATCH that will work.
For #3, let's get the Actions piece done.

For #2, let's start with something like this:

Return a Collection:
  GET /:collection
  Accept: <text/html or application/activity+json>

Add to a Collection
  POST /:collection
  Content-Type: <any>

  201 Created
  Location: /:collection/:resource

Remove from a Collection
  DELETE /:collection/:resource

Update resource within a collection:
  PUT /:collection/:resource

Get the resource within the collection:
  GET /:collection/:resource

- James

Received on Thursday, 29 January 2015 03:42:48 UTC